summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libeffects/factory/Android.mk25
-rw-r--r--media/libeffects/factory/EffectsFactory.c647
-rw-r--r--media/libeffects/factory/EffectsFactory.h56
-rw-r--r--media/libeffects/lvm/lib/Android.mk124
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/lib/LVDBE.h472
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h518
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Control.c379
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Init.c267
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Private.h148
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Process.c205
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c463
-rwxr-xr-xmedia/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h93
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/lib/LVM.h637
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c158
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c878
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h573
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Control.c1033
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Init.c1003
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Private.h292
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Process.c283
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Tables.c397
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Tables.h67
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/AGC.h92
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/BIQUAD.h341
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/CompLim.h91
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/Filter.h71
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/InstAlloc.h99
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/LVM_Common.h69
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/LVM_Macros.h130
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/LVM_Timer.h89
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/LVM_Types.h195
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/Mixer.h135
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h68
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/lib/VectorArithmetic.h189
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c204
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Abs_32.c58
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c64
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c69
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c90
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c59
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h38
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c92
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c69
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h38
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c90
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c60
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h38
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c94
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c66
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h38
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c93
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h38
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c67
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c123
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c123
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c67
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h40
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c127
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c126
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c126
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h40
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c67
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c135
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c66
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h41
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/CompLim_private.h52
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Copy_16.c66
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c69
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c103
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c112
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c76
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c36
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h43
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c113
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/DelayMix_16x16.c81
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/DelayWrite_32.c66
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c83
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c63
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h40
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c83
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c66
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h41
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c137
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c65
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h41
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Filters.h74
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c65
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/From2iToMono_16.c57
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/From2iToMono_32.c58
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/InstAlloc.c194
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c56
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c68
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c63
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c77
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c67
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c136
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c151
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c114
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c120
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c160
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c119
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c78
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer.h144
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c50
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c51
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c76
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h136
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c75
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c84
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c104
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c109
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c106
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_GetOmega.c79
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h100
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c165
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Polynomial.c105
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Power10.c87
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Timer.c57
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c63
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h61
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LoadConst_16.c51
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/LoadConst_32.c52
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c88
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c81
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c80
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c104
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c104
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c74
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Mixer_private.h44
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/MonoTo2I_16.c57
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/MonoTo2I_32.c58
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Mult3s_32x16.c60
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/NonLinComp_D16.c125
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c130
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c128
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c47
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h40
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c46
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h41
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c89
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c92
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/dB_to_Lin32.c109
-rwxr-xr-xmedia/libeffects/lvm/lib/Common/src/mult3s_16x16.c56
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/lib/LVEQNB.h484
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c306
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h106
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c501
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c329
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h141
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c208
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c203
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h298
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c715
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c197
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c177
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h159
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c260
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h98
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c50
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c220
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c250
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/lib/LVCS.h396
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c301
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h89
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c264
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c168
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h66
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h398
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c220
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h172
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c271
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c272
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h98
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c268
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h88
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c456
-rwxr-xr-xmedia/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h159
-rw-r--r--media/libeffects/lvm/wrapper/Android.mk36
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp2909
-rw-r--r--media/libeffects/lvm/wrapper/Bundle/EffectBundle.h181
-rw-r--r--media/libeffects/testlibs/Android.mk_66
-rw-r--r--media/libeffects/testlibs/AudioBiquadFilter.cpp260
-rw-r--r--media/libeffects/testlibs/AudioBiquadFilter.h180
-rw-r--r--media/libeffects/testlibs/AudioCoefInterpolator.cpp84
-rw-r--r--media/libeffects/testlibs/AudioCoefInterpolator.h98
-rw-r--r--media/libeffects/testlibs/AudioCommon.h92
-rw-r--r--media/libeffects/testlibs/AudioEqualizer.cpp315
-rw-r--r--media/libeffects/testlibs/AudioEqualizer.h246
-rw-r--r--media/libeffects/testlibs/AudioFormatAdapter.h184
-rw-r--r--media/libeffects/testlibs/AudioHighShelfFilterCoef.inl225
-rw-r--r--media/libeffects/testlibs/AudioLowShelfFilterCoef.inl375
-rw-r--r--media/libeffects/testlibs/AudioPeakingFilter.cpp121
-rw-r--r--media/libeffects/testlibs/AudioPeakingFilter.h151
-rw-r--r--media/libeffects/testlibs/AudioPeakingFilterCoef.inl2700
-rw-r--r--media/libeffects/testlibs/AudioShelvingFilter.cpp109
-rw-r--r--media/libeffects/testlibs/AudioShelvingFilter.h146
-rw-r--r--media/libeffects/testlibs/EffectEqualizer.cpp654
-rw-r--r--media/libeffects/testlibs/EffectReverb.c2135
-rw-r--r--media/libeffects/testlibs/EffectReverb.h448
-rw-r--r--media/libeffects/testlibs/EffectsMath.c143
-rw-r--r--media/libeffects/testlibs/EffectsMath.h424
-rw-r--r--media/libeffects/visualizer/Android.mk30
-rw-r--r--media/libeffects/visualizer/EffectVisualizer.cpp401
-rw-r--r--media/libmedia/Android.mk7
-rw-r--r--media/libmedia/AudioEffect.cpp462
-rw-r--r--media/libmedia/AudioRecord.cpp92
-rw-r--r--media/libmedia/AudioSystem.cpp50
-rw-r--r--media/libmedia/AudioTrack.cpp283
-rw-r--r--media/libmedia/IAudioFlinger.cpp281
-rw-r--r--media/libmedia/IAudioPolicyService.cpp148
-rw-r--r--media/libmedia/IAudioTrack.cpp24
-rw-r--r--media/libmedia/IEffect.cpp195
-rw-r--r--media/libmedia/IEffectClient.cpp145
-rw-r--r--media/libmedia/IMediaPlayer.cpp30
-rw-r--r--media/libmedia/IMediaPlayerService.cpp36
-rw-r--r--media/libmedia/IMediaRecorder.cpp8
-rw-r--r--media/libmedia/IMediaRecorderClient.cpp70
-rw-r--r--media/libmedia/IOMX.cpp2
-rw-r--r--media/libmedia/MediaProfiles.cpp81
-rw-r--r--media/libmedia/MediaScanner.cpp4
-rw-r--r--media/libmedia/Visualizer.cpp330
-rw-r--r--media/libmedia/mediaplayer.cpp109
-rw-r--r--media/libmediaplayerservice/Android.mk17
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp298
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h24
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.cpp11
-rw-r--r--media/libmediaplayerservice/MediaRecorderClient.h21
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp18
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp999
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h70
-rw-r--r--media/libmediaplayerservice/VorbisMetadataRetriever.cpp87
-rw-r--r--media/libmediaplayerservice/VorbisMetadataRetriever.h49
-rw-r--r--media/libmediaplayerservice/VorbisPlayer.cpp529
-rw-r--r--media/libmediaplayerservice/VorbisPlayer.h94
-rw-r--r--media/libstagefright/AMRExtractor.cpp3
-rw-r--r--media/libstagefright/AMRWriter.cpp121
-rw-r--r--media/libstagefright/Android.mk107
-rw-r--r--media/libstagefright/AudioPlayer.cpp66
-rw-r--r--media/libstagefright/AudioSource.cpp158
-rw-r--r--media/libstagefright/AwesomePlayer.cpp251
-rw-r--r--media/libstagefright/CachingDataSource.cpp165
-rw-r--r--media/libstagefright/CameraSource.cpp323
-rw-r--r--media/libstagefright/DataSource.cpp15
-rw-r--r--media/libstagefright/FileSource.cpp8
-rw-r--r--media/libstagefright/HTTPDataSource.cpp457
-rw-r--r--media/libstagefright/JPEGSource.cpp3
-rw-r--r--media/libstagefright/MP3Extractor.cpp8
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp161
-rw-r--r--media/libstagefright/MPEG4Writer.cpp1352
-rw-r--r--media/libstagefright/MediaDefs.cpp3
-rw-r--r--media/libstagefright/MediaExtractor.cpp7
-rw-r--r--media/libstagefright/MediaSource.cpp24
-rw-r--r--media/libstagefright/NuCachedSource2.cpp471
-rw-r--r--media/libstagefright/NuHTTPDataSource.cpp338
-rw-r--r--media/libstagefright/OMXCodec.cpp698
-rw-r--r--media/libstagefright/OggExtractor.cpp280
-rw-r--r--media/libstagefright/Prefetcher.cpp476
-rw-r--r--media/libstagefright/SampleTable.cpp154
-rw-r--r--media/libstagefright/ShoutcastSource.cpp3
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp53
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp18
-rw-r--r--media/libstagefright/ThrottledSource.cpp84
-rw-r--r--media/libstagefright/WAVExtractor.cpp3
-rw-r--r--media/libstagefright/codecs/aacdec/AACDecoder.cpp113
-rw-r--r--media/libstagefright/codecs/aacenc/AACEncoder.cpp299
-rw-r--r--media/libstagefright/codecs/aacenc/Android.mk87
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c283
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/Android.mk24
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile55
-rw-r--r--media/libstagefright/codecs/aacenc/SampleCode/ms.mk23
-rw-r--r--media/libstagefright/codecs/aacenc/Tools/doit.mk133
-rw-r--r--media/libstagefright/codecs/aacenc/Tools/eclair.mk172
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/basic_op.h1166
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/basicop2.c1624
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/oper_32b.c361
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/oper_32b.h89
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/typedef.h63
-rw-r--r--media/libstagefright/codecs/aacenc/basic_op/typedefs.h179
-rw-r--r--media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile55
-rw-r--r--media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile55
-rw-r--r--media/libstagefright/codecs/aacenc/build/eclair/makefile40
-rw-r--r--media/libstagefright/codecs/aacenc/build/ms.mk42
-rw-r--r--media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdfbin0 -> 160899 bytes
-rw-r--r--media/libstagefright/codecs/aacenc/inc/aac_rom.h117
-rw-r--r--media/libstagefright/codecs/aacenc/inc/aacenc_core.h117
-rw-r--r--media/libstagefright/codecs/aacenc/inc/adj_thr.h57
-rw-r--r--media/libstagefright/codecs/aacenc/inc/adj_thr_data.h69
-rw-r--r--media/libstagefright/codecs/aacenc/inc/band_nrg.h46
-rw-r--r--media/libstagefright/codecs/aacenc/inc/bit_cnt.h106
-rw-r--r--media/libstagefright/codecs/aacenc/inc/bitbuffer.h89
-rw-r--r--media/libstagefright/codecs/aacenc/inc/bitenc.h50
-rw-r--r--media/libstagefright/codecs/aacenc/inc/block_switch.h72
-rw-r--r--media/libstagefright/codecs/aacenc/inc/channel_map.h37
-rw-r--r--media/libstagefright/codecs/aacenc/inc/config.h36
-rw-r--r--media/libstagefright/codecs/aacenc/inc/dyn_bits.h82
-rw-r--r--media/libstagefright/codecs/aacenc/inc/grp_data.h44
-rw-r--r--media/libstagefright/codecs/aacenc/inc/interface.h106
-rw-r--r--media/libstagefright/codecs/aacenc/inc/line_pe.h75
-rw-r--r--media/libstagefright/codecs/aacenc/inc/memalign.h35
-rw-r--r--media/libstagefright/codecs/aacenc/inc/ms_stereo.h45
-rw-r--r--media/libstagefright/codecs/aacenc/inc/pre_echo_control.h42
-rw-r--r--media/libstagefright/codecs/aacenc/inc/psy_configuration.h107
-rw-r--r--media/libstagefright/codecs/aacenc/inc/psy_const.h80
-rw-r--r--media/libstagefright/codecs/aacenc/inc/psy_data.h66
-rw-r--r--media/libstagefright/codecs/aacenc/inc/psy_main.h69
-rw-r--r--media/libstagefright/codecs/aacenc/inc/qc_data.h143
-rw-r--r--media/libstagefright/codecs/aacenc/inc/qc_main.h64
-rw-r--r--media/libstagefright/codecs/aacenc/inc/quantize.h42
-rw-r--r--media/libstagefright/codecs/aacenc/inc/sf_estim.h46
-rw-r--r--media/libstagefright/codecs/aacenc/inc/spreading.h33
-rw-r--r--media/libstagefright/codecs/aacenc/inc/stat_bits.h34
-rw-r--r--media/libstagefright/codecs/aacenc/inc/tns.h108
-rw-r--r--media/libstagefright/codecs/aacenc/inc/tns_func.h75
-rw-r--r--media/libstagefright/codecs/aacenc/inc/tns_param.h52
-rw-r--r--media/libstagefright/codecs/aacenc/inc/transform.h36
-rw-r--r--media/libstagefright/codecs/aacenc/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/aacenc/src/aac_rom.c2363
-rw-r--r--media/libstagefright/codecs/aacenc/src/aacenc.c495
-rw-r--r--media/libstagefright/codecs/aacenc/src/aacenc_core.c239
-rw-r--r--media/libstagefright/codecs/aacenc/src/adj_thr.c1223
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s167
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s112
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s131
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s252
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s169
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s204
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s135
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s146
-rw-r--r--media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s143
-rw-r--r--media/libstagefright/codecs/aacenc/src/band_nrg.c102
-rw-r--r--media/libstagefright/codecs/aacenc/src/bit_cnt.c885
-rw-r--r--media/libstagefright/codecs/aacenc/src/bitbuffer.c172
-rw-r--r--media/libstagefright/codecs/aacenc/src/bitenc.c690
-rw-r--r--media/libstagefright/codecs/aacenc/src/block_switch.c431
-rw-r--r--media/libstagefright/codecs/aacenc/src/channel_map.c123
-rw-r--r--media/libstagefright/codecs/aacenc/src/dyn_bits.c545
-rw-r--r--media/libstagefright/codecs/aacenc/src/grp_data.c188
-rw-r--r--media/libstagefright/codecs/aacenc/src/interface.c112
-rw-r--r--media/libstagefright/codecs/aacenc/src/line_pe.c145
-rw-r--r--media/libstagefright/codecs/aacenc/src/memalign.c107
-rw-r--r--media/libstagefright/codecs/aacenc/src/ms_stereo.c139
-rw-r--r--media/libstagefright/codecs/aacenc/src/pre_echo_control.c113
-rw-r--r--media/libstagefright/codecs/aacenc/src/psy_configuration.c505
-rw-r--r--media/libstagefright/codecs/aacenc/src/psy_main.c810
-rw-r--r--media/libstagefright/codecs/aacenc/src/qc_main.c580
-rw-r--r--media/libstagefright/codecs/aacenc/src/quantize.c445
-rw-r--r--media/libstagefright/codecs/aacenc/src/sf_estim.c882
-rw-r--r--media/libstagefright/codecs/aacenc/src/spreading.c52
-rw-r--r--media/libstagefright/codecs/aacenc/src/stat_bits.c237
-rw-r--r--media/libstagefright/codecs/aacenc/src/tns.c932
-rw-r--r--media/libstagefright/codecs/aacenc/src/transform.c672
-rw-r--r--media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp3
-rw-r--r--media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp38
-rw-r--r--media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp3
-rw-r--r--media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp288
-rw-r--r--media/libstagefright/codecs/amrwbenc/Android.mk120
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c364
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk27
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile56
-rw-r--r--media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk24
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile53
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile53
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/makefile39
-rw-r--r--media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk43
-rw-r--r--media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdfbin0 -> 156892 bytes
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/acelp.h521
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/basic_op.h1094
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/bits.h92
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/cnst.h81
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/cod_main.h103
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/dtx.h115
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/grid100.tab53
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab73
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/homing.tab123
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab62
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab81
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/log2.h62
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/log2_tab.h35
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/main.h45
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/math_op.h55
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/mem_align.h35
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/mime_io.tab368
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/oper_32b.h31
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/p_med_o.h52
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab47
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab228
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/q_pulse.h66
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab347
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab1360
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/stream.h47
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/typedef.h65
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/typedefs.h211
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/wb_vad.h78
-rw-r--r--media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h109
-rw-r--r--media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt9
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s104
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s80
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s185
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s231
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s226
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s186
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s151
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s460
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s228
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s75
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s238
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s102
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s127
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s228
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s270
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s133
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s178
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s151
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s100
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s127
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s138
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s106
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/autocorr.c127
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/az_isp.c268
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/bits.c210
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/c2t64fx.c297
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/c4t64fx.c1043
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/cmnMemory.c73
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/convolve.c109
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/cor_h_x.c127
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/decim54.c146
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/deemph.c117
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/dtx.c605
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/g_pitch.c79
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/gpclip.c110
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/homing.c46
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/hp400.c106
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/hp50.c106
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/hp6k.c93
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/hp_wsp.c148
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/int_lpc.c66
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/isp_az.c247
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/isp_isf.c91
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/lag_wind.c49
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/levinson.c250
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/log2.c111
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/lp_dec2.c70
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/math_op.c219
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/mem_align.c107
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/oper_32b.c223
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/p_med_ol.c256
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/pit_shrp.c49
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/pitch_f4.c324
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/pred_lt4.c120
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/preemph.c88
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/q_gain2.c346
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/q_pulse.c400
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/qisf_ns.c111
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c542
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/random.c33
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/residu.c67
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/scale.c57
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/stream.c58
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/syn_filt.c160
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/updt_tar.c49
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/util.c74
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c1941
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/voicefac.c92
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/wb_vad.c808
-rw-r--r--media/libstagefright/codecs/amrwbenc/src/weight_a.c48
-rw-r--r--media/libstagefright/codecs/avc/dec/AVCDecoder.cpp205
-rw-r--r--media/libstagefright/codecs/avc/enc/AVCEncoder.cpp492
-rw-r--r--media/libstagefright/codecs/avc/enc/Android.mk35
-rw-r--r--media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp744
-rw-r--r--media/libstagefright/codecs/avc/enc/src/avcenc_api.h323
-rw-r--r--media/libstagefright/codecs/avc/enc/src/avcenc_int.h471
-rw-r--r--media/libstagefright/codecs/avc/enc/src/avcenc_lib.h1020
-rw-r--r--media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp336
-rw-r--r--media/libstagefright/codecs/avc/enc/src/block.cpp1283
-rw-r--r--media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp622
-rw-r--r--media/libstagefright/codecs/avc/enc/src/header.cpp917
-rw-r--r--media/libstagefright/codecs/avc/enc/src/init.cpp899
-rw-r--r--media/libstagefright/codecs/avc/enc/src/intra_est.cpp2199
-rw-r--r--media/libstagefright/codecs/avc/enc/src/motion_comp.cpp2156
-rw-r--r--media/libstagefright/codecs/avc/enc/src/motion_est.cpp1774
-rw-r--r--media/libstagefright/codecs/avc/enc/src/rate_control.cpp981
-rw-r--r--media/libstagefright/codecs/avc/enc/src/residual.cpp389
-rw-r--r--media/libstagefright/codecs/avc/enc/src/sad.cpp290
-rw-r--r--media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp629
-rw-r--r--media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h96
-rw-r--r--media/libstagefright/codecs/avc/enc/src/sad_inline.h488
-rw-r--r--media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h311
-rw-r--r--media/libstagefright/codecs/avc/enc/src/slice.cpp1025
-rw-r--r--media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp336
-rw-r--r--media/libstagefright/codecs/common/Android.mk33
-rw-r--r--media/libstagefright/codecs/common/Config.mk24
-rw-r--r--media/libstagefright/codecs/common/cmnMemory.c73
-rw-r--r--media/libstagefright/codecs/common/include/cmnMemory.h106
-rw-r--r--media/libstagefright/codecs/common/include/voAAC.h74
-rw-r--r--media/libstagefright/codecs/common/include/voAMRWB.h87
-rw-r--r--media/libstagefright/codecs/common/include/voAudio.h173
-rw-r--r--media/libstagefright/codecs/common/include/voIndex.h193
-rw-r--r--media/libstagefright/codecs/common/include/voMem.h65
-rw-r--r--media/libstagefright/codecs/common/include/voType.h221
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp52
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/Android.mk37
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp358
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/include/cvei.h437
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h454
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp859
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h57
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp693
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp482
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp1283
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/dct.h191
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h395
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp622
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h103
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp2020
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp967
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h625
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp287
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h43
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp386
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp1965
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp1741
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h229
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp3278
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h207
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h472
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp885
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h96
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp375
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp855
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h130
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h539
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h317
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h1146
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp2799
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h42
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h316
-rw-r--r--media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp581
-rw-r--r--media/libstagefright/codecs/mp3dec/MP3Decoder.cpp60
-rw-r--r--media/libstagefright/codecs/on2/Android.mk4
-rw-r--r--media/libstagefright/codecs/on2/dec/Android.mk16
-rw-r--r--media/libstagefright/codecs/on2/dec/VPXDecoder.cpp273
-rw-r--r--media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp3
-rw-r--r--media/libstagefright/colorconversion/ColorConverter.cpp68
-rw-r--r--media/libstagefright/foundation/AAtomizer.cpp67
-rw-r--r--media/libstagefright/foundation/ABuffer.cpp76
-rw-r--r--media/libstagefright/foundation/ADebug.cpp76
-rw-r--r--media/libstagefright/foundation/AHandler.cpp33
-rw-r--r--media/libstagefright/foundation/ALooper.cpp198
-rw-r--r--media/libstagefright/foundation/ALooperRoster.cpp144
-rw-r--r--media/libstagefright/foundation/AMessage.cpp344
-rw-r--r--media/libstagefright/foundation/AString.cpp331
-rw-r--r--media/libstagefright/foundation/Android.mk36
-rw-r--r--media/libstagefright/foundation/base64.cpp139
-rw-r--r--media/libstagefright/foundation/hexdump.cpp73
-rw-r--r--media/libstagefright/httplive/Android.mk20
-rw-r--r--media/libstagefright/httplive/LiveSource.cpp188
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp231
-rw-r--r--media/libstagefright/id3/Android.mk4
-rw-r--r--media/libstagefright/include/AACDecoder.h4
-rw-r--r--media/libstagefright/include/AACEncoder.h81
-rw-r--r--media/libstagefright/include/AMRNBEncoder.h4
-rw-r--r--media/libstagefright/include/AMRWBEncoder.h72
-rw-r--r--media/libstagefright/include/ARTSPController.h53
-rw-r--r--media/libstagefright/include/AVCDecoder.h3
-rw-r--r--media/libstagefright/include/AVCEncoder.h90
-rw-r--r--media/libstagefright/include/AwesomePlayer.h20
-rw-r--r--media/libstagefright/include/LiveSource.h69
-rw-r--r--media/libstagefright/include/M3UParser.h71
-rw-r--r--media/libstagefright/include/M4vH263Decoder.h1
-rw-r--r--media/libstagefright/include/M4vH263Encoder.h80
-rw-r--r--media/libstagefright/include/MP3Decoder.h7
-rw-r--r--media/libstagefright/include/MPEG2TSExtractor.h54
-rw-r--r--media/libstagefright/include/NuCachedSource2.h98
-rw-r--r--media/libstagefright/include/NuHTTPDataSource.h73
-rw-r--r--media/libstagefright/include/OMX.h11
-rw-r--r--media/libstagefright/include/Prefetcher.h70
-rw-r--r--media/libstagefright/include/SampleTable.h13
-rw-r--r--media/libstagefright/include/ThrottledSource.h52
-rw-r--r--media/libstagefright/include/VPXDecoder.h62
-rw-r--r--media/libstagefright/matroska/Android.mk16
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.cpp595
-rw-r--r--media/libstagefright/matroska/MatroskaExtractor.h76
-rw-r--r--media/libstagefright/matroska/mkvparser.cpp3103
-rw-r--r--media/libstagefright/matroska/mkvparser.hpp428
-rw-r--r--media/libstagefright/mpeg2ts/ABitReader.cpp98
-rw-r--r--media/libstagefright/mpeg2ts/ABitReader.h53
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp941
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.h68
-rw-r--r--media/libstagefright/mpeg2ts/Android.mk22
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp112
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.h62
-rw-r--r--media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp197
-rw-r--r--media/libstagefright/omx/OMX.cpp36
-rw-r--r--media/libstagefright/omx/OMXMaster.cpp4
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp6
-rw-r--r--media/libstagefright/omx/tests/Android.mk6
-rw-r--r--media/libstagefright/rtsp/AAVCAssembler.cpp385
-rw-r--r--media/libstagefright/rtsp/AAVCAssembler.h61
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp171
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.h56
-rw-r--r--media/libstagefright/rtsp/APacketSource.cpp345
-rw-r--r--media/libstagefright/rtsp/APacketSource.h61
-rw-r--r--media/libstagefright/rtsp/ARTPAssembler.cpp78
-rw-r--r--media/libstagefright/rtsp/ARTPAssembler.h56
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.cpp499
-rw-r--r--media/libstagefright/rtsp/ARTPConnection.h83
-rw-r--r--media/libstagefright/rtsp/ARTPSource.cpp250
-rw-r--r--media/libstagefright/rtsp/ARTPSource.h67
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.cpp549
-rw-r--r--media/libstagefright/rtsp/ARTSPConnection.h97
-rw-r--r--media/libstagefright/rtsp/ARTSPController.cpp78
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.cpp270
-rw-r--r--media/libstagefright/rtsp/ASessionDescription.h75
-rw-r--r--media/libstagefright/rtsp/Android.mk28
-rw-r--r--media/libstagefright/rtsp/MyHandler.h465
-rw-r--r--media/libstagefright/rtsp/MyTransmitter.h981
-rw-r--r--media/libstagefright/rtsp/VideoSource.h98
617 files changed, 149728 insertions, 3480 deletions
diff --git a/media/libeffects/factory/Android.mk b/media/libeffects/factory/Android.mk
new file mode 100644
index 0000000..20f58e5
--- /dev/null
+++ b/media/libeffects/factory/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Effect factory library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectsFactory.c
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_MODULE:= libeffects
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/factory/EffectsFactory.c b/media/libeffects/factory/EffectsFactory.c
new file mode 100644
index 0000000..c19a505
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.c
@@ -0,0 +1,647 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectsFactory"
+//#define LOG_NDEBUG 0
+
+#include "EffectsFactory.h"
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+
+static list_elem_t *gEffectList; // list of effect_entry_t: all currently created effects
+static list_elem_t *gLibraryList; // list of lib_entry_t: all currently loaded libraries
+static pthread_mutex_t gLibLock = PTHREAD_MUTEX_INITIALIZER; // controls access to gLibraryList
+static uint32_t gNumEffects; // total number number of effects
+static list_elem_t *gCurLib; // current library in enumeration process
+static list_elem_t *gCurEffect; // current effect in enumeration process
+static uint32_t gCurEffectIdx; // current effect index in enumeration process
+
+const char * const gEffectLibPath = "/system/lib/soundfx"; // path to built-in effect libraries
+static int gInitDone; // true is global initialization has been preformed
+static int gNextLibId; // used by loadLibrary() to allocate unique library handles
+static int gCanQueryEffect; // indicates that call to EffectQueryEffect() is valid, i.e. that the list of effects
+ // was not modified since last call to EffectQueryNumberEffects()
+
+/////////////////////////////////////////////////
+// Local functions prototypes
+/////////////////////////////////////////////////
+
+static int init();
+static int loadLibrary(const char *libPath, int *handle);
+static int unloadLibrary(int handle);
+static void resetEffectEnumeration();
+static uint32_t updateNumEffects();
+static int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc);
+static void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len);
+
+/////////////////////////////////////////////////
+// Effect Control Interface functions
+/////////////////////////////////////////////////
+
+int Effect_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ effect_entry_t *fx = (effect_entry_t *)self;
+ pthread_mutex_lock(&gLibLock);
+ if (fx->lib == NULL) {
+ pthread_mutex_unlock(&gLibLock);
+ return -EPIPE;
+ }
+ pthread_mutex_lock(&fx->lib->lock);
+ pthread_mutex_unlock(&gLibLock);
+
+ ret = (*fx->subItfe)->process(fx->subItfe, inBuffer, outBuffer);
+ pthread_mutex_unlock(&fx->lib->lock);
+ return ret;
+}
+
+int Effect_Command(effect_interface_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ effect_entry_t *fx = (effect_entry_t *)self;
+ pthread_mutex_lock(&gLibLock);
+ if (fx->lib == NULL) {
+ pthread_mutex_unlock(&gLibLock);
+ return -EPIPE;
+ }
+ pthread_mutex_lock(&fx->lib->lock);
+ pthread_mutex_unlock(&gLibLock);
+
+ ret = (*fx->subItfe)->command(fx->subItfe, cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ pthread_mutex_unlock(&fx->lib->lock);
+ return ret;
+}
+
+const struct effect_interface_s gInterface = {
+ Effect_Process,
+ Effect_Command
+};
+
+/////////////////////////////////////////////////
+// Effect Factory Interface functions
+/////////////////////////////////////////////////
+
+int EffectQueryNumberEffects(uint32_t *pNumEffects)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ if (pNumEffects == NULL) {
+ return -EINVAL;
+ }
+
+ pthread_mutex_lock(&gLibLock);
+ *pNumEffects = gNumEffects;
+ gCanQueryEffect = 1;
+ pthread_mutex_unlock(&gLibLock);
+ LOGV("EffectQueryNumberEffects(): %d", *pNumEffects);
+ return ret;
+}
+
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ if (pDescriptor == NULL ||
+ index >= gNumEffects) {
+ return -EINVAL;
+ }
+ if (gCanQueryEffect == 0) {
+ return -ENOSYS;
+ }
+
+ pthread_mutex_lock(&gLibLock);
+ ret = -ENOENT;
+ if (index < gCurEffectIdx) {
+ resetEffectEnumeration();
+ }
+ while (gCurLib) {
+ if (gCurEffect) {
+ if (index == gCurEffectIdx) {
+ memcpy(pDescriptor, gCurEffect->object, sizeof(effect_descriptor_t));
+ ret = 0;
+ break;
+ } else {
+ gCurEffect = gCurEffect->next;
+ gCurEffectIdx++;
+ }
+ } else {
+ gCurLib = gCurLib->next;
+ gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+ }
+ }
+
+#if (LOG_NDEBUG == 0)
+ char str[256];
+ dumpEffectDescriptor(pDescriptor, str, 256);
+ LOGV("EffectQueryEffect() desc:%s", str);
+#endif
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectGetDescriptor(effect_uuid_t *uuid, effect_descriptor_t *pDescriptor)
+{
+ lib_entry_t *l = NULL;
+ effect_descriptor_t *d = NULL;
+
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ if (pDescriptor == NULL || uuid == NULL) {
+ return -EINVAL;
+ }
+ pthread_mutex_lock(&gLibLock);
+ ret = findEffect(uuid, &l, &d);
+ if (ret == 0) {
+ memcpy(pDescriptor, d, sizeof(effect_descriptor_t));
+ }
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectCreate(effect_uuid_t *uuid, int32_t sessionId, int32_t ioId, effect_interface_t *pInterface)
+{
+ list_elem_t *e = gLibraryList;
+ lib_entry_t *l = NULL;
+ effect_descriptor_t *d = NULL;
+ effect_interface_t itfe;
+ effect_entry_t *fx;
+ int found = 0;
+ int ret;
+
+ if (uuid == NULL || pInterface == NULL) {
+ return -EINVAL;
+ }
+
+ LOGV("EffectCreate() UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+ uuid->timeLow, uuid->timeMid, uuid->timeHiAndVersion,
+ uuid->clockSeq, uuid->node[0], uuid->node[1],uuid->node[2],
+ uuid->node[3],uuid->node[4],uuid->node[5]);
+
+ ret = init();
+
+ if (ret < 0) {
+ LOGW("EffectCreate() init error: %d", ret);
+ return ret;
+ }
+
+ pthread_mutex_lock(&gLibLock);
+
+ ret = findEffect(uuid, &l, &d);
+ if (ret < 0){
+ goto exit;
+ }
+
+ // create effect in library
+ ret = l->createFx(uuid, sessionId, ioId, &itfe);
+ if (ret != 0) {
+ LOGW("EffectCreate() library %s: could not create fx %s, error %d", l->path, d->name, ret);
+ goto exit;
+ }
+
+ // add entry to effect list
+ fx = (effect_entry_t *)malloc(sizeof(effect_entry_t));
+ fx->subItfe = itfe;
+ fx->itfe = (struct effect_interface_s *)&gInterface;
+ fx->lib = l;
+
+ e = (list_elem_t *)malloc(sizeof(list_elem_t));
+ e->object = fx;
+ e->next = gEffectList;
+ gEffectList = e;
+
+ *pInterface = (effect_interface_t)fx;
+
+ LOGV("EffectCreate() created entry %p with sub itfe %p in library %s", *pInterface, itfe, l->path);
+
+exit:
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectRelease(effect_interface_t interface)
+{
+ effect_entry_t *fx;
+ list_elem_t *e1;
+ list_elem_t *e2;
+
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+
+ // remove effect from effect list
+ pthread_mutex_lock(&gLibLock);
+ e1 = gEffectList;
+ e2 = NULL;
+ while (e1) {
+ if (e1->object == interface) {
+ if (e2) {
+ e2->next = e1->next;
+ } else {
+ gEffectList = e1->next;
+ }
+ fx = (effect_entry_t *)e1->object;
+ free(e1);
+ break;
+ }
+ e2 = e1;
+ e1 = e1->next;
+ }
+ if (e1 == NULL) {
+ ret = -ENOENT;
+ goto exit;
+ }
+
+ // release effect in library
+ if (fx->lib == NULL) {
+ LOGW("EffectRelease() fx %p library already unloaded", interface);
+ } else {
+ pthread_mutex_lock(&fx->lib->lock);
+ fx->lib->releaseFx(fx->subItfe);
+ pthread_mutex_unlock(&fx->lib->lock);
+ }
+ free(fx);
+
+exit:
+ pthread_mutex_unlock(&gLibLock);
+ return ret;
+}
+
+int EffectLoadLibrary(const char *libPath, int *handle)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+ if (libPath == NULL) {
+ return -EINVAL;
+ }
+
+ ret = loadLibrary(libPath, handle);
+ updateNumEffects();
+ return ret;
+}
+
+int EffectUnloadLibrary(int handle)
+{
+ int ret = init();
+ if (ret < 0) {
+ return ret;
+ }
+
+ ret = unloadLibrary(handle);
+ updateNumEffects();
+ return ret;
+}
+
+int EffectIsNullUuid(effect_uuid_t *uuid)
+{
+ if (memcmp(uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t))) {
+ return 0;
+ }
+ return 1;
+}
+
+/////////////////////////////////////////////////
+// Local functions
+/////////////////////////////////////////////////
+
+int init() {
+ struct dirent *ent;
+ DIR *dir = NULL;
+ char libpath[PATH_MAX];
+ int hdl;
+
+ if (gInitDone) {
+ return 0;
+ }
+
+ pthread_mutex_init(&gLibLock, NULL);
+
+ // load built-in libraries
+ dir = opendir(gEffectLibPath);
+ if (dir == NULL) {
+ return -ENODEV;
+ }
+ while ((ent = readdir(dir)) != NULL) {
+ LOGV("init() reading file %s", ent->d_name);
+ if ((strlen(ent->d_name) < 3) ||
+ strncmp(ent->d_name, "lib", 3) != 0 ||
+ strncmp(ent->d_name + strlen(ent->d_name) - 3, ".so", 3) != 0) {
+ continue;
+ }
+ strcpy(libpath, gEffectLibPath);
+ strcat(libpath, "/");
+ strcat(libpath, ent->d_name);
+ if (loadLibrary(libpath, &hdl) < 0) {
+ LOGW("init() failed to load library %s",libpath);
+ }
+ }
+ closedir(dir);
+ updateNumEffects();
+ gInitDone = 1;
+ LOGV("init() done");
+ return 0;
+}
+
+
+int loadLibrary(const char *libPath, int *handle)
+{
+ void *hdl;
+ effect_QueryNumberEffects_t queryNumFx;
+ effect_QueryEffect_t queryFx;
+ effect_CreateEffect_t createFx;
+ effect_ReleaseEffect_t releaseFx;
+ uint32_t numFx;
+ uint32_t fx;
+ int ret;
+ list_elem_t *e, *descHead = NULL;
+ lib_entry_t *l;
+
+ if (handle == NULL) {
+ return -EINVAL;
+ }
+
+ *handle = 0;
+
+ hdl = dlopen(libPath, RTLD_NOW);
+ if (hdl == 0) {
+ LOGW("could open lib %s", libPath);
+ return -ENODEV;
+ }
+
+ // Check functions availability
+ queryNumFx = (effect_QueryNumberEffects_t)dlsym(hdl, "EffectQueryNumberEffects");
+ if (queryNumFx == NULL) {
+ LOGW("could not get EffectQueryNumberEffects from lib %s", libPath);
+ ret = -ENODEV;
+ goto error;
+ }
+ queryFx = (effect_QueryEffect_t)dlsym(hdl, "EffectQueryEffect");
+ if (queryFx == NULL) {
+ LOGW("could not get EffectQueryEffect from lib %s", libPath);
+ ret = -ENODEV;
+ goto error;
+ }
+ createFx = (effect_CreateEffect_t)dlsym(hdl, "EffectCreate");
+ if (createFx == NULL) {
+ LOGW("could not get EffectCreate from lib %s", libPath);
+ ret = -ENODEV;
+ goto error;
+ }
+ releaseFx = (effect_ReleaseEffect_t)dlsym(hdl, "EffectRelease");
+ if (releaseFx == NULL) {
+ LOGW("could not get EffectRelease from lib %s", libPath);
+ ret = -ENODEV;
+ goto error;
+ }
+
+ // load effect descriptors
+ ret = queryNumFx(&numFx);
+ if (ret) {
+ goto error;
+ }
+
+ for (fx = 0; fx < numFx; fx++) {
+ effect_descriptor_t *d = malloc(sizeof(effect_descriptor_t));
+ if (d == NULL) {
+ ret = -ENOMEM;
+ goto error;
+ }
+ ret = queryFx(fx, d);
+ if (ret == 0) {
+#if (LOG_NDEBUG==0)
+ char s[256];
+ dumpEffectDescriptor(d, s, 256);
+ LOGV("loadLibrary() read descriptor %p:%s",d, s);
+#endif
+ if (d->apiVersion != EFFECT_API_VERSION) {
+ LOGW("Bad API version %04x on lib %s", d->apiVersion, libPath);
+ free(d);
+ continue;
+ }
+ e = malloc(sizeof(list_elem_t));
+ if (e == NULL) {
+ free(d);
+ ret = -ENOMEM;
+ goto error;
+ }
+ e->object = d;
+ e->next = descHead;
+ descHead = e;
+ } else {
+ LOGW("Error querying effect # %d on lib %s", fx, libPath);
+ }
+ }
+
+ pthread_mutex_lock(&gLibLock);
+
+ // add entry for library in gLibraryList
+ l = malloc(sizeof(lib_entry_t));
+ l->id = ++gNextLibId;
+ l->handle = hdl;
+ strncpy(l->path, libPath, PATH_MAX);
+ l->createFx = createFx;
+ l->releaseFx = releaseFx;
+ l->effects = descHead;
+ pthread_mutex_init(&l->lock, NULL);
+
+ e = malloc(sizeof(list_elem_t));
+ e->next = gLibraryList;
+ e->object = l;
+ gLibraryList = e;
+ pthread_mutex_unlock(&gLibLock);
+ LOGV("loadLibrary() linked library %p", l);
+
+ *handle = l->id;
+
+ return 0;
+
+error:
+ LOGW("loadLibrary() error: %d on lib: %s", ret, libPath);
+ while (descHead) {
+ free(descHead->object);
+ e = descHead->next;
+ free(descHead);
+ descHead = e;;
+ }
+ dlclose(hdl);
+ return ret;
+}
+
+int unloadLibrary(int handle)
+{
+ void *hdl;
+ int ret;
+ list_elem_t *el1, *el2;
+ lib_entry_t *l;
+ effect_entry_t *fx;
+
+ pthread_mutex_lock(&gLibLock);
+ el1 = gLibraryList;
+ el2 = NULL;
+ while (el1) {
+ l = (lib_entry_t *)el1->object;
+ if (handle == l->id) {
+ if (el2) {
+ el2->next = el1->next;
+ } else {
+ gLibraryList = el1->next;
+ }
+ free(el1);
+ break;
+ }
+ el2 = el1;
+ el1 = el1->next;
+ }
+ pthread_mutex_unlock(&gLibLock);
+ if (el1 == NULL) {
+ return -ENOENT;
+ }
+
+ // clear effect descriptor list
+ el1 = l->effects;
+ while (el1) {
+ free(el1->object);
+ el2 = el1->next;
+ free(el1);
+ el1 = el2;
+ }
+
+ // disable all effects from this library
+ pthread_mutex_lock(&l->lock);
+
+ el1 = gEffectList;
+ while (el1) {
+ fx = (effect_entry_t *)el1->object;
+ if (fx->lib == l) {
+ fx->lib = NULL;
+ }
+ el1 = el1->next;
+ }
+ pthread_mutex_unlock(&l->lock);
+
+ dlclose(l->handle);
+ free(l);
+ return 0;
+}
+
+void resetEffectEnumeration()
+{
+ gCurLib = gLibraryList;
+ gCurEffect = NULL;
+ if (gCurLib) {
+ gCurEffect = ((lib_entry_t *)gCurLib->object)->effects;
+ }
+ gCurEffectIdx = 0;
+}
+
+uint32_t updateNumEffects() {
+ list_elem_t *e;
+ uint32_t cnt = 0;
+
+ resetEffectEnumeration();
+
+ e = gLibraryList;
+ while (e) {
+ lib_entry_t *l = (lib_entry_t *)e->object;
+ list_elem_t *efx = l->effects;
+ while (efx) {
+ cnt++;
+ efx = efx->next;
+ }
+ e = e->next;
+ }
+ gNumEffects = cnt;
+ gCanQueryEffect = 0;
+ return cnt;
+}
+
+int findEffect(effect_uuid_t *uuid, lib_entry_t **lib, effect_descriptor_t **desc)
+{
+ list_elem_t *e = gLibraryList;
+ lib_entry_t *l = NULL;
+ effect_descriptor_t *d = NULL;
+ int found = 0;
+ int ret = 0;
+
+ while (e && !found) {
+ l = (lib_entry_t *)e->object;
+ list_elem_t *efx = l->effects;
+ while (efx) {
+ d = (effect_descriptor_t *)efx->object;
+ if (memcmp(&d->uuid, uuid, sizeof(effect_uuid_t)) == 0) {
+ found = 1;
+ break;
+ }
+ efx = efx->next;
+ }
+ e = e->next;
+ }
+ if (!found) {
+ LOGV("findEffect() effect not found");
+ ret = -ENOENT;
+ } else {
+ LOGV("findEffect() found effect: %s in lib %s", d->name, l->path);
+ *lib = l;
+ *desc = d;
+ }
+
+ return ret;
+}
+
+void dumpEffectDescriptor(effect_descriptor_t *desc, char *str, size_t len) {
+ char s[256];
+
+ snprintf(str, len, "\nEffect Descriptor %p:\n", desc);
+ sprintf(s, "- UUID: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+ desc->uuid.timeLow, desc->uuid.timeMid, desc->uuid.timeHiAndVersion,
+ desc->uuid.clockSeq, desc->uuid.node[0], desc->uuid.node[1],desc->uuid.node[2],
+ desc->uuid.node[3],desc->uuid.node[4],desc->uuid.node[5]);
+ strncat(str, s, len);
+ sprintf(s, "- TYPE: %08X-%04X-%04X-%04X-%02X%02X%02X%02X%02X%02X\n",
+ desc->type.timeLow, desc->type.timeMid, desc->type.timeHiAndVersion,
+ desc->type.clockSeq, desc->type.node[0], desc->type.node[1],desc->type.node[2],
+ desc->type.node[3],desc->type.node[4],desc->type.node[5]);
+ strncat(str, s, len);
+ sprintf(s, "- apiVersion: %04X\n- flags: %08X\n",
+ desc->apiVersion, desc->flags);
+ strncat(str, s, len);
+ sprintf(s, "- name: %s\n", desc->name);
+ strncat(str, s, len);
+ sprintf(s, "- implementor: %s\n", desc->implementor);
+ strncat(str, s, len);
+}
+
diff --git a/media/libeffects/factory/EffectsFactory.h b/media/libeffects/factory/EffectsFactory.h
new file mode 100644
index 0000000..8f543ca
--- /dev/null
+++ b/media/libeffects/factory/EffectsFactory.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTSFACTORY_H_
+#define ANDROID_EFFECTSFACTORY_H_
+
+#include <cutils/log.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <media/EffectsFactoryApi.h>
+
+
+#if __cplusplus
+extern "C" {
+#endif
+
+typedef struct list_elem_s {
+ void *object;
+ struct list_elem_s *next;
+} list_elem_t;
+
+typedef struct lib_entry_s {
+ char path[PATH_MAX];
+ void *handle;
+ int id;
+ effect_CreateEffect_t createFx;
+ effect_ReleaseEffect_t releaseFx;
+ list_elem_t *effects; //list of effect_descriptor_t
+ pthread_mutex_t lock;
+} lib_entry_t;
+
+typedef struct effect_entry_s {
+ struct effect_interface_s *itfe;
+ effect_interface_t subItfe;
+ lib_entry_t *lib;
+} effect_entry_t;
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTSFACTORY_H_*/
diff --git a/media/libeffects/lvm/lib/Android.mk b/media/libeffects/lvm/lib/Android.mk
new file mode 100644
index 0000000..a944212
--- /dev/null
+++ b/media/libeffects/lvm/lib/Android.mk
@@ -0,0 +1,124 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Music bundle
+
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+ StereoWidening/src/LVCS_BypassMix.c \
+ StereoWidening/src/LVCS_Control.c \
+ StereoWidening/src/LVCS_Equaliser.c \
+ StereoWidening/src/LVCS_Init.c \
+ StereoWidening/src/LVCS_Process.c \
+ StereoWidening/src/LVCS_ReverbGenerator.c \
+ StereoWidening/src/LVCS_StereoEnhancer.c \
+ StereoWidening/src/LVCS_Tables.c \
+ Bass/src/LVDBE_Control.c \
+ Bass/src/LVDBE_Init.c \
+ Bass/src/LVDBE_Process.c \
+ Bass/src/LVDBE_Tables.c \
+ Bundle/src/LVM_API_Specials.c \
+ Bundle/src/LVM_Buffers.c \
+ Bundle/src/LVM_Init.c \
+ Bundle/src/LVM_Process.c \
+ Bundle/src/LVM_Tables.c \
+ Bundle/src/LVM_Control.c \
+ SpectrumAnalyzer/src/LVPSA_Control.c \
+ SpectrumAnalyzer/src/LVPSA_Init.c \
+ SpectrumAnalyzer/src/LVPSA_Memory.c \
+ SpectrumAnalyzer/src/LVPSA_Process.c \
+ SpectrumAnalyzer/src/LVPSA_QPD_Init.c \
+ SpectrumAnalyzer/src/LVPSA_QPD_Process.c \
+ SpectrumAnalyzer/src/LVPSA_Tables.c \
+ Eq/src/LVEQNB_CalcCoef.c \
+ Eq/src/LVEQNB_Control.c \
+ Eq/src/LVEQNB_Init.c \
+ Eq/src/LVEQNB_Process.c \
+ Eq/src/LVEQNB_Tables.c \
+ Common/src/InstAlloc.c \
+ Common/src/DC_2I_D16_TRC_WRA_01.c \
+ Common/src/DC_2I_D16_TRC_WRA_01_Init.c \
+ Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c \
+ Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c \
+ Common/src/FO_1I_D16F16C15_TRC_WRA_01.c \
+ Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c \
+ Common/src/BP_1I_D16F32C30_TRC_WRA_01.c \
+ Common/src/BP_1I_D16F16C14_TRC_WRA_01.c \
+ Common/src/BP_1I_D32F32C30_TRC_WRA_02.c \
+ Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c \
+ Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c \
+ Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c \
+ Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c \
+ Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c \
+ Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c \
+ Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c \
+ Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c \
+ Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c \
+ Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c \
+ Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c \
+ Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c \
+ Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c \
+ Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c \
+ Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c \
+ Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c \
+ Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c \
+ Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c \
+ Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c \
+ Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c \
+ Common/src/Int16LShiftToInt32_16x32.c \
+ Common/src/From2iToMono_16.c \
+ Common/src/Copy_16.c \
+ Common/src/MonoTo2I_16.c \
+ Common/src/LoadConst_16.c \
+ Common/src/dB_to_Lin32.c \
+ Common/src/Shift_Sat_v16xv16.c \
+ Common/src/Abs_32.c \
+ Common/src/Int32RShiftToInt16_Sat_32x16.c \
+ Common/src/From2iToMono_32.c \
+ Common/src/mult3s_16x16.c \
+ Common/src/NonLinComp_D16.c \
+ Common/src/DelayMix_16x16.c \
+ Common/src/MSTo2i_Sat_16x16.c \
+ Common/src/From2iToMS_16x16.c \
+ Common/src/Mac3s_Sat_16x16.c \
+ Common/src/Add2_Sat_16x16.c \
+ Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c \
+ Common/src/LVC_MixSoft_1St_D16C31_SAT.c \
+ Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c \
+ Common/src/LVC_Mixer_SetTimeConstant.c \
+ Common/src/LVC_Mixer_SetTarget.c \
+ Common/src/LVC_Mixer_GetTarget.c \
+ Common/src/LVC_Mixer_Init.c \
+ Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c \
+ Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c \
+ Common/src/LVC_Core_MixInSoft_D16C31_SAT.c \
+ Common/src/LVC_Mixer_GetCurrent.c \
+ Common/src/LVC_MixSoft_2St_D16C31_SAT.c \
+ Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c \
+ Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c \
+ Common/src/LVC_MixInSoft_D16C31_SAT.c \
+ Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c \
+ Common/src/LVM_Timer.c \
+ Common/src/LVM_Timer_Init.c
+
+LOCAL_MODULE:= libmusicbundle
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Eq/lib \
+ $(LOCAL_PATH)/Eq/src \
+ $(LOCAL_PATH)/Bass/lib \
+ $(LOCAL_PATH)/Bass/src \
+ $(LOCAL_PATH)/Common/lib \
+ $(LOCAL_PATH)/Common/src \
+ $(LOCAL_PATH)/Bundle/lib \
+ $(LOCAL_PATH)/Bundle/src \
+ $(LOCAL_PATH)/SpectrumAnalyzer/lib \
+ $(LOCAL_PATH)/SpectrumAnalyzer/src \
+ $(LOCAL_PATH)/StereoWidening/src \
+ $(LOCAL_PATH)/StereoWidening/lib
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
new file mode 100755
index 0000000..48731df
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -0,0 +1,472 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1081 $
+ $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the application layer interface of Dynamic Bass Enhancement */
+/* module. */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the calling layer. All other types, structures and */
+/* functions are private. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 1 */
+/* ======= */
+/* The algorithm can execute either with separate input and output buffers or with */
+/* a common buffer, i.e. the data is processed in-place. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 2 */
+/* ======= */
+/* The Dynamic Bass Enhancement algorithm always processes data as stereo input. Mono*/
+/* format data is not supported. The data is interleaved as follows: */
+/* */
+/* Byte Offset Stereo Input Mono-In-Stereo Input */
+/* =========== ============ ==================== */
+/* 0 Left Sample #1 Mono Sample #1 */
+/* 2 Right Sample #1 Mono Sample #1 */
+/* 4 Left Sample #2 Mono Sample #2 */
+/* 6 Right Sample #2 Mono Sample #2 */
+/* . . . */
+/* . . . */
+/* */
+/* Mono format data is not supported, the calling routine must convert a Mono stream */
+/* in to Mono-In-Stereo format. */
+/* */
+/****************************************************************************************/
+
+#ifndef __LVDBE_H__
+#define __LVDBE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+
+/* Memory table*/
+#define LVDBE_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+/* Bass Enhancement effect level */
+#define LVDBE_EFFECT_03DB 3 /* Effect defines for backwards compatibility */
+#define LVDBE_EFFECT_06DB 6
+#define LVDBE_EFFECT_09DB 9
+#define LVDBE_EFFECT_12DB 12
+#define LVDBE_EFFECT_15DB 15
+
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVDBE_Handle_t;
+
+
+/* Operating modes */
+typedef enum
+{
+ LVDBE_OFF = 0,
+ LVDBE_ON = 1,
+ LVDBE_MODE_MAX = LVM_MAXINT_32
+} LVDBE_Mode_en;
+
+
+/* High pass filter */
+typedef enum
+{
+ LVDBE_HPF_OFF = 0,
+ LVDBE_HPF_ON = 1,
+ LVDBE_HPF_MAX = LVM_MAXINT_32
+} LVDBE_FilterSelect_en;
+
+
+/* Volume control */
+typedef enum
+{
+ LVDBE_VOLUME_OFF = 0,
+ LVDBE_VOLUME_ON = 1,
+ LVDBE_VOLUME_MAX = LVM_MAXINT_32
+} LVDBE_Volume_en;
+
+
+/* Memory Types */
+typedef enum
+{
+ LVDBE_PERSISTENT = 0,
+ LVDBE_PERSISTENT_DATA = 1,
+ LVDBE_PERSISTENT_COEF = 2,
+ LVDBE_SCRATCH = 3,
+ LVDBE_MEMORY_MAX = LVM_MAXINT_32
+
+} LVDBE_MemoryTypes_en;
+
+
+/* Function return status */
+typedef enum
+{
+ LVDBE_SUCCESS = 0, /* Successful return from a routine */
+ LVDBE_ALIGNMENTERROR = 1, /* Memory alignment error */
+ LVDBE_NULLADDRESS = 2, /* NULL allocation address */
+ LVDBE_TOOMANYSAMPLES = 3, /* Maximum block size exceeded */
+ LVDBE_SIZEERROR = 4, /* Incorrect structure size */
+ LVDBE_STATUS_MAX = LVM_MAXINT_32
+} LVDBE_ReturnStatus_en;
+
+
+/****************************************************************************************/
+/* */
+/* Linked enumerated type and capability definitions */
+/* */
+/* The capability definitions are used to define the required capabilities at */
+/* initialisation, these are added together to give the capability word. The */
+/* enumerated type is used to select the mode through a control function at run time. */
+/* */
+/* The capability definition is related to the enumerated type value by the equation: */
+/* */
+/* Capability_value = 2^Enumerated_value */
+/* */
+/* For example, a module could be configurd at initialisation to support two sample */
+/* rates only by calling the init function with the value: */
+/* Capabilities.SampleRate = LVDBE_CAP_32000 + LVCS_DBE_44100; */
+/* */
+/* and at run time it would be passed the value LVDBE_FS_32000 through the control */
+/* function to select operation at 32kHz */
+/* */
+/****************************************************************************************/
+
+/*
+ * Bass Enhancement centre frequency
+ */
+#define LVDBE_CAP_CENTRE_55Hz 1
+#define LVDBE_CAP_CENTRE_66Hz 2
+#define LVDBE_CAP_CENTRE_78Hz 4
+#define LVDBE_CAP_CENTRE_90Hz 8
+
+typedef enum
+{
+ LVDBE_CENTRE_55HZ = 0,
+ LVDBE_CENTRE_66HZ = 1,
+ LVDBE_CENTRE_78HZ = 2,
+ LVDBE_CENTRE_90HZ = 3,
+ LVDBE_CENTRE_MAX = LVM_MAXINT_32
+} LVDBE_CentreFreq_en;
+
+
+/*
+ * Supported sample rates in samples per second
+ */
+#define LVDBE_CAP_FS_8000 1
+#define LVDBE_CAP_FS_11025 2
+#define LVDBE_CAP_FS_12000 4
+#define LVDBE_CAP_FS_16000 8
+#define LVDBE_CAP_FS_22050 16
+#define LVDBE_CAP_FS_24000 32
+#define LVDBE_CAP_FS_32000 64
+#define LVDBE_CAP_FS_44100 128
+#define LVDBE_CAP_FS_48000 256
+
+typedef enum
+{
+ LVDBE_FS_8000 = 0,
+ LVDBE_FS_11025 = 1,
+ LVDBE_FS_12000 = 2,
+ LVDBE_FS_16000 = 3,
+ LVDBE_FS_22050 = 4,
+ LVDBE_FS_24000 = 5,
+ LVDBE_FS_32000 = 6,
+ LVDBE_FS_44100 = 7,
+ LVDBE_FS_48000 = 8,
+ LVDBE_FS_MAX = LVM_MAXINT_32
+} LVDBE_Fs_en;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+ LVM_UINT32 Size; /* Region size in bytes */
+ LVM_UINT16 Alignment; /* Region alignment in bytes */
+ LVDBE_MemoryTypes_en Type; /* Region type */
+ void *pBaseAddress; /* Pointer to the region base address */
+} LVDBE_MemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVDBE_MemoryRegion_t Region[LVDBE_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVDBE_MemTab_t;
+
+
+/* Parameter structure */
+typedef struct
+{
+ LVDBE_Mode_en OperatingMode;
+ LVDBE_Fs_en SampleRate;
+ LVM_INT16 EffectLevel;
+ LVDBE_CentreFreq_en CentreFrequency;
+ LVDBE_FilterSelect_en HPFSelect;
+ LVDBE_Volume_en VolumeControl;
+ LVM_INT16 VolumedB;
+ LVM_INT16 HeadroomdB;
+
+} LVDBE_Params_t;
+
+
+/* Capability structure */
+typedef struct
+{
+ LVM_UINT16 SampleRate; /* Sampling rate capabilities */
+ LVM_UINT16 CentreFrequency; /* Centre frequency capabilities */
+ LVM_UINT16 MaxBlockSize; /* Maximum block size in sample pairs */
+} LVDBE_Capabilities_t;
+
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the default capabilites */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t hInstance,
+ LVDBE_MemTab_t *pMemoryTable,
+ LVDBE_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Init */
+/* */
+/* DESCRIPTION: */
+/* Create and initialisation function for the Bass Enhancement module */
+/* */
+/* This function can be used to create an algorithm instance by calling with */
+/* hInstance set to NULL. In this case the algorithm returns the new instance */
+/* handle. */
+/* */
+/* This function can be used to force a full re-initialisation of the algorithm */
+/* by calling with hInstance = Instance Handle. In this case the memory table */
+/* should be correct for the instance, this can be ensured by calling the function */
+/* LVDBE_Memory before calling this function. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pCapabilities Pointer to the initialisation capabilities */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Initialisation succeeded */
+/* LVDBE_ALIGNMENTERROR Instance or scratch memory on incorrect alignment */
+/* LVDBE_NULLADDRESS One or more memory has a NULL pointer */
+/* */
+/* NOTES: */
+/* 1. The instance handle is the pointer to the base address of the first memory */
+/* region. */
+/* 2. This function must not be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance,
+ LVDBE_MemTab_t *pMemoryTable,
+ LVDBE_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_GetParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the Bass Enhancement parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t hInstance,
+ LVDBE_Params_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_GetCapabilities */
+/* */
+/* DESCRIPTION: */
+/* Request the Dynamic Bass Enhancement capabilities. The initial capabilities are */
+/* returned via the pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pCapabilities Pointer to an empty capabilitiy structure */
+/* */
+/* RETURNS: */
+/* LVDBE_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,
+ LVDBE_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Control */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the Bass Enhancement parameters. Changing the parameters while the */
+/* module is processing signals may have the following side effects: */
+/* */
+/* General parameters: */
+/* =================== */
+/* OperatingMode: Changing the mode of operation may cause a change in volume */
+/* level. */
+/* */
+/* SampleRate: Changing the sample rate may cause pops and clicks. */
+/* */
+/* EffectLevel: Changing the effect level setting will have no side effects */
+/* */
+/* CentreFrequency: Changing the centre frequency may cause pops and clicks */
+/* */
+/* HPFSelect: Selecting/de-selecting the high pass filter may cause pops and */
+/* clicks */
+/* */
+/* VolumedB Changing the volume setting will have no side effects */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance,
+ LVDBE_Params_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the Bass Enhancement module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Succeeded */
+/* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVDBE_H__ */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
new file mode 100755
index 0000000..94a7869
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Coeffs.h
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LVDBE_COEFFS_H__
+#define __LVDBE_COEFFS_H__
+
+
+/************************************************************************************/
+/* */
+/* General */
+/* */
+/************************************************************************************/
+
+#define LVDBE_SCALESHIFT 10 /* As a power of 2 */
+
+
+/************************************************************************************/
+/* */
+/* High Pass Filter coefficients */
+/* */
+/************************************************************************************/
+
+ /* Coefficients for centre frequency 55Hz */
+#define HPF_Fs8000_Fc55_A0 1029556328 /* Floating point value 0.958849 */
+#define HPF_Fs8000_Fc55_A1 -2059112655 /* Floating point value -1.917698 */
+#define HPF_Fs8000_Fc55_A2 1029556328 /* Floating point value 0.958849 */
+#define HPF_Fs8000_Fc55_B1 -2081986375 /* Floating point value -1.939001 */
+#define HPF_Fs8000_Fc55_B2 1010183914 /* Floating point value 0.940807 */
+#define HPF_Fs11025_Fc55_A0 1038210831 /* Floating point value 0.966909 */
+#define HPF_Fs11025_Fc55_A1 -2076421662 /* Floating point value -1.933818 */
+#define HPF_Fs11025_Fc55_A2 1038210831 /* Floating point value 0.966909 */
+#define HPF_Fs11025_Fc55_B1 -2099950710 /* Floating point value -1.955732 */
+#define HPF_Fs11025_Fc55_B2 1027238450 /* Floating point value 0.956690 */
+#define HPF_Fs12000_Fc55_A0 1040079943 /* Floating point value 0.968650 */
+#define HPF_Fs12000_Fc55_A1 -2080159885 /* Floating point value -1.937300 */
+#define HPF_Fs12000_Fc55_A2 1040079943 /* Floating point value 0.968650 */
+#define HPF_Fs12000_Fc55_B1 -2103811702 /* Floating point value -1.959327 */
+#define HPF_Fs12000_Fc55_B2 1030940477 /* Floating point value 0.960138 */
+#define HPF_Fs16000_Fc55_A0 1045381988 /* Floating point value 0.973588 */
+#define HPF_Fs16000_Fc55_A1 -2090763976 /* Floating point value -1.947176 */
+#define HPF_Fs16000_Fc55_A2 1045381988 /* Floating point value 0.973588 */
+#define HPF_Fs16000_Fc55_B1 -2114727793 /* Floating point value -1.969494 */
+#define HPF_Fs16000_Fc55_B2 1041478147 /* Floating point value 0.969952 */
+#define HPF_Fs22050_Fc55_A0 1049766523 /* Floating point value 0.977671 */
+#define HPF_Fs22050_Fc55_A1 -2099533046 /* Floating point value -1.955343 */
+#define HPF_Fs22050_Fc55_A2 1049766523 /* Floating point value 0.977671 */
+#define HPF_Fs22050_Fc55_B1 -2123714381 /* Floating point value -1.977863 */
+#define HPF_Fs22050_Fc55_B2 1050232780 /* Floating point value 0.978105 */
+#define HPF_Fs24000_Fc55_A0 1050711051 /* Floating point value 0.978551 */
+#define HPF_Fs24000_Fc55_A1 -2101422103 /* Floating point value -1.957102 */
+#define HPF_Fs24000_Fc55_A2 1050711051 /* Floating point value 0.978551 */
+#define HPF_Fs24000_Fc55_B1 -2125645498 /* Floating point value -1.979662 */
+#define HPF_Fs24000_Fc55_B2 1052123526 /* Floating point value 0.979866 */
+#define HPF_Fs32000_Fc55_A0 1053385759 /* Floating point value 0.981042 */
+#define HPF_Fs32000_Fc55_A1 -2106771519 /* Floating point value -1.962084 */
+#define HPF_Fs32000_Fc55_A2 1053385759 /* Floating point value 0.981042 */
+#define HPF_Fs32000_Fc55_B1 -2131104794 /* Floating point value -1.984746 */
+#define HPF_Fs32000_Fc55_B2 1057486949 /* Floating point value 0.984861 */
+#define HPF_Fs44100_Fc55_A0 1055592498 /* Floating point value 0.983097 */
+#define HPF_Fs44100_Fc55_A1 -2111184995 /* Floating point value -1.966194 */
+#define HPF_Fs44100_Fc55_A2 1055592498 /* Floating point value 0.983097 */
+#define HPF_Fs44100_Fc55_B1 -2135598658 /* Floating point value -1.988931 */
+#define HPF_Fs44100_Fc55_B2 1061922249 /* Floating point value 0.988992 */
+#define HPF_Fs48000_Fc55_A0 1056067276 /* Floating point value 0.983539 */
+#define HPF_Fs48000_Fc55_A1 -2112134551 /* Floating point value -1.967079 */
+#define HPF_Fs48000_Fc55_A2 1056067276 /* Floating point value 0.983539 */
+#define HPF_Fs48000_Fc55_B1 -2136564296 /* Floating point value -1.989831 */
+#define HPF_Fs48000_Fc55_B2 1062877714 /* Floating point value 0.989882 */
+
+ /* Coefficients for centre frequency 66Hz */
+#define HPF_Fs8000_Fc66_A0 1023293271 /* Floating point value 0.953016 */
+#define HPF_Fs8000_Fc66_A1 -2046586542 /* Floating point value -1.906032 */
+#define HPF_Fs8000_Fc66_A2 1023293271 /* Floating point value 0.953016 */
+#define HPF_Fs8000_Fc66_B1 -2068896860 /* Floating point value -1.926810 */
+#define HPF_Fs8000_Fc66_B2 997931110 /* Floating point value 0.929396 */
+#define HPF_Fs11025_Fc66_A0 1033624228 /* Floating point value 0.962638 */
+#define HPF_Fs11025_Fc66_A1 -2067248455 /* Floating point value -1.925275 */
+#define HPF_Fs11025_Fc66_A2 1033624228 /* Floating point value 0.962638 */
+#define HPF_Fs11025_Fc66_B1 -2090448000 /* Floating point value -1.946881 */
+#define HPF_Fs11025_Fc66_B2 1018182305 /* Floating point value 0.948256 */
+#define HPF_Fs12000_Fc66_A0 1035857662 /* Floating point value 0.964718 */
+#define HPF_Fs12000_Fc66_A1 -2071715325 /* Floating point value -1.929435 */
+#define HPF_Fs12000_Fc66_A2 1035857662 /* Floating point value 0.964718 */
+#define HPF_Fs12000_Fc66_B1 -2095080333 /* Floating point value -1.951196 */
+#define HPF_Fs12000_Fc66_B2 1022587158 /* Floating point value 0.952359 */
+#define HPF_Fs16000_Fc66_A0 1042197528 /* Floating point value 0.970622 */
+#define HPF_Fs16000_Fc66_A1 -2084395056 /* Floating point value -1.941244 */
+#define HPF_Fs16000_Fc66_A2 1042197528 /* Floating point value 0.970622 */
+#define HPF_Fs16000_Fc66_B1 -2108177912 /* Floating point value -1.963394 */
+#define HPF_Fs16000_Fc66_B2 1035142690 /* Floating point value 0.964052 */
+#define HPF_Fs22050_Fc66_A0 1047445145 /* Floating point value 0.975509 */
+#define HPF_Fs22050_Fc66_A1 -2094890289 /* Floating point value -1.951019 */
+#define HPF_Fs22050_Fc66_A2 1047445145 /* Floating point value 0.975509 */
+#define HPF_Fs22050_Fc66_B1 -2118961025 /* Floating point value -1.973436 */
+#define HPF_Fs22050_Fc66_B2 1045593102 /* Floating point value 0.973784 */
+#define HPF_Fs24000_Fc66_A0 1048576175 /* Floating point value 0.976563 */
+#define HPF_Fs24000_Fc66_A1 -2097152349 /* Floating point value -1.953125 */
+#define HPF_Fs24000_Fc66_A2 1048576175 /* Floating point value 0.976563 */
+#define HPF_Fs24000_Fc66_B1 -2121278255 /* Floating point value -1.975594 */
+#define HPF_Fs24000_Fc66_B2 1047852379 /* Floating point value 0.975889 */
+#define HPF_Fs32000_Fc66_A0 1051780119 /* Floating point value 0.979547 */
+#define HPF_Fs32000_Fc66_A1 -2103560237 /* Floating point value -1.959093 */
+#define HPF_Fs32000_Fc66_A2 1051780119 /* Floating point value 0.979547 */
+#define HPF_Fs32000_Fc66_B1 -2127829187 /* Floating point value -1.981695 */
+#define HPF_Fs32000_Fc66_B2 1054265623 /* Floating point value 0.981861 */
+#define HPF_Fs44100_Fc66_A0 1054424722 /* Floating point value 0.982010 */
+#define HPF_Fs44100_Fc66_A1 -2108849444 /* Floating point value -1.964019 */
+#define HPF_Fs44100_Fc66_A2 1054424722 /* Floating point value 0.982010 */
+#define HPF_Fs44100_Fc66_B1 -2133221723 /* Floating point value -1.986718 */
+#define HPF_Fs44100_Fc66_B2 1059573993 /* Floating point value 0.986805 */
+#define HPF_Fs48000_Fc66_A0 1054993851 /* Floating point value 0.982540 */
+#define HPF_Fs48000_Fc66_A1 -2109987702 /* Floating point value -1.965079 */
+#define HPF_Fs48000_Fc66_A2 1054993851 /* Floating point value 0.982540 */
+#define HPF_Fs48000_Fc66_B1 -2134380475 /* Floating point value -1.987797 */
+#define HPF_Fs48000_Fc66_B2 1060718118 /* Floating point value 0.987871 */
+
+ /* Coefficients for centre frequency 78Hz */
+#define HPF_Fs8000_Fc78_A0 1016504203 /* Floating point value 0.946693 */
+#define HPF_Fs8000_Fc78_A1 -2033008405 /* Floating point value -1.893387 */
+#define HPF_Fs8000_Fc78_A2 1016504203 /* Floating point value 0.946693 */
+#define HPF_Fs8000_Fc78_B1 -2054623390 /* Floating point value -1.913517 */
+#define HPF_Fs8000_Fc78_B2 984733853 /* Floating point value 0.917105 */
+#define HPF_Fs11025_Fc78_A0 1028643741 /* Floating point value 0.957999 */
+#define HPF_Fs11025_Fc78_A1 -2057287482 /* Floating point value -1.915998 */
+#define HPF_Fs11025_Fc78_A2 1028643741 /* Floating point value 0.957999 */
+#define HPF_Fs11025_Fc78_B1 -2080083769 /* Floating point value -1.937229 */
+#define HPF_Fs11025_Fc78_B2 1008393904 /* Floating point value 0.939140 */
+#define HPF_Fs12000_Fc78_A0 1031271067 /* Floating point value 0.960446 */
+#define HPF_Fs12000_Fc78_A1 -2062542133 /* Floating point value -1.920892 */
+#define HPF_Fs12000_Fc78_A2 1031271067 /* Floating point value 0.960446 */
+#define HPF_Fs12000_Fc78_B1 -2085557048 /* Floating point value -1.942326 */
+#define HPF_Fs12000_Fc78_B2 1013551620 /* Floating point value 0.943944 */
+#define HPF_Fs16000_Fc78_A0 1038734628 /* Floating point value 0.967397 */
+#define HPF_Fs16000_Fc78_A1 -2077469256 /* Floating point value -1.934794 */
+#define HPF_Fs16000_Fc78_A2 1038734628 /* Floating point value 0.967397 */
+#define HPF_Fs16000_Fc78_B1 -2101033380 /* Floating point value -1.956740 */
+#define HPF_Fs16000_Fc78_B2 1028275228 /* Floating point value 0.957656 */
+#define HPF_Fs22050_Fc78_A0 1044918584 /* Floating point value 0.973156 */
+#define HPF_Fs22050_Fc78_A1 -2089837169 /* Floating point value -1.946313 */
+#define HPF_Fs22050_Fc78_A2 1044918584 /* Floating point value 0.973156 */
+#define HPF_Fs22050_Fc78_B1 -2113775854 /* Floating point value -1.968607 */
+#define HPF_Fs22050_Fc78_B2 1040555007 /* Floating point value 0.969092 */
+#define HPF_Fs24000_Fc78_A0 1046252164 /* Floating point value 0.974398 */
+#define HPF_Fs24000_Fc78_A1 -2092504328 /* Floating point value -1.948797 */
+#define HPF_Fs24000_Fc78_A2 1046252164 /* Floating point value 0.974398 */
+#define HPF_Fs24000_Fc78_B1 -2116514229 /* Floating point value -1.971157 */
+#define HPF_Fs24000_Fc78_B2 1043212719 /* Floating point value 0.971568 */
+#define HPF_Fs32000_Fc78_A0 1050031301 /* Floating point value 0.977918 */
+#define HPF_Fs32000_Fc78_A1 -2100062603 /* Floating point value -1.955836 */
+#define HPF_Fs32000_Fc78_A2 1050031301 /* Floating point value 0.977918 */
+#define HPF_Fs32000_Fc78_B1 -2124255900 /* Floating point value -1.978367 */
+#define HPF_Fs32000_Fc78_B2 1050762639 /* Floating point value 0.978599 */
+#define HPF_Fs44100_Fc78_A0 1053152258 /* Floating point value 0.980824 */
+#define HPF_Fs44100_Fc78_A1 -2106304516 /* Floating point value -1.961649 */
+#define HPF_Fs44100_Fc78_A2 1053152258 /* Floating point value 0.980824 */
+#define HPF_Fs44100_Fc78_B1 -2130628742 /* Floating point value -1.984303 */
+#define HPF_Fs44100_Fc78_B2 1057018180 /* Floating point value 0.984425 */
+#define HPF_Fs48000_Fc78_A0 1053824087 /* Floating point value 0.981450 */
+#define HPF_Fs48000_Fc78_A1 -2107648173 /* Floating point value -1.962900 */
+#define HPF_Fs48000_Fc78_A2 1053824087 /* Floating point value 0.981450 */
+#define HPF_Fs48000_Fc78_B1 -2131998154 /* Floating point value -1.985578 */
+#define HPF_Fs48000_Fc78_B2 1058367200 /* Floating point value 0.985681 */
+
+ /* Coefficients for centre frequency 90Hz */
+#define HPF_Fs8000_Fc90_A0 1009760053 /* Floating point value 0.940412 */
+#define HPF_Fs8000_Fc90_A1 -2019520105 /* Floating point value -1.880825 */
+#define HPF_Fs8000_Fc90_A2 1009760053 /* Floating point value 0.940412 */
+#define HPF_Fs8000_Fc90_B1 -2040357139 /* Floating point value -1.900231 */
+#define HPF_Fs8000_Fc90_B2 971711129 /* Floating point value 0.904977 */
+#define HPF_Fs11025_Fc90_A0 1023687217 /* Floating point value 0.953383 */
+#define HPF_Fs11025_Fc90_A1 -2047374434 /* Floating point value -1.906766 */
+#define HPF_Fs11025_Fc90_A2 1023687217 /* Floating point value 0.953383 */
+#define HPF_Fs11025_Fc90_B1 -2069722397 /* Floating point value -1.927579 */
+#define HPF_Fs11025_Fc90_B2 998699604 /* Floating point value 0.930111 */
+#define HPF_Fs12000_Fc90_A0 1026704754 /* Floating point value 0.956193 */
+#define HPF_Fs12000_Fc90_A1 -2053409508 /* Floating point value -1.912387 */
+#define HPF_Fs12000_Fc90_A2 1026704754 /* Floating point value 0.956193 */
+#define HPF_Fs12000_Fc90_B1 -2076035996 /* Floating point value -1.933459 */
+#define HPF_Fs12000_Fc90_B2 1004595918 /* Floating point value 0.935603 */
+#define HPF_Fs16000_Fc90_A0 1035283225 /* Floating point value 0.964183 */
+#define HPF_Fs16000_Fc90_A1 -2070566451 /* Floating point value -1.928365 */
+#define HPF_Fs16000_Fc90_A2 1035283225 /* Floating point value 0.964183 */
+#define HPF_Fs16000_Fc90_B1 -2093889811 /* Floating point value -1.950087 */
+#define HPF_Fs16000_Fc90_B2 1021453326 /* Floating point value 0.951303 */
+#define HPF_Fs22050_Fc90_A0 1042398116 /* Floating point value 0.970809 */
+#define HPF_Fs22050_Fc90_A1 -2084796232 /* Floating point value -1.941618 */
+#define HPF_Fs22050_Fc90_A2 1042398116 /* Floating point value 0.970809 */
+#define HPF_Fs22050_Fc90_B1 -2108591057 /* Floating point value -1.963778 */
+#define HPF_Fs22050_Fc90_B2 1035541188 /* Floating point value 0.964423 */
+#define HPF_Fs24000_Fc90_A0 1043933302 /* Floating point value 0.972239 */
+#define HPF_Fs24000_Fc90_A1 -2087866604 /* Floating point value -1.944477 */
+#define HPF_Fs24000_Fc90_A2 1043933302 /* Floating point value 0.972239 */
+#define HPF_Fs24000_Fc90_B1 -2111750495 /* Floating point value -1.966721 */
+#define HPF_Fs24000_Fc90_B2 1038593601 /* Floating point value 0.967266 */
+#define HPF_Fs32000_Fc90_A0 1048285391 /* Floating point value 0.976292 */
+#define HPF_Fs32000_Fc90_A1 -2096570783 /* Floating point value -1.952584 */
+#define HPF_Fs32000_Fc90_A2 1048285391 /* Floating point value 0.976292 */
+#define HPF_Fs32000_Fc90_B1 -2120682737 /* Floating point value -1.975040 */
+#define HPF_Fs32000_Fc90_B2 1047271295 /* Floating point value 0.975347 */
+#define HPF_Fs44100_Fc90_A0 1051881330 /* Floating point value 0.979641 */
+#define HPF_Fs44100_Fc90_A1 -2103762660 /* Floating point value -1.959282 */
+#define HPF_Fs44100_Fc90_A2 1051881330 /* Floating point value 0.979641 */
+#define HPF_Fs44100_Fc90_B1 -2128035809 /* Floating point value -1.981888 */
+#define HPF_Fs44100_Fc90_B2 1054468533 /* Floating point value 0.982050 */
+#define HPF_Fs48000_Fc90_A0 1052655619 /* Floating point value 0.980362 */
+#define HPF_Fs48000_Fc90_A1 -2105311238 /* Floating point value -1.960724 */
+#define HPF_Fs48000_Fc90_A2 1052655619 /* Floating point value 0.980362 */
+#define HPF_Fs48000_Fc90_B1 -2129615871 /* Floating point value -1.983359 */
+#define HPF_Fs48000_Fc90_B2 1056021492 /* Floating point value 0.983497 */
+
+
+/************************************************************************************/
+/* */
+/* Band Pass Filter coefficients */
+/* */
+/************************************************************************************/
+
+ /* Coefficients for centre frequency 55Hz */
+#define BPF_Fs8000_Fc55_A0 9875247 /* Floating point value 0.009197 */
+#define BPF_Fs8000_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc55_A2 -9875247 /* Floating point value -0.009197 */
+#define BPF_Fs8000_Fc55_B1 -2125519830 /* Floating point value -1.979545 */
+#define BPF_Fs8000_Fc55_B2 1053762629 /* Floating point value 0.981393 */
+#define BPF_Fs11025_Fc55_A0 7183952 /* Floating point value 0.006691 */
+#define BPF_Fs11025_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc55_A2 -7183952 /* Floating point value -0.006691 */
+#define BPF_Fs11025_Fc55_B1 -2131901658 /* Floating point value -1.985488 */
+#define BPF_Fs11025_Fc55_B2 1059207548 /* Floating point value 0.986464 */
+#define BPF_Fs12000_Fc55_A0 6603871 /* Floating point value 0.006150 */
+#define BPF_Fs12000_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc55_A2 -6603871 /* Floating point value -0.006150 */
+#define BPF_Fs12000_Fc55_B1 -2133238092 /* Floating point value -1.986733 */
+#define BPF_Fs12000_Fc55_B2 1060381143 /* Floating point value 0.987557 */
+#define BPF_Fs16000_Fc55_A0 4960591 /* Floating point value 0.004620 */
+#define BPF_Fs16000_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc55_A2 -4960591 /* Floating point value -0.004620 */
+#define BPF_Fs16000_Fc55_B1 -2136949052 /* Floating point value -1.990189 */
+#define BPF_Fs16000_Fc55_B2 1063705760 /* Floating point value 0.990653 */
+#define BPF_Fs22050_Fc55_A0 3604131 /* Floating point value 0.003357 */
+#define BPF_Fs22050_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc55_A2 -3604131 /* Floating point value -0.003357 */
+#define BPF_Fs22050_Fc55_B1 -2139929085 /* Floating point value -1.992964 */
+#define BPF_Fs22050_Fc55_B2 1066450095 /* Floating point value 0.993209 */
+#define BPF_Fs24000_Fc55_A0 3312207 /* Floating point value 0.003085 */
+#define BPF_Fs24000_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc55_A2 -3312207 /* Floating point value -0.003085 */
+#define BPF_Fs24000_Fc55_B1 -2140560606 /* Floating point value -1.993552 */
+#define BPF_Fs24000_Fc55_B2 1067040703 /* Floating point value 0.993759 */
+#define BPF_Fs32000_Fc55_A0 2486091 /* Floating point value 0.002315 */
+#define BPF_Fs32000_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc55_A2 -2486091 /* Floating point value -0.002315 */
+#define BPF_Fs32000_Fc55_B1 -2142328962 /* Floating point value -1.995199 */
+#define BPF_Fs32000_Fc55_B2 1068712067 /* Floating point value 0.995316 */
+#define BPF_Fs44100_Fc55_A0 1805125 /* Floating point value 0.001681 */
+#define BPF_Fs44100_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc55_A2 -1805125 /* Floating point value -0.001681 */
+#define BPF_Fs44100_Fc55_B1 -2143765772 /* Floating point value -1.996537 */
+#define BPF_Fs44100_Fc55_B2 1070089770 /* Floating point value 0.996599 */
+#define BPF_Fs48000_Fc55_A0 1658687 /* Floating point value 0.001545 */
+#define BPF_Fs48000_Fc55_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc55_A2 -1658687 /* Floating point value -0.001545 */
+#define BPF_Fs48000_Fc55_B1 -2144072292 /* Floating point value -1.996823 */
+#define BPF_Fs48000_Fc55_B2 1070386036 /* Floating point value 0.996875 */
+
+ /* Coefficients for centre frequency 66Hz */
+#define BPF_Fs8000_Fc66_A0 13580189 /* Floating point value 0.012648 */
+#define BPF_Fs8000_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc66_A2 -13580189 /* Floating point value -0.012648 */
+#define BPF_Fs8000_Fc66_B1 -2117161175 /* Floating point value -1.971760 */
+#define BPF_Fs8000_Fc66_B2 1046266945 /* Floating point value 0.974412 */
+#define BPF_Fs11025_Fc66_A0 9888559 /* Floating point value 0.009209 */
+#define BPF_Fs11025_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc66_A2 -9888559 /* Floating point value -0.009209 */
+#define BPF_Fs11025_Fc66_B1 -2125972738 /* Floating point value -1.979966 */
+#define BPF_Fs11025_Fc66_B2 1053735698 /* Floating point value 0.981368 */
+#define BPF_Fs12000_Fc66_A0 9091954 /* Floating point value 0.008468 */
+#define BPF_Fs12000_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc66_A2 -9091954 /* Floating point value -0.008468 */
+#define BPF_Fs12000_Fc66_B1 -2127818004 /* Floating point value -1.981685 */
+#define BPF_Fs12000_Fc66_B2 1055347356 /* Floating point value 0.982869 */
+#define BPF_Fs16000_Fc66_A0 6833525 /* Floating point value 0.006364 */
+#define BPF_Fs16000_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc66_A2 -6833525 /* Floating point value -0.006364 */
+#define BPF_Fs16000_Fc66_B1 -2132941739 /* Floating point value -1.986457 */
+#define BPF_Fs16000_Fc66_B2 1059916517 /* Floating point value 0.987124 */
+#define BPF_Fs22050_Fc66_A0 4967309 /* Floating point value 0.004626 */
+#define BPF_Fs22050_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc66_A2 -4967309 /* Floating point value -0.004626 */
+#define BPF_Fs22050_Fc66_B1 -2137056003 /* Floating point value -1.990288 */
+#define BPF_Fs22050_Fc66_B2 1063692170 /* Floating point value 0.990641 */
+#define BPF_Fs24000_Fc66_A0 4565445 /* Floating point value 0.004252 */
+#define BPF_Fs24000_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc66_A2 -4565445 /* Floating point value -0.004252 */
+#define BPF_Fs24000_Fc66_B1 -2137927842 /* Floating point value -1.991100 */
+#define BPF_Fs24000_Fc66_B2 1064505202 /* Floating point value 0.991398 */
+#define BPF_Fs32000_Fc66_A0 3427761 /* Floating point value 0.003192 */
+#define BPF_Fs32000_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc66_A2 -3427761 /* Floating point value -0.003192 */
+#define BPF_Fs32000_Fc66_B1 -2140369007 /* Floating point value -1.993374 */
+#define BPF_Fs32000_Fc66_B2 1066806920 /* Floating point value 0.993541 */
+#define BPF_Fs44100_Fc66_A0 2489466 /* Floating point value 0.002318 */
+#define BPF_Fs44100_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc66_A2 -2489466 /* Floating point value -0.002318 */
+#define BPF_Fs44100_Fc66_B1 -2142352342 /* Floating point value -1.995221 */
+#define BPF_Fs44100_Fc66_B2 1068705240 /* Floating point value 0.995309 */
+#define BPF_Fs48000_Fc66_A0 2287632 /* Floating point value 0.002131 */
+#define BPF_Fs48000_Fc66_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc66_A2 -2287632 /* Floating point value -0.002131 */
+#define BPF_Fs48000_Fc66_B1 -2142775436 /* Floating point value -1.995615 */
+#define BPF_Fs48000_Fc66_B2 1069113581 /* Floating point value 0.995690 */
+
+ /* Coefficients for centre frequency 78Hz */
+#define BPF_Fs8000_Fc78_A0 19941180 /* Floating point value 0.018572 */
+#define BPF_Fs8000_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc78_A2 -19941180 /* Floating point value -0.018572 */
+#define BPF_Fs8000_Fc78_B1 -2103186749 /* Floating point value -1.958745 */
+#define BPF_Fs8000_Fc78_B2 1033397648 /* Floating point value 0.962427 */
+#define BPF_Fs11025_Fc78_A0 14543934 /* Floating point value 0.013545 */
+#define BPF_Fs11025_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc78_A2 -14543934 /* Floating point value -0.013545 */
+#define BPF_Fs11025_Fc78_B1 -2115966638 /* Floating point value -1.970647 */
+#define BPF_Fs11025_Fc78_B2 1044317135 /* Floating point value 0.972596 */
+#define BPF_Fs12000_Fc78_A0 13376999 /* Floating point value 0.012458 */
+#define BPF_Fs12000_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc78_A2 -13376999 /* Floating point value -0.012458 */
+#define BPF_Fs12000_Fc78_B1 -2118651708 /* Floating point value -1.973148 */
+#define BPF_Fs12000_Fc78_B2 1046678029 /* Floating point value 0.974795 */
+#define BPF_Fs16000_Fc78_A0 10064222 /* Floating point value 0.009373 */
+#define BPF_Fs16000_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc78_A2 -10064222 /* Floating point value -0.009373 */
+#define BPF_Fs16000_Fc78_B1 -2126124342 /* Floating point value -1.980108 */
+#define BPF_Fs16000_Fc78_B2 1053380304 /* Floating point value 0.981037 */
+#define BPF_Fs22050_Fc78_A0 7321780 /* Floating point value 0.006819 */
+#define BPF_Fs22050_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc78_A2 -7321780 /* Floating point value -0.006819 */
+#define BPF_Fs22050_Fc78_B1 -2132143771 /* Floating point value -1.985714 */
+#define BPF_Fs22050_Fc78_B2 1058928700 /* Floating point value 0.986204 */
+#define BPF_Fs24000_Fc78_A0 6730640 /* Floating point value 0.006268 */
+#define BPF_Fs24000_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc78_A2 -6730640 /* Floating point value -0.006268 */
+#define BPF_Fs24000_Fc78_B1 -2133421607 /* Floating point value -1.986904 */
+#define BPF_Fs24000_Fc78_B2 1060124669 /* Floating point value 0.987318 */
+#define BPF_Fs32000_Fc78_A0 5055965 /* Floating point value 0.004709 */
+#define BPF_Fs32000_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc78_A2 -5055965 /* Floating point value -0.004709 */
+#define BPF_Fs32000_Fc78_B1 -2137003977 /* Floating point value -1.990240 */
+#define BPF_Fs32000_Fc78_B2 1063512802 /* Floating point value 0.990473 */
+#define BPF_Fs44100_Fc78_A0 3673516 /* Floating point value 0.003421 */
+#define BPF_Fs44100_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc78_A2 -3673516 /* Floating point value -0.003421 */
+#define BPF_Fs44100_Fc78_B1 -2139919394 /* Floating point value -1.992955 */
+#define BPF_Fs44100_Fc78_B2 1066309718 /* Floating point value 0.993078 */
+#define BPF_Fs48000_Fc78_A0 3375990 /* Floating point value 0.003144 */
+#define BPF_Fs48000_Fc78_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc78_A2 -3375990 /* Floating point value -0.003144 */
+#define BPF_Fs48000_Fc78_B1 -2140541906 /* Floating point value -1.993535 */
+#define BPF_Fs48000_Fc78_B2 1066911660 /* Floating point value 0.993639 */
+
+ /* Coefficients for centre frequency 90Hz */
+#define BPF_Fs8000_Fc90_A0 24438548 /* Floating point value 0.022760 */
+#define BPF_Fs8000_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs8000_Fc90_A2 -24438548 /* Floating point value -0.022760 */
+#define BPF_Fs8000_Fc90_B1 -2092801347 /* Floating point value -1.949073 */
+#define BPF_Fs8000_Fc90_B2 1024298757 /* Floating point value 0.953953 */
+#define BPF_Fs11025_Fc90_A0 17844385 /* Floating point value 0.016619 */
+#define BPF_Fs11025_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs11025_Fc90_A2 -17844385 /* Floating point value -0.016619 */
+#define BPF_Fs11025_Fc90_B1 -2108604921 /* Floating point value -1.963791 */
+#define BPF_Fs11025_Fc90_B2 1037639797 /* Floating point value 0.966377 */
+#define BPF_Fs12000_Fc90_A0 16416707 /* Floating point value 0.015289 */
+#define BPF_Fs12000_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs12000_Fc90_A2 -16416707 /* Floating point value -0.015289 */
+#define BPF_Fs12000_Fc90_B1 -2111922936 /* Floating point value -1.966882 */
+#define BPF_Fs12000_Fc90_B2 1040528216 /* Floating point value 0.969067 */
+#define BPF_Fs16000_Fc90_A0 12359883 /* Floating point value 0.011511 */
+#define BPF_Fs16000_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs16000_Fc90_A2 -12359883 /* Floating point value -0.011511 */
+#define BPF_Fs16000_Fc90_B1 -2121152162 /* Floating point value -1.975477 */
+#define BPF_Fs16000_Fc90_B2 1048735817 /* Floating point value 0.976711 */
+#define BPF_Fs22050_Fc90_A0 8997173 /* Floating point value 0.008379 */
+#define BPF_Fs22050_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs22050_Fc90_A2 -8997173 /* Floating point value -0.008379 */
+#define BPF_Fs22050_Fc90_B1 -2128580762 /* Floating point value -1.982395 */
+#define BPF_Fs22050_Fc90_B2 1055539113 /* Floating point value 0.983047 */
+#define BPF_Fs24000_Fc90_A0 8271818 /* Floating point value 0.007704 */
+#define BPF_Fs24000_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs24000_Fc90_A2 -8271818 /* Floating point value -0.007704 */
+#define BPF_Fs24000_Fc90_B1 -2130157013 /* Floating point value -1.983863 */
+#define BPF_Fs24000_Fc90_B2 1057006621 /* Floating point value 0.984414 */
+#define BPF_Fs32000_Fc90_A0 6215918 /* Floating point value 0.005789 */
+#define BPF_Fs32000_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs32000_Fc90_A2 -6215918 /* Floating point value -0.005789 */
+#define BPF_Fs32000_Fc90_B1 -2134574521 /* Floating point value -1.987977 */
+#define BPF_Fs32000_Fc90_B2 1061166033 /* Floating point value 0.988288 */
+#define BPF_Fs44100_Fc90_A0 4517651 /* Floating point value 0.004207 */
+#define BPF_Fs44100_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs44100_Fc90_A2 -4517651 /* Floating point value -0.004207 */
+#define BPF_Fs44100_Fc90_B1 -2138167926 /* Floating point value -1.991324 */
+#define BPF_Fs44100_Fc90_B2 1064601898 /* Floating point value 0.991488 */
+#define BPF_Fs48000_Fc90_A0 4152024 /* Floating point value 0.003867 */
+#define BPF_Fs48000_Fc90_A1 0 /* Floating point value 0.000000 */
+#define BPF_Fs48000_Fc90_A2 -4152024 /* Floating point value -0.003867 */
+#define BPF_Fs48000_Fc90_B1 -2138935002 /* Floating point value -1.992038 */
+#define BPF_Fs48000_Fc90_B2 1065341620 /* Floating point value 0.992177 */
+
+
+/************************************************************************************/
+/* */
+/* Automatic Gain Control time constants and gain settings */
+/* */
+/************************************************************************************/
+
+/* AGC Time constants */
+#define AGC_ATTACK_Fs8000 27571 /* Floating point value 0.841395 */
+#define AGC_ATTACK_Fs11025 28909 /* Floating point value 0.882223 */
+#define AGC_ATTACK_Fs12000 29205 /* Floating point value 0.891251 */
+#define AGC_ATTACK_Fs16000 30057 /* Floating point value 0.917276 */
+#define AGC_ATTACK_Fs22050 30778 /* Floating point value 0.939267 */
+#define AGC_ATTACK_Fs24000 30935 /* Floating point value 0.944061 */
+#define AGC_ATTACK_Fs32000 31383 /* Floating point value 0.957745 */
+#define AGC_ATTACK_Fs44100 31757 /* Floating point value 0.969158 */
+#define AGC_ATTACK_Fs48000 31838 /* Floating point value 0.971628 */
+#define DECAY_SHIFT 10 /* As a power of 2 */
+#define AGC_DECAY_Fs8000 44 /* Floating point value 0.000042 */
+#define AGC_DECAY_Fs11025 32 /* Floating point value 0.000030 */
+#define AGC_DECAY_Fs12000 29 /* Floating point value 0.000028 */
+#define AGC_DECAY_Fs16000 22 /* Floating point value 0.000021 */
+#define AGC_DECAY_Fs22050 16 /* Floating point value 0.000015 */
+#define AGC_DECAY_Fs24000 15 /* Floating point value 0.000014 */
+#define AGC_DECAY_Fs32000 11 /* Floating point value 0.000010 */
+#define AGC_DECAY_Fs44100 8 /* Floating point value 0.000008 */
+#define AGC_DECAY_Fs48000 7 /* Floating point value 0.000007 */
+
+/* AGC Gain settings */
+#define AGC_GAIN_SCALE 31 /* As a power of 2 */
+#define AGC_GAIN_SHIFT 4 /* As a power of 2 */
+#define AGC_TARGETLEVEL 33170337 /* Floating point value -0.100000dB */
+#define AGC_HPFGAIN_0dB 110739704 /* Floating point value 0.412538 */
+#define AGC_GAIN_0dB 0 /* Floating point value 0.000000 */
+#define AGC_HPFGAIN_1dB 157006071 /* Floating point value 0.584893 */
+#define AGC_GAIN_1dB 32754079 /* Floating point value 0.122018 */
+#define AGC_HPFGAIN_2dB 208917788 /* Floating point value 0.778279 */
+#define AGC_GAIN_2dB 69504761 /* Floating point value 0.258925 */
+#define AGC_HPFGAIN_3dB 267163693 /* Floating point value 0.995262 */
+#define AGC_GAIN_3dB 110739704 /* Floating point value 0.412538 */
+#define AGC_HPFGAIN_4dB 332516674 /* Floating point value 1.238721 */
+#define AGC_GAIN_4dB 157006071 /* Floating point value 0.584893 */
+#define AGC_HPFGAIN_5dB 405843924 /* Floating point value 1.511886 */
+#define AGC_GAIN_5dB 208917788 /* Floating point value 0.778279 */
+#define AGC_HPFGAIN_6dB 488118451 /* Floating point value 1.818383 */
+#define AGC_GAIN_6dB 267163693 /* Floating point value 0.995262 */
+#define AGC_HPFGAIN_7dB 580431990 /* Floating point value 2.162278 */
+#define AGC_GAIN_7dB 332516674 /* Floating point value 1.238721 */
+#define AGC_HPFGAIN_8dB 684009483 /* Floating point value 2.548134 */
+#define AGC_GAIN_8dB 405843924 /* Floating point value 1.511886 */
+#define AGC_HPFGAIN_9dB 800225343 /* Floating point value 2.981072 */
+#define AGC_GAIN_9dB 488118451 /* Floating point value 1.818383 */
+#define AGC_HPFGAIN_10dB 930621681 /* Floating point value 3.466836 */
+#define AGC_GAIN_10dB 580431990 /* Floating point value 2.162278 */
+#define AGC_HPFGAIN_11dB 1076928780 /* Floating point value 4.011872 */
+#define AGC_GAIN_11dB 684009483 /* Floating point value 2.548134 */
+#define AGC_HPFGAIN_12dB 1241088045 /* Floating point value 4.623413 */
+#define AGC_GAIN_12dB 800225343 /* Floating point value 2.981072 */
+#define AGC_HPFGAIN_13dB 1425277769 /* Floating point value 5.309573 */
+#define AGC_GAIN_13dB 930621681 /* Floating point value 3.466836 */
+#define AGC_HPFGAIN_14dB 1631942039 /* Floating point value 6.079458 */
+#define AGC_GAIN_14dB 1076928780 /* Floating point value 4.011872 */
+#define AGC_HPFGAIN_15dB 1863823163 /* Floating point value 6.943282 */
+#define AGC_GAIN_15dB 1241088045 /* Floating point value 4.623413 */
+
+
+/************************************************************************************/
+/* */
+/* Volume control */
+/* */
+/************************************************************************************/
+
+/* Volume control gain */
+#define VOLUME_MAX 0 /* In dBs */
+#define VOLUME_SHIFT 0 /* In dBs */
+
+/* Volume control time constants */
+#define VOL_TC_SHIFT 21 /* As a power of 2 */
+#define VOL_TC_Fs8000 25889 /* Floating point value 0.024690 */
+#define VOL_TC_Fs11025 18850 /* Floating point value 0.017977 */
+#define VOL_TC_Fs12000 17331 /* Floating point value 0.016529 */
+#define VOL_TC_Fs16000 13026 /* Floating point value 0.012422 */
+#define VOL_TC_Fs22050 9468 /* Floating point value 0.009029 */
+#define VOL_TC_Fs24000 8702 /* Floating point value 0.008299 */
+#define VOL_TC_Fs32000 6533 /* Floating point value 0.006231 */
+#define VOL_TC_Fs44100 4745 /* Floating point value 0.004525 */
+#define VOL_TC_Fs48000 4360 /* Floating point value 0.004158 */
+#define MIX_TC_Fs8000 29365 /* Floating point value 0.896151 */
+#define MIX_TC_Fs11025 30230 /* Floating point value 0.922548 */
+#define MIX_TC_Fs12000 30422 /* Floating point value 0.928415 */
+#define MIX_TC_Fs16000 30978 /* Floating point value 0.945387 */
+#define MIX_TC_Fs22050 31451 /* Floating point value 0.959804 */
+#define MIX_TC_Fs24000 31554 /* Floating point value 0.962956 */
+#define MIX_TC_Fs32000 31850 /* Floating point value 0.971973 */
+#define MIX_TC_Fs44100 32097 /* Floating point value 0.979515 */
+#define MIX_TC_Fs48000 32150 /* Floating point value 0.981150 */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
new file mode 100755
index 0000000..8cf84b7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1315 $
+ $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+#include "VectorArithmetic.h"
+#include "LVDBE_Coeffs.h"
+#include "LVDBE_Tables.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_GetParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the Dynamic Bass Enhancement parameters. The current parameter set is */
+/* returned via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t hInstance,
+ LVDBE_Params_t *pParams)
+{
+
+ LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+
+ *pParams = pInstance->Params;
+
+ return(LVDBE_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_GetCapabilities */
+/* */
+/* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
+/* returned via the pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pCapabilities Pointer to an empty capability structure */
+/* */
+/* RETURNS: */
+/* LVDBE_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVDBE_Process function */
+/* */
+/************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,
+ LVDBE_Capabilities_t *pCapabilities)
+{
+
+ LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+
+ *pCapabilities = pInstance->Capabilities;
+
+ return(LVDBE_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_SetFilters */
+/* */
+/* DESCRIPTION: */
+/* Sets the filter coefficients and clears the data history */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/************************************************************************************/
+
+void LVDBE_SetFilters(LVDBE_Instance_t *pInstance,
+ LVDBE_Params_t *pParams)
+{
+
+ /*
+ * Calculate the table offsets
+ */
+ LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
+
+
+ /*
+ * Setup the high pass filter
+ */
+ LoadConst_16(0, /* Clear the history, value 0 */
+ (void *)&pInstance->pData->HPFTaps, /* Destination Cast to void: \
+ no dereferencing in function*/
+ sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16)); /* Number of words */
+ BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance, /* Initialise the filter */
+ &pInstance->pData->HPFTaps,
+ (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
+
+
+ /*
+ * Setup the band pass filter
+ */
+ LoadConst_16(0, /* Clear the history, value 0 */
+ (void *)&pInstance->pData->BPFTaps, /* Destination Cast to void:\
+ no dereferencing in function*/
+ sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16)); /* Number of words */
+ BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance, /* Initialise the filter */
+ &pInstance->pData->BPFTaps,
+ (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
+
+}
+
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_SetAGC */
+/* */
+/* DESCRIPTION: */
+/* Sets the AGC gain level and attack and decay times constants. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/************************************************************************************/
+
+void LVDBE_SetAGC(LVDBE_Instance_t *pInstance,
+ LVDBE_Params_t *pParams)
+{
+
+ /*
+ * Get the attack and decay time constants
+ */
+ pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate]; /* Attack multiplier */
+ pInstance->pData->AGCInstance.AGC_Decay = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate]; /* Decay multipler */
+
+
+ /*
+ * Get the boost gain
+ */
+ if (pParams->HPFSelect == LVDBE_HPF_ON)
+ {
+ pInstance->pData->AGCInstance.AGC_MaxGain = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter on */
+ }
+ else
+ {
+ pInstance->pData->AGCInstance.AGC_MaxGain = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel]; /* High pass filter off */
+ }
+ pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT;
+ pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
+
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_SetVolume */
+/* */
+/* DESCRIPTION: */
+/* Converts the input volume demand from dBs to linear. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/* NOTES: */
+/* 1. The volume should have the following settings: */
+/* */
+/* DBE Vol Control Volume setting */
+/* === =========== =================== */
+/* Off Off HeadroomdB */
+/* Off On VolumedB+HeadroomdB */
+/* On Off HeadroomdB */
+/* On On VolumedB+HeadroomdB */
+/* */
+/************************************************************************************/
+
+void LVDBE_SetVolume(LVDBE_Instance_t *pInstance,
+ LVDBE_Params_t *pParams)
+{
+
+ LVM_UINT16 dBShifts; /* 6dB shifts */
+ LVM_UINT16 dBOffset; /* Table offset */
+ LVM_INT16 Volume = 0; /* Required volume in dBs */
+
+ /*
+ * Apply the volume if enabled
+ */
+ if (pParams->VolumeControl == LVDBE_VOLUME_ON)
+ {
+ /*
+ * Limit the gain to the maximum allowed
+ */
+ if (pParams->VolumedB > VOLUME_MAX)
+ {
+ Volume = VOLUME_MAX;
+ }
+ else
+ {
+ Volume = pParams->VolumedB;
+ }
+ }
+
+
+ /*
+ * Calculate the required gain and shifts
+ */
+ dBOffset = (LVM_UINT16)(6 + Volume % 6); /* Get the dBs 0-5 */
+ dBShifts = (LVM_UINT16)(Volume / -6); /* Get the 6dB shifts */
+
+
+ /*
+ * When DBE is enabled use AGC volume
+ */
+ pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16);
+ pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts;
+
+ pInstance->pData->AGCInstance.VolumeTC = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate]; /* Volume update time constant */
+ pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1;
+
+ /*
+ * When DBE is disabled use the bypass volume control
+ */
+ if(dBShifts > 0)
+ {
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts));
+ }
+ else
+ {
+ LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]);
+ }
+
+ pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
+ LVDBE_MIXER_TC,
+ (LVM_Fs_en)pInstance->Params.SampleRate,
+ 2);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Control */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the Bass Enhancement parameters. Changing the parameters while the */
+/* module is processing signals may have the following side effects: */
+/* */
+/* General parameters: */
+/* =================== */
+/* OperatingMode: Changing the mode of operation may cause a change in volume */
+/* level or cause pops and clicks. */
+/* */
+/* SampleRate: Changing the sample rate may cause pops and clicks. */
+/* */
+/* EffectLevel: Changing the effect level may cause pops and clicks */
+/* */
+/* CentreFrequency: Changing the centre frequency may cause pops and clicks */
+/* */
+/* HPFSelect: Selecting/de-selecting the high pass filter may cause pops and */
+/* clicks */
+/* */
+/* VolumedB Changing the volume setting will have no side effects */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t hInstance,
+ LVDBE_Params_t *pParams)
+{
+
+ LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+
+
+ /*
+ * Update the filters
+ */
+ if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
+ {
+ LVDBE_SetFilters(pInstance, /* Instance pointer */
+ pParams); /* New parameters */
+ }
+
+
+ /*
+ * Update the AGC is the effect level has changed
+ */
+ if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
+ (pInstance->Params.HPFSelect != pParams->HPFSelect))
+ {
+ LVDBE_SetAGC(pInstance, /* Instance pointer */
+ pParams); /* New parameters */
+ }
+
+
+ /*
+ * Update the Volume if the volume demand has changed
+ */
+ if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
+ (pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
+ (pInstance->Params.VolumeControl != pParams->VolumeControl))
+ {
+ LVDBE_SetVolume(pInstance, /* Instance pointer */
+ pParams); /* New parameters */
+ }
+
+ if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
+ {
+ LVDBE_Params_t Params = *pParams; /* make local copy of params */
+ Params.EffectLevel = 0; /* zero effect level before switching off module*/
+ pInstance->bTransitionOnToOff = LVM_TRUE; /* Set the CallBack */
+ LVDBE_SetAGC(pInstance, /* Instance pointer */
+ &Params); /* New parameters */
+ }
+ if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
+ {
+ pInstance->bTransitionOnToOff = LVM_FALSE; /* Set the CallBack */
+ LVDBE_SetAGC(pInstance, /* Instance pointer */
+ pParams); /* New parameters */
+ }
+
+ /*
+ * Update the instance parameters
+ */
+ pInstance->Params = *pParams;
+
+
+ return(LVDBE_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
new file mode 100755
index 0000000..75869c7
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1081 $
+ $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the instance capabilities */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t hInstance,
+ LVDBE_MemTab_t *pMemoryTable,
+ LVDBE_Capabilities_t *pCapabilities)
+{
+
+ LVM_UINT32 ScratchSize;
+ LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *)hInstance;
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+ /*
+ * Instance memory
+ */
+ pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size = sizeof(LVDBE_Instance_t);
+ pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment = LVDBE_INSTANCE_ALIGN;
+ pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type = LVDBE_PERSISTENT;
+ pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+ /*
+ * Data memory
+ */
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size = sizeof(LVDBE_Data_t);
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment = LVDBE_PERSISTENT_DATA_ALIGN;
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type = LVDBE_PERSISTENT_DATA;
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+ /*
+ * Coef memory
+ */
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_t);
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment = LVDBE_PERSISTENT_COEF_ALIGN;
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type = LVDBE_PERSISTENT_COEF;
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+ /*
+ * Scratch memory
+ */
+ ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
+ pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size = ScratchSize;
+ pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment = LVDBE_SCRATCH_ALIGN;
+ pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type = LVDBE_SCRATCH;
+ pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+ }
+ else
+ {
+ /* Read back memory allocation table */
+ *pMemoryTable = pInstance->MemoryTable;
+ }
+
+ return(LVDBE_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Init */
+/* */
+/* DESCRIPTION: */
+/* Create and initialisation function for the Dynamic Bass Enhancement module */
+/* */
+/* This function can be used to create an algorithm instance by calling with */
+/* hInstance set to NULL. In this case the algorithm returns the new instance */
+/* handle. */
+/* */
+/* This function can be used to force a full re-initialisation of the algorithm */
+/* by calling with hInstance = Instance Handle. In this case the memory table */
+/* should be correct for the instance, this can be ensured by calling the function */
+/* DBE_Memory before calling this function. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pCapabilities Pointer to the instance capabilities */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Initialisation succeeded */
+/* LVDBE_ALIGNMENTERROR Instance or scratch memory on incorrect alignment */
+/* LVDBE_NULLADDRESS Instance or scratch memory has a NULL pointer */
+/* */
+/* NOTES: */
+/* 1. The instance handle is the pointer to the base address of the first memory */
+/* region. */
+/* 2. This function must not be interrupted by the LVDBE_Process function */
+/* */
+/****************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance,
+ LVDBE_MemTab_t *pMemoryTable,
+ LVDBE_Capabilities_t *pCapabilities)
+{
+
+ LVDBE_Instance_t *pInstance;
+ LVMixer3_1St_st *pMixer_Instance;
+ LVM_INT16 i;
+ LVM_INT32 MixGain;
+
+
+ /*
+ * Set the instance handle if not already initialised
+ */
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
+ }
+ pInstance =(LVDBE_Instance_t *)*phInstance;
+
+
+ /*
+ * Check the memory table for NULL pointers and incorrectly aligned data
+ */
+ for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
+ {
+ if (pMemoryTable->Region[i].Size!=0)
+ {
+ if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+ {
+ return(LVDBE_NULLADDRESS);
+ }
+ if (((LVM_UINT32)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
+ return(LVDBE_ALIGNMENTERROR);
+ }
+ }
+ }
+
+
+ /*
+ * Save the memory table in the instance structure
+ */
+ pInstance->Capabilities = *pCapabilities;
+
+
+ /*
+ * Save the memory table in the instance structure
+ */
+ pInstance->MemoryTable = *pMemoryTable;
+
+
+ /*
+ * Set the default instance parameters
+ */
+ pInstance->Params.CentreFrequency = LVDBE_CENTRE_55HZ;
+ pInstance->Params.EffectLevel = 0;
+ pInstance->Params.HeadroomdB = 0;
+ pInstance->Params.HPFSelect = LVDBE_HPF_OFF;
+ pInstance->Params.OperatingMode = LVDBE_OFF;
+ pInstance->Params.SampleRate = LVDBE_FS_8000;
+ pInstance->Params.VolumeControl = LVDBE_VOLUME_OFF;
+ pInstance->Params.VolumedB = 0;
+
+
+ /*
+ * Set pointer to data and coef memory
+ */
+ pInstance->pData = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
+ pInstance->pCoef = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
+
+
+ /*
+ * Initialise the filters
+ */
+ LVDBE_SetFilters(pInstance, /* Set the filter taps and coefficients */
+ &pInstance->Params);
+
+
+ /*
+ * Initialise the AGC
+ */
+ LVDBE_SetAGC(pInstance, /* Set the AGC gain */
+ &pInstance->Params);
+ pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain; /* Default to the bass boost setting */
+
+
+ /*
+ * Initialise the volume
+ */
+ LVDBE_SetVolume(pInstance, /* Set the Volume */
+ &pInstance->Params);
+
+ pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target; /* Initialise as the target */
+
+ pMixer_Instance = &pInstance->pData->BypassVolume;
+ MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
+ LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
+
+ /* Configure the mixer process path */
+ pMixer_Instance->MixerStream[0].CallbackParam = 0;
+ pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
+ pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
+ pMixer_Instance->MixerStream[0].CallbackSet = 0;
+
+ /*
+ * Initialise the clicks minimisation variable
+ */
+ pInstance->bTransitionOnToOff = LVM_FALSE;
+
+ return(LVDBE_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
new file mode 100755
index 0000000..3e09cf4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1081 $
+ $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the private layer interface of Dynamic Bass Enhancement module */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the execution layer. */
+/* */
+/****************************************************************************************/
+
+#ifndef __LVDBE_PRIVATE_H__
+#define __LVDBE_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVDBE.h" /* Calling or Application layer definitions */
+#include "BIQUAD.h"
+#include "LVC_Mixer.h"
+#include "AGC.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+
+/* General */
+#define LVDBE_INVALID 0xFFFF /* Invalid init parameter */
+
+/* Memory */
+#define LVDBE_MEMREGION_INSTANCE 0 /* Offset to the instance memory region */
+#define LVDBE_MEMREGION_PERSISTENT_DATA 1 /* Offset to persistent data memory region */
+#define LVDBE_MEMREGION_PERSISTENT_COEF 2 /* Offset to persistent coefficient region */
+#define LVDBE_MEMREGION_SCRATCH 3 /* Offset to data scratch memory region */
+
+#define LVDBE_INSTANCE_ALIGN 4 /* 32-bit alignment for structures */
+#define LVDBE_PERSISTENT_DATA_ALIGN 4 /* 32-bit alignment for data */
+#define LVDBE_PERSISTENT_COEF_ALIGN 4 /* 32-bit alignment for coef */
+#define LVDBE_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
+
+#define LVDBE_SCRATCHBUFFERS_INPLACE 4 /* Number of buffers required for inplace processing */
+
+#define LVDBE_MIXER_TC 5 /* Mixer time */
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Data structure */
+typedef struct
+{
+ /* AGC parameters */
+ AGC_MIX_VOL_2St1Mon_D32_t AGCInstance; /* AGC instance parameters */
+
+ /* Process variables */
+ Biquad_2I_Order2_Taps_t HPFTaps; /* High pass filter taps */
+ Biquad_1I_Order2_Taps_t BPFTaps; /* Band pass filter taps */
+ LVMixer3_1St_st BypassVolume; /* Bypass volume scaler */
+
+} LVDBE_Data_t;
+
+/* Coefs structure */
+typedef struct
+{
+ /* Process variables */
+ Biquad_Instance_t HPFInstance; /* High pass filter instance */
+ Biquad_Instance_t BPFInstance; /* Band pass filter instance */
+
+} LVDBE_Coef_t;
+
+/* Instance structure */
+typedef struct
+{
+ /* Public parameters */
+ LVDBE_MemTab_t MemoryTable; /* Instance memory allocation table */
+ LVDBE_Params_t Params; /* Instance parameters */
+ LVDBE_Capabilities_t Capabilities; /* Instance capabilities */
+
+ /* Data and coefficient pointers */
+ LVDBE_Data_t *pData; /* Instance data */
+ LVDBE_Coef_t *pCoef; /* Instance coefficients */
+
+ LVM_INT32 bTransitionOnToOff;
+
+} LVDBE_Instance_t;
+
+
+/****************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/****************************************************************************************/
+
+void LVDBE_SetAGC(LVDBE_Instance_t *pInstance,
+ LVDBE_Params_t *pParams);
+
+
+void LVDBE_SetVolume(LVDBE_Instance_t *pInstance,
+ LVDBE_Params_t *pParams);
+
+
+void LVDBE_SetFilters(LVDBE_Instance_t *pInstance,
+ LVDBE_Params_t *pParams);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVDBE_PRIVATE_H__ */
+
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
new file mode 100755
index 0000000..35eec07
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1081 $
+ $Date: 2010-07-05 11:48:44 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Private.h"
+#include "VectorArithmetic.h"
+#include "AGC.h"
+#include "LVDBE_Coeffs.h" /* Filter coefficients */
+
+
+/********************************************************************************************/
+/* */
+/* FUNCTION: LVDBE_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the Bass Enhancement module. */
+/* */
+/* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */
+/* format is not supported, the calling routine must convert the mono stream to */
+/* mono-in-stereo. */
+/* ___________ */
+/* ________ | | ________ */
+/* | | _____ |------------------------->| | | | */
+/* | 16-bit | | | | ________ | | | 32-bit | */
+/* -+-->| to |-->| HPF |--| | | _____ | AGC Mixer |-->| to |--| */
+/* | | 32-bit | |_____| | | Stereo | | | | | | 16-bit | | */
+/* | |________| |-->| to |-->| BPF |-->| | |________| 0 */
+/* | | Mono | |_____| |___________| \--> */
+/* | |________| */
+/* | _________ 0 */
+/* | | | | */
+/* |----------------------------------------------------| Volume |-----------------| */
+/* | Control | */
+/* |_________| */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVDBE_SUCCESS Succeeded */
+/* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* 1. The input and output data must be 32-bit format. The input is scaled by a shift */
+/* when converting from 16-bit format, this scaling allows for internal headroom in the */
+/* bass enhancement algorithm. */
+/* 2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with */
+/* the headroom loss. This headroom loss is compensated in the volume control so the */
+/* overall end to end gain is odB. */
+/* */
+/********************************************************************************************/
+
+LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+
+ LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
+ LVM_INT32 *pScratch = (LVM_INT32 *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
+ LVM_INT32 *pMono = (LVM_INT32 *)pOutData;
+ LVM_INT16 *pInput = (LVM_INT16 *)pInData;
+
+
+ /*
+ * Check the number of samples is not too large
+ */
+ if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+ {
+ return(LVDBE_TOOMANYSAMPLES);
+ }
+
+ /*
+ * Check if the algorithm is enabled
+ */
+ if ((pInstance->Params.OperatingMode != LVDBE_OFF) ||
+ (pInstance->bTransitionOnToOff == LVM_TRUE))
+ {
+
+ /*
+ * Convert 16-bit samples to 32-bit and scale
+ * (For a 16-bit implementation apply headroom loss here)
+ */
+ Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data */
+ pScratch, /* Destination 32-bit data */
+ (LVM_INT16)(2*NumSamples), /* Left and right */
+ LVDBE_SCALESHIFT); /* Shift scale */
+
+
+ /*
+ * Apply the high pass filter if selected
+ */
+ if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
+ {
+ BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
+ (LVM_INT32 *)pScratch, /* Source */
+ (LVM_INT32 *)pScratch, /* Destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
+ }
+
+
+ /*
+ * Create the mono stream
+ */
+ From2iToMono_32(pScratch, /* Stereo source */
+ pMono, /* Mono destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
+
+
+ /*
+ * Apply the band pass filter
+ */
+ BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
+ (LVM_INT32 *)pMono, /* Source */
+ (LVM_INT32 *)pMono, /* Destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
+
+
+ /*
+ * Apply the AGC and mix
+ */
+ AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
+ pScratch, /* Stereo source */
+ pMono, /* Mono band pass source */
+ pScratch, /* Stereo destination */
+ NumSamples); /* Number of samples */
+
+ if(pInstance->bTransitionOnToOff == LVM_TRUE)
+ {
+ if ((pInstance->pData->AGCInstance.AGC_Gain == pInstance->pData->AGCInstance.AGC_Target)&&
+ (pInstance->pData->AGCInstance.AGC_Gain == 0))
+ {
+ pInstance->bTransitionOnToOff = LVM_FALSE;
+ }
+ }
+
+
+
+ /*
+ * Convert 32-bit samples to 16-bit and saturate
+ * (Not required for 16-bit implemenations)
+ */
+ Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */
+ pOutData, /* Destination 16-bit data */
+ (LVM_INT16)(2*NumSamples), /* Left and right */
+ LVDBE_SCALESHIFT); /* Shift scale */
+
+ }
+ else
+ {
+
+ /*
+ * The algorithm is disabled but volume management is required to compensate for
+ * headroom and volume (if enabled)
+ */
+ LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
+ pInData,
+ pOutData,
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+
+ }
+
+ return(LVDBE_SUCCESS);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
new file mode 100755
index 0000000..da8ca5a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1009 $
+ $Date: 2010-06-28 14:14:15 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVDBE.h"
+#include "LVDBE_Coeffs.h" /* Filter coefficients */
+#include "BIQUAD.h"
+
+
+/************************************************************************************/
+/* */
+/* Coefficients constant table */
+/* */
+/************************************************************************************/
+
+/*
+ * High Pass Filter Coefficient table
+ */
+const BQ_C32_Coefs_t LVDBE_HPF_Table[] = {
+ /* Coefficients for 55Hz centre frequency */
+ {HPF_Fs8000_Fc55_A2, /* 8kS/s coefficients */
+ HPF_Fs8000_Fc55_A1,
+ HPF_Fs8000_Fc55_A0,
+ -HPF_Fs8000_Fc55_B2,
+ -HPF_Fs8000_Fc55_B1},
+ {HPF_Fs11025_Fc55_A2, /* 11kS/s coefficients */
+ HPF_Fs11025_Fc55_A1,
+ HPF_Fs11025_Fc55_A0,
+ -HPF_Fs11025_Fc55_B2,
+ -HPF_Fs11025_Fc55_B1},
+ {HPF_Fs12000_Fc55_A2, /* 12kS/s coefficients */
+ HPF_Fs12000_Fc55_A1,
+ HPF_Fs12000_Fc55_A0,
+ -HPF_Fs12000_Fc55_B2,
+ -HPF_Fs12000_Fc55_B1},
+ {HPF_Fs16000_Fc55_A2, /* 16kS/s coefficients */
+ HPF_Fs16000_Fc55_A1,
+ HPF_Fs16000_Fc55_A0,
+ -HPF_Fs16000_Fc55_B2,
+ -HPF_Fs16000_Fc55_B1},
+ {HPF_Fs22050_Fc55_A2, /* 22kS/s coefficients */
+ HPF_Fs22050_Fc55_A1,
+ HPF_Fs22050_Fc55_A0,
+ -HPF_Fs22050_Fc55_B2,
+ -HPF_Fs22050_Fc55_B1},
+ {HPF_Fs24000_Fc55_A2, /* 24kS/s coefficients */
+ HPF_Fs24000_Fc55_A1,
+ HPF_Fs24000_Fc55_A0,
+ -HPF_Fs24000_Fc55_B2,
+ -HPF_Fs24000_Fc55_B1},
+ {HPF_Fs32000_Fc55_A2, /* 32kS/s coefficients */
+ HPF_Fs32000_Fc55_A1,
+ HPF_Fs32000_Fc55_A0,
+ -HPF_Fs32000_Fc55_B2,
+ -HPF_Fs32000_Fc55_B1},
+ {HPF_Fs44100_Fc55_A2, /* 44kS/s coefficients */
+ HPF_Fs44100_Fc55_A1,
+ HPF_Fs44100_Fc55_A0,
+ -HPF_Fs44100_Fc55_B2,
+ -HPF_Fs44100_Fc55_B1},
+ {HPF_Fs48000_Fc55_A2, /* 48kS/s coefficients */
+ HPF_Fs48000_Fc55_A1,
+ HPF_Fs48000_Fc55_A0,
+ -HPF_Fs48000_Fc55_B2,
+ -HPF_Fs48000_Fc55_B1},
+
+ /* Coefficients for 66Hz centre frequency */
+ {HPF_Fs8000_Fc66_A2, /* 8kS/s coefficients */
+ HPF_Fs8000_Fc66_A1,
+ HPF_Fs8000_Fc66_A0,
+ -HPF_Fs8000_Fc66_B2,
+ -HPF_Fs8000_Fc66_B1},
+ {HPF_Fs11025_Fc66_A2, /* 11kS/s coefficients */
+ HPF_Fs11025_Fc66_A1,
+ HPF_Fs11025_Fc66_A0,
+ -HPF_Fs11025_Fc66_B2,
+ -HPF_Fs11025_Fc66_B1},
+ {HPF_Fs12000_Fc66_A2, /* 12kS/s coefficients */
+ HPF_Fs12000_Fc66_A1,
+ HPF_Fs12000_Fc66_A0,
+ -HPF_Fs12000_Fc66_B2,
+ -HPF_Fs12000_Fc66_B1},
+ {HPF_Fs16000_Fc66_A2, /* 16kS/s coefficients */
+ HPF_Fs16000_Fc66_A1,
+ HPF_Fs16000_Fc66_A0,
+ -HPF_Fs16000_Fc66_B2,
+ -HPF_Fs16000_Fc66_B1},
+ {HPF_Fs22050_Fc66_A2, /* 22kS/s coefficients */
+ HPF_Fs22050_Fc66_A1,
+ HPF_Fs22050_Fc66_A0,
+ -HPF_Fs22050_Fc66_B2,
+ -HPF_Fs22050_Fc66_B1},
+ {HPF_Fs24000_Fc66_A2, /* 24kS/s coefficients */
+ HPF_Fs24000_Fc66_A1,
+ HPF_Fs24000_Fc66_A0,
+ -HPF_Fs24000_Fc66_B2,
+ -HPF_Fs24000_Fc66_B1},
+ {HPF_Fs32000_Fc66_A2, /* 32kS/s coefficients */
+ HPF_Fs32000_Fc66_A1,
+ HPF_Fs32000_Fc66_A0,
+ -HPF_Fs32000_Fc66_B2,
+ -HPF_Fs32000_Fc66_B1},
+ {HPF_Fs44100_Fc66_A2, /* 44kS/s coefficients */
+ HPF_Fs44100_Fc66_A1,
+ HPF_Fs44100_Fc66_A0,
+ -HPF_Fs44100_Fc66_B2,
+ -HPF_Fs44100_Fc66_B1},
+ {HPF_Fs48000_Fc66_A2, /* 48kS/s coefficients */
+ HPF_Fs48000_Fc66_A1,
+ HPF_Fs48000_Fc66_A0,
+ -HPF_Fs48000_Fc66_B2,
+ -HPF_Fs48000_Fc66_B1},
+
+ /* Coefficients for 78Hz centre frequency */
+ {HPF_Fs8000_Fc78_A2, /* 8kS/s coefficients */
+ HPF_Fs8000_Fc78_A1,
+ HPF_Fs8000_Fc78_A0,
+ -HPF_Fs8000_Fc78_B2,
+ -HPF_Fs8000_Fc78_B1},
+ {HPF_Fs11025_Fc78_A2, /* 11kS/s coefficients */
+ HPF_Fs11025_Fc78_A1,
+ HPF_Fs11025_Fc78_A0,
+ -HPF_Fs11025_Fc78_B2,
+ -HPF_Fs11025_Fc78_B1},
+ {HPF_Fs12000_Fc78_A2, /* 12kS/s coefficients */
+ HPF_Fs12000_Fc78_A1,
+ HPF_Fs12000_Fc78_A0,
+ -HPF_Fs12000_Fc78_B2,
+ -HPF_Fs12000_Fc78_B1},
+ {HPF_Fs16000_Fc78_A2, /* 16kS/s coefficients */
+ HPF_Fs16000_Fc78_A1,
+ HPF_Fs16000_Fc78_A0,
+ -HPF_Fs16000_Fc78_B2,
+ -HPF_Fs16000_Fc78_B1},
+ {HPF_Fs22050_Fc78_A2, /* 22kS/s coefficients */
+ HPF_Fs22050_Fc78_A1,
+ HPF_Fs22050_Fc78_A0,
+ -HPF_Fs22050_Fc78_B2,
+ -HPF_Fs22050_Fc78_B1},
+ {HPF_Fs24000_Fc78_A2, /* 24kS/s coefficients */
+ HPF_Fs24000_Fc78_A1,
+ HPF_Fs24000_Fc78_A0,
+ -HPF_Fs24000_Fc78_B2,
+ -HPF_Fs24000_Fc78_B1},
+ {HPF_Fs32000_Fc78_A2, /* 32kS/s coefficients */
+ HPF_Fs32000_Fc78_A1,
+ HPF_Fs32000_Fc78_A0,
+ -HPF_Fs32000_Fc78_B2,
+ -HPF_Fs32000_Fc78_B1},
+ {HPF_Fs44100_Fc78_A2, /* 44kS/s coefficients */
+ HPF_Fs44100_Fc78_A1,
+ HPF_Fs44100_Fc78_A0,
+ -HPF_Fs44100_Fc78_B2,
+ -HPF_Fs44100_Fc78_B1},
+ {HPF_Fs48000_Fc78_A2, /* 48kS/s coefficients */
+ HPF_Fs48000_Fc78_A1,
+ HPF_Fs48000_Fc78_A0,
+ -HPF_Fs48000_Fc78_B2,
+ -HPF_Fs48000_Fc78_B1},
+
+ /* Coefficients for 90Hz centre frequency */
+ {HPF_Fs8000_Fc90_A2, /* 8kS/s coefficients */
+ HPF_Fs8000_Fc90_A1,
+ HPF_Fs8000_Fc90_A0,
+ -HPF_Fs8000_Fc90_B2,
+ -HPF_Fs8000_Fc90_B1},
+ {HPF_Fs11025_Fc90_A2, /* 11kS/s coefficients */
+ HPF_Fs11025_Fc90_A1,
+ HPF_Fs11025_Fc90_A0,
+ -HPF_Fs11025_Fc90_B2,
+ -HPF_Fs11025_Fc90_B1},
+ {HPF_Fs12000_Fc90_A2, /* 12kS/s coefficients */
+ HPF_Fs12000_Fc90_A1,
+ HPF_Fs12000_Fc90_A0,
+ -HPF_Fs12000_Fc90_B2,
+ -HPF_Fs12000_Fc90_B1},
+ {HPF_Fs16000_Fc90_A2, /* 16kS/s coefficients */
+ HPF_Fs16000_Fc90_A1,
+ HPF_Fs16000_Fc90_A0,
+ -HPF_Fs16000_Fc90_B2,
+ -HPF_Fs16000_Fc90_B1},
+ {HPF_Fs22050_Fc90_A2, /* 22kS/s coefficients */
+ HPF_Fs22050_Fc90_A1,
+ HPF_Fs22050_Fc90_A0,
+ -HPF_Fs22050_Fc90_B2,
+ -HPF_Fs22050_Fc90_B1},
+ {HPF_Fs24000_Fc90_A2, /* 24kS/s coefficients */
+ HPF_Fs24000_Fc90_A1,
+ HPF_Fs24000_Fc90_A0,
+ -HPF_Fs24000_Fc90_B2,
+ -HPF_Fs24000_Fc90_B1},
+ {HPF_Fs32000_Fc90_A2, /* 32kS/s coefficients */
+ HPF_Fs32000_Fc90_A1,
+ HPF_Fs32000_Fc90_A0,
+ -HPF_Fs32000_Fc90_B2,
+ -HPF_Fs32000_Fc90_B1},
+ {HPF_Fs44100_Fc90_A2, /* 44kS/s coefficients */
+ HPF_Fs44100_Fc90_A1,
+ HPF_Fs44100_Fc90_A0,
+ -HPF_Fs44100_Fc90_B2,
+ -HPF_Fs44100_Fc90_B1},
+ {HPF_Fs48000_Fc90_A2, /* 48kS/s coefficients */
+ HPF_Fs48000_Fc90_A1,
+ HPF_Fs48000_Fc90_A0,
+ -HPF_Fs48000_Fc90_B2,
+ -HPF_Fs48000_Fc90_B1}};
+
+/*
+ * Band Pass Filter coefficient table
+ */
+const BP_C32_Coefs_t LVDBE_BPF_Table[] = {
+ /* Coefficients for 55Hz centre frequency */
+ {BPF_Fs8000_Fc55_A0, /* 8kS/s coefficients */
+ -BPF_Fs8000_Fc55_B2,
+ -BPF_Fs8000_Fc55_B1},
+ {BPF_Fs11025_Fc55_A0, /* 11kS/s coefficients */
+ -BPF_Fs11025_Fc55_B2,
+ -BPF_Fs11025_Fc55_B1},
+ {BPF_Fs12000_Fc55_A0, /* 12kS/s coefficients */
+ -BPF_Fs12000_Fc55_B2,
+ -BPF_Fs12000_Fc55_B1},
+ {BPF_Fs16000_Fc55_A0, /* 16kS/s coefficients */
+ -BPF_Fs16000_Fc55_B2,
+ -BPF_Fs16000_Fc55_B1},
+ {BPF_Fs22050_Fc55_A0, /* 22kS/s coefficients */
+ -BPF_Fs22050_Fc55_B2,
+ -BPF_Fs22050_Fc55_B1},
+ {BPF_Fs24000_Fc55_A0, /* 24kS/s coefficients */
+ -BPF_Fs24000_Fc55_B2,
+ -BPF_Fs24000_Fc55_B1},
+ {BPF_Fs32000_Fc55_A0, /* 32kS/s coefficients */
+ -BPF_Fs32000_Fc55_B2,
+ -BPF_Fs32000_Fc55_B1},
+ {BPF_Fs44100_Fc55_A0, /* 44kS/s coefficients */
+ -BPF_Fs44100_Fc55_B2,
+ -BPF_Fs44100_Fc55_B1},
+ {BPF_Fs48000_Fc55_A0, /* 48kS/s coefficients */
+ -BPF_Fs48000_Fc55_B2,
+ -BPF_Fs48000_Fc55_B1},
+
+ /* Coefficients for 66Hz centre frequency */
+ {BPF_Fs8000_Fc66_A0, /* 8kS/s coefficients */
+ -BPF_Fs8000_Fc66_B2,
+ -BPF_Fs8000_Fc66_B1},
+ {BPF_Fs11025_Fc66_A0, /* 11kS/s coefficients */
+ -BPF_Fs11025_Fc66_B2,
+ -BPF_Fs11025_Fc66_B1},
+ {BPF_Fs12000_Fc66_A0, /* 12kS/s coefficients */
+ -BPF_Fs12000_Fc66_B2,
+ -BPF_Fs12000_Fc66_B1},
+ {BPF_Fs16000_Fc66_A0, /* 16kS/s coefficients */
+ -BPF_Fs16000_Fc66_B2,
+ -BPF_Fs16000_Fc66_B1},
+ {BPF_Fs22050_Fc66_A0, /* 22kS/s coefficients */
+ -BPF_Fs22050_Fc66_B2,
+ -BPF_Fs22050_Fc66_B1},
+ {BPF_Fs24000_Fc66_A0, /* 24kS/s coefficients */
+ -BPF_Fs24000_Fc66_B2,
+ -BPF_Fs24000_Fc66_B1},
+ {BPF_Fs32000_Fc66_A0, /* 32kS/s coefficients */
+ -BPF_Fs32000_Fc66_B2,
+ -BPF_Fs32000_Fc66_B1},
+ {BPF_Fs44100_Fc66_A0, /* 44kS/s coefficients */
+ -BPF_Fs44100_Fc66_B2,
+ -BPF_Fs44100_Fc66_B1},
+ {BPF_Fs48000_Fc66_A0, /* 48kS/s coefficients */
+ -BPF_Fs48000_Fc66_B2,
+ -BPF_Fs48000_Fc66_B1},
+
+ /* Coefficients for 78Hz centre frequency */
+ {BPF_Fs8000_Fc78_A0, /* 8kS/s coefficients */
+ -BPF_Fs8000_Fc78_B2,
+ -BPF_Fs8000_Fc78_B1},
+ {BPF_Fs11025_Fc78_A0, /* 11kS/s coefficients */
+ -BPF_Fs11025_Fc78_B2,
+ -BPF_Fs11025_Fc78_B1},
+ {BPF_Fs12000_Fc78_A0, /* 12kS/s coefficients */
+ -BPF_Fs12000_Fc78_B2,
+ -BPF_Fs12000_Fc78_B1},
+ {BPF_Fs16000_Fc78_A0, /* 16kS/s coefficients */
+ -BPF_Fs16000_Fc78_B2,
+ -BPF_Fs16000_Fc78_B1},
+ {BPF_Fs22050_Fc78_A0, /* 22kS/s coefficients */
+ -BPF_Fs22050_Fc78_B2,
+ -BPF_Fs22050_Fc78_B1},
+ {BPF_Fs24000_Fc78_A0, /* 24kS/s coefficients */
+ -BPF_Fs24000_Fc78_B2,
+ -BPF_Fs24000_Fc78_B1},
+ {BPF_Fs32000_Fc78_A0, /* 32kS/s coefficients */
+ -BPF_Fs32000_Fc78_B2,
+ -BPF_Fs32000_Fc78_B1},
+ {BPF_Fs44100_Fc78_A0, /* 44kS/s coefficients */
+ -BPF_Fs44100_Fc78_B2,
+ -BPF_Fs44100_Fc78_B1},
+ {BPF_Fs48000_Fc78_A0, /* 48kS/s coefficients */
+ -BPF_Fs48000_Fc78_B2,
+ -BPF_Fs48000_Fc78_B1},
+
+ /* Coefficients for 90Hz centre frequency */
+ {BPF_Fs8000_Fc90_A0, /* 8kS/s coefficients */
+ -BPF_Fs8000_Fc90_B2,
+ -BPF_Fs8000_Fc90_B1},
+ {BPF_Fs11025_Fc90_A0, /* 11kS/s coefficients */
+ -BPF_Fs11025_Fc90_B2,
+ -BPF_Fs11025_Fc90_B1},
+ {BPF_Fs12000_Fc90_A0, /* 12kS/s coefficients */
+ -BPF_Fs12000_Fc90_B2,
+ -BPF_Fs12000_Fc90_B1},
+ {BPF_Fs16000_Fc90_A0, /* 16kS/s coefficients */
+ -BPF_Fs16000_Fc90_B2,
+ -BPF_Fs16000_Fc90_B1},
+ {BPF_Fs22050_Fc90_A0, /* 22kS/s coefficients */
+ -BPF_Fs22050_Fc90_B2,
+ -BPF_Fs22050_Fc90_B1},
+ {BPF_Fs24000_Fc90_A0, /* 24kS/s coefficients */
+ -BPF_Fs24000_Fc90_B2,
+ -BPF_Fs24000_Fc90_B1},
+ {BPF_Fs32000_Fc90_A0, /* 32kS/s coefficients */
+ -BPF_Fs32000_Fc90_B2,
+ -BPF_Fs32000_Fc90_B1},
+ {BPF_Fs44100_Fc90_A0, /* 44kS/s coefficients */
+ -BPF_Fs44100_Fc90_B2,
+ -BPF_Fs44100_Fc90_B1},
+ {BPF_Fs48000_Fc90_A0, /* 48kS/s coefficients */
+ -BPF_Fs48000_Fc90_B2,
+ -BPF_Fs48000_Fc90_B1}};
+
+
+/************************************************************************************/
+/* */
+/* AGC constant tables */
+/* */
+/************************************************************************************/
+
+/* Attack time (signal too large) */
+const LVM_INT16 LVDBE_AGC_ATTACK_Table[] = {
+ AGC_ATTACK_Fs8000,
+ AGC_ATTACK_Fs11025,
+ AGC_ATTACK_Fs12000,
+ AGC_ATTACK_Fs16000,
+ AGC_ATTACK_Fs22050,
+ AGC_ATTACK_Fs24000,
+ AGC_ATTACK_Fs32000,
+ AGC_ATTACK_Fs44100,
+ AGC_ATTACK_Fs48000};
+
+/* Decay time (signal too small) */
+const LVM_INT16 LVDBE_AGC_DECAY_Table[] = {
+ AGC_DECAY_Fs8000,
+ AGC_DECAY_Fs11025,
+ AGC_DECAY_Fs12000,
+ AGC_DECAY_Fs16000,
+ AGC_DECAY_Fs22050,
+ AGC_DECAY_Fs24000,
+ AGC_DECAY_Fs32000,
+ AGC_DECAY_Fs44100,
+ AGC_DECAY_Fs48000};
+
+/* Gain for use without the high pass filter */
+const LVM_INT32 LVDBE_AGC_GAIN_Table[] = {
+ AGC_GAIN_0dB,
+ AGC_GAIN_1dB,
+ AGC_GAIN_2dB,
+ AGC_GAIN_3dB,
+ AGC_GAIN_4dB,
+ AGC_GAIN_5dB,
+ AGC_GAIN_6dB,
+ AGC_GAIN_7dB,
+ AGC_GAIN_8dB,
+ AGC_GAIN_9dB,
+ AGC_GAIN_10dB,
+ AGC_GAIN_11dB,
+ AGC_GAIN_12dB,
+ AGC_GAIN_13dB,
+ AGC_GAIN_14dB,
+ AGC_GAIN_15dB};
+
+/* Gain for use with the high pass filter */
+const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[] = {
+ AGC_HPFGAIN_0dB,
+ AGC_HPFGAIN_1dB,
+ AGC_HPFGAIN_2dB,
+ AGC_HPFGAIN_3dB,
+ AGC_HPFGAIN_4dB,
+ AGC_HPFGAIN_5dB,
+ AGC_HPFGAIN_6dB,
+ AGC_HPFGAIN_7dB,
+ AGC_HPFGAIN_8dB,
+ AGC_HPFGAIN_9dB,
+ AGC_HPFGAIN_10dB,
+ AGC_HPFGAIN_11dB,
+ AGC_HPFGAIN_12dB,
+ AGC_HPFGAIN_13dB,
+ AGC_HPFGAIN_14dB,
+ AGC_HPFGAIN_15dB};
+
+
+/************************************************************************************/
+/* */
+/* Volume control gain and time constant tables */
+/* */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+const LVM_INT16 LVDBE_VolumeTable[] = {
+ 0x4000, /* -6dB */
+ 0x47FB, /* -5dB */
+ 0x50C3, /* -4dB */
+ 0x5A9E, /* -3dB */
+ 0x65AD, /* -2dB */
+ 0x7215, /* -1dB */
+ 0x7FFF}; /* 0dB */
+
+const LVM_INT16 LVDBE_VolumeTCTable[] = {
+ VOL_TC_Fs8000,
+ VOL_TC_Fs11025,
+ VOL_TC_Fs12000,
+ VOL_TC_Fs16000,
+ VOL_TC_Fs22050,
+ VOL_TC_Fs24000,
+ VOL_TC_Fs32000,
+ VOL_TC_Fs44100,
+ VOL_TC_Fs48000};
+
+const LVM_INT16 LVDBE_MixerTCTable[] = {
+ MIX_TC_Fs8000,
+ MIX_TC_Fs11025,
+ MIX_TC_Fs12000,
+ MIX_TC_Fs16000,
+ MIX_TC_Fs22050,
+ MIX_TC_Fs24000,
+ MIX_TC_Fs32000,
+ MIX_TC_Fs44100,
+ MIX_TC_Fs48000};
+
+
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
new file mode 100755
index 0000000..4cb6d21
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Tables.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1009 $
+ $Date: 2010-06-28 14:14:15 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+#ifndef __LVBDE_TABLES_H__
+#define __LVBDE_TABLES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "BIQUAD.h"
+#include "LVM_Types.h"
+
+/************************************************************************************/
+/* */
+/* Coefficients constant table */
+/* */
+/************************************************************************************/
+
+/*
+ * High Pass Filter Coefficient table
+ */
+extern const BQ_C32_Coefs_t LVDBE_HPF_Table[];
+
+/*
+ * Band Pass Filter coefficient table
+ */
+extern const BP_C32_Coefs_t LVDBE_BPF_Table[];
+
+/************************************************************************************/
+/* */
+/* AGC constant tables */
+/* */
+/************************************************************************************/
+
+/* Attack time (signal too large) */
+extern const LVM_INT16 LVDBE_AGC_ATTACK_Table[];
+
+/* Decay time (signal too small) */
+extern const LVM_INT16 LVDBE_AGC_DECAY_Table[];
+
+/* Gain for use without the high pass filter */
+extern const LVM_INT32 LVDBE_AGC_GAIN_Table[];
+
+/* Gain for use with the high pass filter */
+extern const LVM_INT32 LVDBE_AGC_HPFGAIN_Table[];
+
+/************************************************************************************/
+/* */
+/* Volume control gain and time constant tables */
+/* */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+extern const LVM_INT16 LVDBE_VolumeTable[];
+
+extern const LVM_INT16 LVDBE_VolumeTCTable[];
+
+extern const LVM_INT16 LVDBE_MixerTCTable[];
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVBDE_TABLES_H__ */
diff --git a/media/libeffects/lvm/lib/Bundle/lib/LVM.h b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
new file mode 100755
index 0000000..d472182
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*****************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1002 $
+ $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the application layer interface of Concert Sound, Bass Enhancement, */
+/* Equalizer, Power Spectrum Analyzer, Trebble Enhancement and volume management */
+/* bundle. */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the calling layer. All other types, structures and */
+/* functions are private. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 1 */
+/* ======= */
+/* The algorithm can execute either with separate input and output buffers or with */
+/* a common buffer, i.e. the data is processed in-place. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 2 */
+/* ======= */
+/* Three data formats are support Stereo,Mono-In-Stereo and Mono. The data is */
+/* interleaved as follows: */
+/* */
+/* Byte Offset Stereo Input Mono-In-Stereo Input Mono Input */
+/* =========== ============ ==================== ============== */
+/* 0 Left Sample #1 Mono Sample #1 Mono Sample #1 */
+/* 2 Right Sample #1 Mono Sample #1 Mono Sample #2 */
+/* 4 Left Sample #2 Mono Sample #2 Mono Sample #3 */
+/* 6 Right Sample #2 Mono Sample #2 Mono Sample #4 */
+/* . . . . */
+/* . . . . */
+/* */
+/****************************************************************************************/
+
+#ifndef __LVM_H__
+#define __LVM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+
+/* Memory table*/
+#define LVM_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+/* Concert Sound effect level presets */
+#define LVM_CS_EFFECT_NONE 0 /* 0% effect, minimum value */
+#define LVM_CS_EFFECT_LOW 16384 /* 50% effect */
+#define LVM_CS_EFFECT_MED 24576 /* 75% effect */
+#define LVM_CS_EFFECT_HIGH 32767 /* 100% effect, maximum value */
+
+/* Treble enhancement */
+#define LVM_TE_LOW_MIPS 32767
+
+/* Bass enhancement effect level presets */
+#define LVM_BE_0DB 0 /* 0dB boost, no effect */
+#define LVM_BE_3DB 3 /* +3dB boost */
+#define LVM_BE_6DB 6 /* +6dB boost */
+#define LVM_BE_9DB 9 /* +9dB boost */
+#define LVM_BE_12DB 12 /* +12dB boost */
+#define LVM_BE_15DB 15 /* +15dB boost */
+
+/* N-Band Equalizer */
+#define LVM_EQ_NBANDS 5 /* Number of bands for equalizer */
+
+/* Headroom management */
+#define LVM_HEADROOM_MAX_NBANDS 5
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVM_Handle_t;
+
+
+/* Status return values */
+typedef enum
+{
+ LVM_SUCCESS = 0, /* Successful return from a routine */
+ LVM_ALIGNMENTERROR = 1, /* Memory alignment error */
+ LVM_NULLADDRESS = 2, /* NULL allocation address */
+ LVM_OUTOFRANGE = 3, /* Out of range control parameter */
+ LVM_INVALIDNUMSAMPLES = 4, /* Invalid number of samples */
+ LVM_WRONGAUDIOTIME = 5, /* Wrong time value for audio time*/
+ LVM_ALGORITHMDISABLED = 6, /* Algorithm is disabled*/
+ LVM_ALGORITHMPSA = 7, /* Algorithm PSA returns an error */
+ LVM_RETURNSTATUS_DUMMY = LVM_MAXENUM
+} LVM_ReturnStatus_en;
+
+
+/* Buffer Management mode */
+typedef enum
+{
+ LVM_MANAGED_BUFFERS = 0,
+ LVM_UNMANAGED_BUFFERS = 1,
+ LVM_BUFFERS_DUMMY = LVM_MAXENUM
+} LVM_BufferMode_en;
+
+/* Output device type */
+typedef enum
+{
+ LVM_HEADPHONES = 0,
+ LVM_EX_HEADPHONES = 1,
+ LVM_SPEAKERTYPE_MAX = LVM_MAXENUM
+} LVM_OutputDeviceType_en;
+
+/* Virtualizer mode selection*/
+typedef enum
+{
+ LVM_CONCERTSOUND = 0,
+ LVM_VIRTUALIZERTYPE_DUMMY = LVM_MAXENUM
+} LVM_VirtualizerType_en;
+
+/* N-Band Equaliser operating mode */
+typedef enum
+{
+ LVM_EQNB_OFF = 0,
+ LVM_EQNB_ON = 1,
+ LVM_EQNB_DUMMY = LVM_MAXENUM
+} LVM_EQNB_Mode_en;
+
+/* Bass Enhancement operating mode */
+typedef enum
+{
+ LVM_BE_OFF = 0,
+ LVM_BE_ON = 1,
+ LVM_BE_DUMMY = LVM_MAXENUM
+} LVM_BE_Mode_en;
+
+/* Bass Enhancement centre frequency selection control */
+typedef enum
+{
+ LVM_BE_CENTRE_55Hz = 0,
+ LVM_BE_CENTRE_66Hz = 1,
+ LVM_BE_CENTRE_78Hz = 2,
+ LVM_BE_CENTRE_90Hz = 3,
+ LVM_BE_CENTRE_DUMMY = LVM_MAXENUM
+} LVM_BE_CentreFreq_en;
+
+/* Bass Enhancement HPF selection control */
+typedef enum
+{
+ LVM_BE_HPF_OFF = 0,
+ LVM_BE_HPF_ON = 1,
+ LVM_BE_HPF_DUMMY = LVM_MAXENUM
+} LVM_BE_FilterSelect_en;
+
+/* Volume Control operating mode */
+typedef enum
+{
+ LVM_VC_OFF = 0,
+ LVM_VC_ON = 1,
+ LVM_VC_DUMMY = LVM_MAXENUM
+} LVM_VC_Mode_en;
+
+/* Treble Enhancement operating mode */
+typedef enum
+{
+ LVM_TE_OFF = 0,
+ LVM_TE_ON = 1,
+ LVM_TE_DUMMY = LVM_MAXENUM
+} LVM_TE_Mode_en;
+
+/* Headroom management operating mode */
+typedef enum
+{
+ LVM_HEADROOM_OFF = 0,
+ LVM_HEADROOM_ON = 1,
+ LVM_Headroom_DUMMY = LVM_MAXENUM
+} LVM_Headroom_Mode_en;
+
+typedef enum
+{
+ LVM_PSA_SPEED_SLOW, /* Peak decaying at slow speed */
+ LVM_PSA_SPEED_MEDIUM, /* Peak decaying at medium speed */
+ LVM_PSA_SPEED_FAST, /* Peak decaying at fast speed */
+ LVM_PSA_SPEED_DUMMY = LVM_MAXENUM
+} LVM_PSA_DecaySpeed_en;
+
+typedef enum
+{
+ LVM_PSA_OFF = 0,
+ LVM_PSA_ON = 1,
+ LVM_PSA_DUMMY = LVM_MAXENUM
+} LVM_PSA_Mode_en;
+
+/* Version information */
+typedef struct
+{
+ LVM_CHAR *pVersionNumber; /* Pointer to the version number in the format X.YY.ZZ */
+ LVM_CHAR *pPlatform; /* Pointer to the library platform type */
+} LVM_VersionInfo_st;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVM_MemTab_t;
+
+/* N-Band equaliser band definition */
+typedef struct
+{
+ LVM_INT16 Gain; /* Band gain in dB */
+ LVM_UINT16 Frequency; /* Band centre frequency in Hz */
+ LVM_UINT16 QFactor; /* Band quality factor (x100) */
+} LVM_EQNB_BandDef_t;
+
+
+/* Headroom band definition */
+typedef struct
+{
+ LVM_UINT16 Limit_Low; /* Low frequency limit of the band in Hertz */
+ LVM_UINT16 Limit_High; /* High frequency limit of the band in Hertz */
+ LVM_INT16 Headroom_Offset; /* Headroom = biggest band gain - Headroom_Offset */
+} LVM_HeadroomBandDef_t;
+
+
+/* Control Parameter structure */
+typedef struct
+{
+ /* General parameters */
+ LVM_Mode_en OperatingMode; /* Bundle operating mode On/Bypass */
+ LVM_Fs_en SampleRate; /* Sample rate */
+ LVM_Format_en SourceFormat; /* Input data format */
+ LVM_OutputDeviceType_en SpeakerType; /* Output device type */
+
+ /* Concert Sound Virtualizer parameters*/
+ LVM_Mode_en VirtualizerOperatingMode; /* Virtualizer operating mode On/Off */
+ LVM_VirtualizerType_en VirtualizerType; /* Virtualizer type: ConcertSound */
+ LVM_UINT16 VirtualizerReverbLevel; /* Virtualizer reverb level in % */
+ LVM_INT16 CS_EffectLevel; /* Concert Sound effect level */
+
+ /* N-Band Equaliser parameters */
+ LVM_EQNB_Mode_en EQNB_OperatingMode; /* N-Band Equaliser operating mode */
+ LVM_UINT16 EQNB_NBands; /* Number of bands */
+ LVM_EQNB_BandDef_t *pEQNB_BandDefinition; /* Pointer to equaliser definitions */
+
+ /* Bass Enhancement parameters */
+ LVM_BE_Mode_en BE_OperatingMode; /* Bass Enhancement operating mode */
+ LVM_INT16 BE_EffectLevel; /* Bass Enhancement effect level */
+ LVM_BE_CentreFreq_en BE_CentreFreq; /* Bass Enhancement centre frequency */
+ LVM_BE_FilterSelect_en BE_HPF; /* Bass Enhancement high pass filter selector */
+
+ /* Volume Control parameters */
+ LVM_INT16 VC_EffectLevel; /* Volume Control setting in dBs */
+ LVM_INT16 VC_Balance; /* Left Right Balance control in dB (-96 to 96 dB), -ve values reduce
+ Right channel while +ve value reduces Left channel*/
+
+ /* Treble Enhancement parameters */
+ LVM_TE_Mode_en TE_OperatingMode; /* Treble Enhancement On/Off */
+ LVM_INT16 TE_EffectLevel; /* Treble Enhancement gain dBs */
+
+ /* Spectrum Analyzer parameters Control */
+ LVM_PSA_Mode_en PSA_Enable;
+ LVM_PSA_DecaySpeed_en PSA_PeakDecayRate; /* Peak value decay rate*/
+
+} LVM_ControlParams_t;
+
+
+/* Instance Parameter structure */
+typedef struct
+{
+ /* General */
+ LVM_BufferMode_en BufferMode; /* Buffer management mode */
+ LVM_UINT16 MaxBlockSize; /* Maximum processing block size */
+
+ /* N-Band Equaliser */
+ LVM_UINT16 EQNB_NumBands; /* Maximum number of equaliser bands */
+
+ /* PSA */
+ LVM_PSA_Mode_en PSA_Included; /* Controls the instance memory allocation for PSA: ON/OFF */
+} LVM_InstParams_t;
+
+/* Headroom management parameter structure */
+typedef struct
+{
+ LVM_Headroom_Mode_en Headroom_OperatingMode; /* Headroom Control On/Off */
+ LVM_HeadroomBandDef_t *pHeadroomDefinition; /* Pointer to headroom bands definition */
+ LVM_UINT16 NHeadroomBands; /* Number of headroom bands */
+
+} LVM_HeadroomParams_t;
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetVersionInfo */
+/* */
+/* DESCRIPTION: */
+/* This function is used to retrieve information about the library's version. */
+/* */
+/* PARAMETERS: */
+/* pVersion Pointer to an empty version info structure */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS when pVersion is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetVersionInfo(LVM_VersionInfo_st *pVersion);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetMemoryTable */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pInstParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS When one of pMemoryTable or pInstParams is NULL */
+/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t hInstance,
+ LVM_MemTab_t *pMemoryTable,
+ LVM_InstParams_t *pInstParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetInstanceHandle */
+/* */
+/* DESCRIPTION: */
+/* This function is used to create a bundle instance. It returns the created instance */
+/* handle through phInstance. All parameters are set to their default, inactive state. */
+/* */
+/* PARAMETERS: */
+/* phInstance pointer to the instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pInstParams Pointer to the instance parameters */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Initialisation succeeded */
+/* LVM_NULLADDRESS One or more memory has a NULL pointer */
+/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t *phInstance,
+ LVM_MemTab_t *pMemoryTable,
+ LVM_InstParams_t *pInstParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_ClearAudioBuffers */
+/* */
+/* DESCRIPTION: */
+/* This function is used to clear the internal audio buffers of the bundle. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Initialisation succeeded */
+/* LVM_NULLADDRESS Instance memory has a NULL pointer */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t hInstance);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the LifeVibes module parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS when any of hInstance or pParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t hInstance,
+ LVM_ControlParams_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LifeVibes module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS When hInstance, pParams or any control pointers are NULL */
+/* LVM_OUTOFRANGE When any of the control parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance,
+ LVM_ControlParams_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LifeVibes module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* AudioTime Audio Time of the current input data in milli-seconds */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_INVALIDNUMSAMPLES When the NumSamples is not a valied multiple in unmanaged */
+/* buffer mode */
+/* LVM_ALIGNMENTERROR When either the input our output buffers are not 32-bit */
+/* aligned in unmanaged mode */
+/* LVM_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* 2. Number of samples is defined as follows: */
+/* MONO the number of samples in the block */
+/* MONOINSTEREO the number of sample pairs in the block */
+/* STEREO the number of sample pairs in the block */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples,
+ LVM_UINT32 AudioTime);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetHeadroomParams */
+/* */
+/* DESCRIPTION: */
+/* This function is used to set the automatic headroom management parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pHeadroomParams Pointer to headroom parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_NULLADDRESS When hInstance or pHeadroomParams is NULL */
+/* LVM_SUCCESS Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetHeadroomParams( LVM_Handle_t hInstance,
+ LVM_HeadroomParams_t *pHeadroomParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetHeadroomParams */
+/* */
+/* DESCRIPTION: */
+/* This function is used to get the automatic headroom management parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pHeadroomParams Pointer to headroom parameter structure (output) */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS When hInstance or pHeadroomParams are NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetHeadroomParams( LVM_Handle_t hInstance,
+ LVM_HeadroomParams_t *pHeadroomParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetSpectrum */
+/* */
+/* DESCRIPTION: */
+/* This function is used to retrieve Spectral information at a given Audio time */
+/* for display usage */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pCurrentPeaks Pointer to location where currents peaks are to be saved */
+/* pPastPeaks Pointer to location where past peaks are to be saved */
+/* pCentreFreqs Pointer to location where centre frequency of each band is */
+/* to be saved */
+/* AudioTime Audio time at which the spectral information is needed */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS If any of input addresses are NULL */
+/* LVM_WRONGAUDIOTIME Failure due to audio time error */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetSpectrum( LVM_Handle_t hInstance,
+ LVM_UINT8 *pCurrentPeaks,
+ LVM_UINT8 *pPastPeaks,
+ LVM_INT32 AudioTime);
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetVolumeNoSmoothing */
+/* */
+/* DESCRIPTION: */
+/* This function is used to set output volume without any smoothing */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Control Parameters, only volume value is used here */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS If any of input addresses are NULL */
+/* LVM_OUTOFRANGE When any of the control parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t hInstance,
+ LVM_ControlParams_t *pParams);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVM_H__ */
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
new file mode 100755
index 0000000..2f6fa4c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_API_Specials.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1002 $
+ $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "LVM_Tables.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetSpectrum */
+/* */
+/* DESCRIPTION: */
+/* This function is used to retrieve Spectral information at a given Audio time */
+/* for display usage */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pCurrentPeaks Pointer to location where currents peaks are to be saved */
+/* pPastPeaks Pointer to location where past peaks are to be saved */
+/* AudioTime Audio time at which the spectral information is needed */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS If any of input addresses are NULL */
+/* LVM_WRONGAUDIOTIME Failure due to audio time error */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_GetSpectrum(
+ LVM_Handle_t hInstance,
+ LVM_UINT8 *pCurrentPeaks,
+ LVM_UINT8 *pPastPeaks,
+ LVM_INT32 AudioTime
+ )
+{
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+ pLVPSA_Handle_t *hPSAInstance;
+ LVPSA_RETURN LVPSA_Status;
+
+
+ if(pInstance == LVM_NULL)
+ {
+ return LVM_NULLADDRESS;
+ }
+
+ /*If PSA is not included at the time of instance creation, return without any processing*/
+ if(pInstance->InstParams.PSA_Included!=LVM_PSA_ON)
+ {
+ return LVM_SUCCESS;
+ }
+
+ hPSAInstance = pInstance->hPSAInstance;
+
+ if((pCurrentPeaks == LVM_NULL) ||
+ (pPastPeaks == LVM_NULL))
+ {
+ return LVM_NULLADDRESS;
+ }
+
+
+ /*
+ * Update new parameters if necessary
+ */
+ if (pInstance->ControlPending == LVM_TRUE)
+ {
+ LVM_ApplyNewSettings(hInstance);
+ }
+
+ /* If PSA module is disabled, do nothing */
+ if(pInstance->Params.PSA_Enable==LVM_PSA_OFF)
+ {
+ return LVM_ALGORITHMDISABLED;
+ }
+
+ LVPSA_Status = LVPSA_GetSpectrum(hPSAInstance,
+ (LVPSA_Time) (AudioTime),
+ (LVM_UINT8*) pCurrentPeaks,
+ (LVM_UINT8*) pPastPeaks );
+
+ if(LVPSA_Status != LVPSA_OK)
+ {
+ if(LVPSA_Status == LVPSA_ERROR_WRONGTIME)
+ {
+ return (LVM_ReturnStatus_en) LVM_WRONGAUDIOTIME;
+ }
+ else
+ {
+ return (LVM_ReturnStatus_en) LVM_NULLADDRESS;
+ }
+ }
+
+ return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetVolumeNoSmoothing */
+/* */
+/* DESCRIPTION: */
+/* This function is used to set output volume without any smoothing */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Control Parameters, only volume value is used here */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS If any of input addresses are NULL */
+/* LVM_OUTOFRANGE When any of the control parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_ReturnStatus_en LVM_SetVolumeNoSmoothing( LVM_Handle_t hInstance,
+ LVM_ControlParams_t *pParams)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
+ LVM_ReturnStatus_en Error;
+
+ /*Apply new controls*/
+ Error = LVM_SetControlParameters(hInstance,pParams);
+ pInstance->NoSmoothVolume = LVM_TRUE;
+ return Error;
+}
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
new file mode 100755
index 0000000..7273400
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
@@ -0,0 +1,878 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1316 $
+ $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferManagedIn */
+/* */
+/* DESCRIPTION: */
+/* Full buffer management allowing the user to provide input and output buffers on */
+/* any alignment and with any number of samples. The alignment is corrected within */
+/* the buffer management and the samples are grouped in to blocks of the correct size */
+/* before processing. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pInData - Pointer to the input data stream */
+/* *pToProcess - Pointer to pointer to the start of data processing */
+/* *pProcessed - Pointer to pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferManagedIn(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_INT16 SampleCount; /* Number of samples to be processed this call */
+ LVM_INT16 NumSamples; /* Number of samples in scratch buffer */
+ LVM_INT16 *pStart;
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer;
+ LVM_INT16 *pDest;
+ LVM_INT16 NumChannels =2;
+
+
+ /*
+ * Set the processing address pointers
+ */
+ pBuffer = pInstance->pBufferManagement;
+ pDest = pBuffer->pScratch;
+ *pToProcess = pBuffer->pScratch;
+ *pProcessed = pBuffer->pScratch;
+
+ /*
+ * Check if it is the first call of a block
+ */
+ if (pInstance->SamplesToProcess == 0)
+ {
+ /*
+ * First call for a new block of samples
+ */
+ pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
+ pInstance->pInputSamples = (LVM_INT16 *)pInData;
+ pBuffer->BufferState = LVM_FIRSTCALL;
+ }
+ pStart = pInstance->pInputSamples; /* Pointer to the input samples */
+ pBuffer->SamplesToOutput = 0; /* Samples to output is same as number read for inplace processing */
+
+
+ /*
+ * Calculate the number of samples to process this call and update the buffer state
+ */
+ if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+ {
+ /*
+ * Process the maximum bock size of samples.
+ */
+ SampleCount = pInstance->InternalBlockSize;
+ NumSamples = pInstance->InternalBlockSize;
+ }
+ else
+ {
+ /*
+ * Last call for the block, so calculate how many frames and samples to process
+ */
+ LVM_INT16 NumFrames;
+
+ NumSamples = pInstance->SamplesToProcess;
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+
+ /*
+ * Update the buffer state
+ */
+ if (pBuffer->BufferState == LVM_FIRSTCALL)
+ {
+ pBuffer->BufferState = LVM_FIRSTLASTCALL;
+ }
+ else
+ {
+ pBuffer->BufferState = LVM_LASTCALL;
+ }
+ }
+ *pNumSamples = (LVM_UINT16)SampleCount; /* Set the number of samples to process this call */
+
+
+ /*
+ * Copy samples from the delay buffer as required
+ */
+ if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
+ (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
+ (pBuffer->InDelaySamples != 0))
+ {
+ Copy_16(&pBuffer->InDelayBuffer[0], /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(NumChannels*pBuffer->InDelaySamples)); /* Number of delay samples, left and right */
+ NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
+ pDest += NumChannels * pBuffer->InDelaySamples; /* Update the destination pointer */
+ }
+
+
+ /*
+ * Copy the rest of the samples for this call from the input buffer
+ */
+ if (NumSamples > 0)
+ {
+ Copy_16(pStart, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(NumChannels*NumSamples)); /* Number of input samples */
+ pStart += NumChannels * NumSamples; /* Update the input pointer */
+
+ /*
+ * Update the input data pointer and samples to output
+ */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
+ }
+
+
+ /*
+ * Update the sample count and input pointer
+ */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Update the count of samples */
+ pInstance->pInputSamples = pStart; /* Update input sample pointer */
+
+
+ /*
+ * Save samples to the delay buffer if any left unprocessed
+ */
+ if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
+ (pBuffer->BufferState == LVM_LASTCALL))
+ {
+ NumSamples = pInstance->SamplesToProcess;
+ pStart = pBuffer->pScratch; /* Start of the buffer */
+ pStart += NumChannels*SampleCount; /* Offset by the number of processed samples */
+ if (NumSamples != 0)
+ {
+ Copy_16(pStart, /* Source */
+ &pBuffer->InDelayBuffer[0], /* Destination */
+ (LVM_INT16)(NumChannels*NumSamples)); /* Number of input samples */
+ }
+
+
+ /*
+ * Update the delay sample count
+ */
+ pBuffer->InDelaySamples = NumSamples; /* Number of delay sample pairs */
+ pInstance->SamplesToProcess = 0; /* All Samples used */
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferUnmanagedIn */
+/* */
+/* DESCRIPTION: */
+/* This mode is selected by the user code and disables the buffer management with the */
+/* exception of the maximum block size processing. The user must ensure that the */
+/* input and output buffers are 32-bit aligned and also that the number of samples to */
+/* process is a correct multiple of samples. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* *pToProcess - Pointer to the start of data processing */
+/* *pProcessed - Pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check if this is the first call of a block
+ */
+ if (pInstance->SamplesToProcess == 0)
+ {
+ pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples; /* Get the number of samples on first call */
+ pInstance->pInputSamples = *pToProcess; /* Get the I/O pointers */
+ pInstance->pOutputSamples = *pProcessed;
+
+
+ /*
+ * Set te block size to process
+ */
+ if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+ }
+ else
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+ }
+ }
+
+ /*
+ * Set the process pointers
+ */
+ *pToProcess = pInstance->pInputSamples;
+ *pProcessed = pInstance->pOutputSamples;
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferOptimisedIn */
+/* */
+/* DESCRIPTION: */
+/* Optimised buffer management for the case where the data is outplace processing, */
+/* the output data is 32-bit aligned and there are sufficient samples to allow some */
+/* processing directly in the output buffer. This saves one data copy per sample */
+/* compared with the unoptimsed version. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pInData - Pointer to the input data stream */
+/* *pToProcess - Pointer to the start of data processing */
+/* *pProcessed - Pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferOptimisedIn(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
+ LVM_INT16 *pDest;
+ LVM_INT16 SampleCount;
+ LVM_INT16 NumSamples;
+ LVM_INT16 NumFrames;
+
+ /*
+ * Check if it is the first call for this block
+ */
+ if (pInstance->SamplesToProcess == 0)
+ {
+ /*
+ * First call for a new block of samples
+ */
+ pBuffer->BufferState = LVM_FIRSTCALL;
+ pInstance->pInputSamples = (LVM_INT16 *)pInData;
+ pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
+ pBuffer->SamplesToOutput = (LVM_INT16)*pNumSamples;
+ pDest = *pProcessed; /* The start of the output buffer */
+
+
+ /*
+ * Copy the already processed samples to the output buffer
+ */
+ if (pBuffer->OutDelaySamples != 0)
+ {
+ Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of delay samples */
+ pDest += 2 * pBuffer->OutDelaySamples; /* Update the output pointer */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
+ }
+ *pToProcess = pDest; /* Set the address to start processing */
+ *pProcessed = pDest; /* Process in the output buffer, now inplace */
+
+ /*
+ * Copy the input delay buffer (unprocessed) samples to the output buffer
+ */
+ if (pBuffer->InDelaySamples != 0)
+ {
+ Copy_16(&pBuffer->InDelayBuffer[0], /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(2*pBuffer->InDelaySamples)); /* Number of delay samples */
+ pDest += 2 * pBuffer->InDelaySamples; /* Update the output pointer */
+ }
+
+
+ /*
+ * Calculate how many input samples to process and copy
+ */
+ NumSamples = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples); /* Number that will fit in the output buffer */
+ if (NumSamples >= pInstance->InternalBlockSize)
+ {
+ NumSamples = pInstance->InternalBlockSize;
+ }
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+ *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
+ SampleCount = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples); /* The number of samples to copy from the input */
+
+
+ /*
+ * Copy samples from the input buffer and update counts and pointers
+ */
+ Copy_16(pInstance->pInputSamples, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of input samples */
+ pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
+ pInstance->pOutputSamples = pDest + (2 * SampleCount); /* Update the output pointer */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+ }
+ else
+ {
+ /*
+ * Second or subsequent call in optimised mode
+ */
+ if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
+ {
+ /*
+ * More samples can be processed directly in the output buffer
+ */
+ *pToProcess = pInstance->pOutputSamples; /* Set the address to start processing */
+ *pProcessed = pInstance->pOutputSamples; /* Process in the output buffer, now inplace */
+ NumSamples = pBuffer->SamplesToOutput; /* Number that will fit in the output buffer */
+ if (NumSamples >= pInstance->InternalBlockSize)
+ {
+ NumSamples = pInstance->InternalBlockSize;
+ }
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+ *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
+
+
+ /*
+ * Copy samples from the input buffer and update counts and pointers
+ */
+ Copy_16(pInstance->pInputSamples, /* Source */
+ pInstance->pOutputSamples, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of input samples */
+ pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
+ pInstance->pOutputSamples += 2 * SampleCount; /* Update the output pointer */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Number that will fit in the output buffer */
+ }
+ else
+ {
+ /*
+ * The remaining samples can not be processed in the output buffer
+ */
+ pBuffer->BufferState = LVM_LASTCALL; /* Indicate this is the last bock to process */
+ *pToProcess = pBuffer->pScratch; /* Set the address to start processing */
+ *pProcessed = pBuffer->pScratch; /* Process in the output buffer, now inplace */
+ NumSamples = pInstance->SamplesToProcess; /* Number left to be processed */
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+ *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
+
+
+ /*
+ * Copy samples from the input buffer and update counts and pointers
+ */
+ Copy_16(pInstance->pInputSamples, /* Source */
+ pBuffer->pScratch, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of input samples */
+ pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+ }
+ }
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferIn */
+/* */
+/* DESCRIPTION: */
+/* This function manages the data input, it has the following features: */
+/* - Accepts data in 16-bit aligned memory */
+/* - Copies the data to 32-bit aligned memory */
+/* - Converts Mono inputs to Mono-in-Stereo */
+/* - Accepts any number of samples as input, except 0 */
+/* - Breaks the input sample stream in to blocks of the configured frame size or */
+/* multiples of the frame size */
+/* - Limits the processing block size to the maximum block size. */
+/* - Works with inplace or outplace processing automatically */
+/* */
+/* To manage the data the function has a number of operating states: */
+/* LVM_FIRSTCALL - The first call for this block of input samples */
+/* LVM_MAXBLOCKCALL - The current block is the maximum size. Only used for the */
+/* second and subsequent blocks. */
+/* LVM_LASTCALL - The last call for this block of input samples */
+/* LVM_FIRSTLASTCALL - This is the first and last call for this block of input*/
+/* samples, this occurs when the number of samples to */
+/* process is less than the maximum block size. */
+/* */
+/* The function uses an internal delay buffer the size of the minimum frame, this is */
+/* used to temporarily hold samples when the number of samples to process is not a */
+/* multiple of the frame size. */
+/* */
+/* To ensure correct operation with inplace buffering the number of samples to output*/
+/* per call is calculated in this function and is set to the number of samples read */
+/* from the input buffer. */
+/* */
+/* The total number of samples to process is stored when the function is called for */
+/* the first time. The value is overwritten by the size of the block to be processed */
+/* in each call so the size of the processing blocks can be controlled. The number of */
+/* samples actually processed for each block of input samples is always a multiple of*/
+/* the frame size so for any particular block of input samples the actual number of */
+/* processed samples may not match the number of input samples, sometime it will be */
+/* sometimes less. The average is the same and the difference is never more than the */
+/* frame size. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pInData - Pointer to the input data stream */
+/* *pToProcess - Pointer to the start of data processing */
+/* *pProcessed - Pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferIn(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check which mode, managed or unmanaged
+ */
+ if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ LVM_BufferManagedIn(hInstance,
+ pInData,
+ pToProcess,
+ pProcessed,
+ pNumSamples);
+ }
+ else
+ {
+ LVM_BufferUnmanagedIn(hInstance,
+ pToProcess,
+ pProcessed,
+ pNumSamples);
+ }
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferManagedOut */
+/* */
+/* DESCRIPTION: */
+/* Full buffer management output. This works in conjunction with the managed input */
+/* routine and ensures the correct number of samples are always output to the output */
+/* buffer. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pOutData - Pointer to the output data stream */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferManagedOut(LVM_Handle_t hInstance,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
+ LVM_INT16 SampleCount = (LVM_INT16)*pNumSamples;
+ LVM_INT16 NumSamples;
+ LVM_INT16 *pStart;
+ LVM_INT16 *pDest;
+
+
+ /*
+ * Set the pointers
+ */
+ NumSamples = pBuffer->SamplesToOutput;
+ pStart = pBuffer->pScratch;
+
+
+ /*
+ * check if it is the first call of a block
+ */
+ if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
+ (pBuffer->BufferState == LVM_FIRSTLASTCALL))
+ {
+ /* First call for a new block */
+ pInstance->pOutputSamples = pOutData; /* Initialise the destination */
+ }
+ pDest = pInstance->pOutputSamples; /* Set the output address */
+
+
+ /*
+ * If the number of samples is non-zero then there are still samples to send to
+ * the output buffer
+ */
+ if ((NumSamples != 0) &&
+ (pBuffer->OutDelaySamples != 0))
+ {
+ /*
+ * Copy the delayed output buffer samples to the output
+ */
+ if (pBuffer->OutDelaySamples <= NumSamples)
+ {
+ /*
+ * Copy all output delay samples to the output
+ */
+ Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of delay samples */
+
+ /*
+ * Update the pointer and sample counts
+ */
+ pDest += 2*pBuffer->OutDelaySamples; /* Output sample pointer */
+ NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left to send */
+ pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
+
+ }
+ else
+ {
+ /*
+ * Copy only some of the ouput delay samples to the output
+ */
+ Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*NumSamples)); /* Number of delay samples */
+
+ /*
+ * Update the pointer and sample counts
+ */
+ pDest += 2*NumSamples; /* Output sample pointer */
+ pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples); /* No samples left in the buffer */
+
+
+ /*
+ * Realign the delay buffer data to avoid using circular buffer management
+ */
+ Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples], /* Source */
+ &pBuffer->OutDelayBuffer[0], /* Destination */
+ (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of samples to move */
+ NumSamples = 0; /* Samples left to send */
+ }
+ }
+
+
+ /*
+ * Copy the processed results to the output
+ */
+ if ((NumSamples != 0) &&
+ (SampleCount != 0))
+ {
+ if (SampleCount <= NumSamples)
+ {
+ /*
+ * Copy all processed samples to the output
+ */
+ Copy_16(pStart, /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*SampleCount)); /* Number of processed samples */
+
+ /*
+ * Update the pointer and sample counts
+ */
+ pDest += 2 * SampleCount; /* Output sample pointer */
+ NumSamples = (LVM_INT16)(NumSamples - SampleCount); /* Samples left to send */
+ SampleCount = 0; /* No samples left in the buffer */
+ }
+ else
+ {
+ /*
+ * Copy only some processed samples to the output
+ */
+ Copy_16(pStart, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Number of processed samples */
+
+
+ /*
+ * Update the pointers and sample counts
+ */
+ pStart += 2 * NumSamples; /* Processed sample pointer */
+ pDest += 2 * NumSamples; /* Output sample pointer */
+ SampleCount = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
+ NumSamples = 0; /* Clear the sample count */
+ }
+ }
+
+
+ /*
+ * Copy the remaining processed data to the output delay buffer
+ */
+ if (SampleCount != 0)
+ {
+ Copy_16(pStart, /* Source */
+ &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples], /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of processed samples */
+ pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
+ }
+
+
+ /*
+ * pointers, counts and set default buffer processing
+ */
+ pBuffer->SamplesToOutput = NumSamples; /* Samples left to send */
+ pInstance->pOutputSamples = pDest; /* Output sample pointer */
+ pBuffer->BufferState = LVM_MAXBLOCKCALL; /* Set for the default call block size */
+ *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess; /* This will terminate the loop when all samples processed */
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferUnmanagedOut */
+/* */
+/* DESCRIPTION: */
+/* This works in conjunction with the unmanaged input routine and updates the number */
+/* of samples left to be processed and adjusts the buffer pointers. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedOut(LVM_Handle_t hInstance,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_INT16 NumChannels =2;
+
+
+ /*
+ * Update sample counts
+ */
+ pInstance->pInputSamples += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
+ pInstance->pOutputSamples += (LVM_INT16)(*pNumSamples * 2);
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
+
+ /*
+ * Set te block size to process
+ */
+ if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+ }
+ else
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferOptimisedOut */
+/* */
+/* DESCRIPTION: */
+/* This works in conjunction with the optimised input routine and copies the last few */
+/* processed and unprocessed samples to their respective buffers. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferOptimisedOut(LVM_Handle_t hInstance,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
+
+ /*
+ * Check if it is the last block to process
+ */
+ if (pBuffer->BufferState == LVM_LASTCALL)
+ {
+ LVM_INT16 *pSrc = pBuffer->pScratch;
+
+ /*
+ * Copy the unprocessed samples to the input delay buffer
+ */
+ if (pInstance->SamplesToProcess != 0)
+ {
+ Copy_16(pInstance->pInputSamples, /* Source */
+ &pBuffer->InDelayBuffer[0], /* Destination */
+ (LVM_INT16)(2*pInstance->SamplesToProcess)); /* Number of input samples */
+ pBuffer->InDelaySamples = pInstance->SamplesToProcess;
+ pInstance->SamplesToProcess = 0;
+ }
+ else
+ {
+ pBuffer->InDelaySamples = 0;
+ }
+
+
+ /*
+ * Fill the last empty spaces in the output buffer
+ */
+ if (pBuffer->SamplesToOutput != 0)
+ {
+ Copy_16(pSrc, /* Source */
+ pInstance->pOutputSamples, /* Destination */
+ (LVM_INT16)(2*pBuffer->SamplesToOutput)); /* Number of input samples */
+ *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
+ pSrc += 2 * pBuffer->SamplesToOutput; /* Update scratch pointer */
+ pBuffer->SamplesToOutput = 0; /* No more samples in this block */
+ }
+
+
+ /*
+ * Save any remaining processed samples in the output delay buffer
+ */
+ if (*pNumSamples != 0)
+ {
+ Copy_16(pSrc, /* Source */
+ &pBuffer->OutDelayBuffer[0], /* Destination */
+ (LVM_INT16)(2**pNumSamples)); /* Number of input samples */
+
+ pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
+
+ *pNumSamples = 0; /* No more samples in this block */
+ }
+ else
+ {
+ pBuffer->OutDelaySamples = 0;
+ }
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferOut */
+/* */
+/* DESCRIPTION: */
+/* This function manages the data output, it has the following features: */
+/* - Output data to 16-bit aligned memory */
+/* - Reads data from 32-bit aligned memory */
+/* - Reads data only in blocks of frame size or multiples of frame size */
+/* - Writes the same number of samples as the LVM_BufferIn function reads */
+/* - Works with inplace or outplace processing automatically */
+/* */
+/* To manage the data the function has a number of operating states: */
+/* LVM_FIRSTCALL - The first call for this block of input samples */
+/* LVM_FIRSTLASTCALL - This is the first and last call for this block of input*/
+/* samples, this occurs when the number of samples to */
+/* process is less than the maximum block size. */
+/* */
+/* The function uses an internal delay buffer the size of the minimum frame, this is */
+/* used to temporarily hold samples when the number of samples to write is not a */
+/* multiple of the frame size. */
+/* */
+/* To ensure correct operation with inplace buffering the number of samples to output*/
+/* per call is always the same as the number of samples read from the input buffer. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pOutData - Pointer to the output data stream */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferOut(LVM_Handle_t hInstance,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check which mode, managed or unmanaged
+ */
+ if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ LVM_BufferManagedOut(hInstance,
+ pOutData,
+ pNumSamples);
+ }
+ else
+ {
+ LVM_BufferUnmanagedOut(hInstance,
+ pNumSamples);
+ }
+}
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
new file mode 100755
index 0000000..f578db9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Coeffs.h
@@ -0,0 +1,573 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LVM_COEFFS_H__
+#define __LVM_COEFFS_H__
+
+
+/************************************************************************************/
+/* */
+/* High Pass Shelving Filter coefficients */
+/* */
+/************************************************************************************/
+
+#define TrebleBoostCorner 8000
+#define TrebleBoostMinRate 4
+#define TrebleBoostSteps 15
+
+
+/* Coefficients for sample rate 22050Hz */
+ /* Gain = 1.000000 dB */
+#define HPF_Fs22050_Gain1_A0 5383 /* Floating point value 0.164291 */
+#define HPF_Fs22050_Gain1_A1 16859 /* Floating point value 0.514492 */
+#define HPF_Fs22050_Gain1_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain1_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain1_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain1_Shift 1 /* Shift value */
+ /* Gain = 2.000000 dB */
+#define HPF_Fs22050_Gain2_A0 4683 /* Floating point value 0.142925 */
+#define HPF_Fs22050_Gain2_A1 17559 /* Floating point value 0.535858 */
+#define HPF_Fs22050_Gain2_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain2_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain2_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain2_Shift 1 /* Shift value */
+ /* Gain = 3.000000 dB */
+#define HPF_Fs22050_Gain3_A0 3898 /* Floating point value 0.118953 */
+#define HPF_Fs22050_Gain3_A1 18345 /* Floating point value 0.559830 */
+#define HPF_Fs22050_Gain3_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain3_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain3_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain3_Shift 1 /* Shift value */
+ /* Gain = 4.000000 dB */
+#define HPF_Fs22050_Gain4_A0 3016 /* Floating point value 0.092055 */
+#define HPF_Fs22050_Gain4_A1 19226 /* Floating point value 0.586728 */
+#define HPF_Fs22050_Gain4_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain4_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain4_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain4_Shift 1 /* Shift value */
+ /* Gain = 5.000000 dB */
+#define HPF_Fs22050_Gain5_A0 2028 /* Floating point value 0.061876 */
+#define HPF_Fs22050_Gain5_A1 20215 /* Floating point value 0.616907 */
+#define HPF_Fs22050_Gain5_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain5_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain5_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain5_Shift 1 /* Shift value */
+ /* Gain = 6.000000 dB */
+#define HPF_Fs22050_Gain6_A0 918 /* Floating point value 0.028013 */
+#define HPF_Fs22050_Gain6_A1 21324 /* Floating point value 0.650770 */
+#define HPF_Fs22050_Gain6_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain6_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain6_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain6_Shift 1 /* Shift value */
+ /* Gain = 7.000000 dB */
+#define HPF_Fs22050_Gain7_A0 -164 /* Floating point value -0.005002 */
+#define HPF_Fs22050_Gain7_A1 11311 /* Floating point value 0.345199 */
+#define HPF_Fs22050_Gain7_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain7_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain7_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain7_Shift 2 /* Shift value */
+ /* Gain = 8.000000 dB */
+#define HPF_Fs22050_Gain8_A0 -864 /* Floating point value -0.026368 */
+#define HPF_Fs22050_Gain8_A1 12012 /* Floating point value 0.366565 */
+#define HPF_Fs22050_Gain8_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain8_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain8_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain8_Shift 2 /* Shift value */
+ /* Gain = 9.000000 dB */
+#define HPF_Fs22050_Gain9_A0 -1650 /* Floating point value -0.050340 */
+#define HPF_Fs22050_Gain9_A1 12797 /* Floating point value 0.390537 */
+#define HPF_Fs22050_Gain9_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain9_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain9_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain9_Shift 2 /* Shift value */
+ /* Gain = 10.000000 dB */
+#define HPF_Fs22050_Gain10_A0 -2531 /* Floating point value -0.077238 */
+#define HPF_Fs22050_Gain10_A1 13679 /* Floating point value 0.417435 */
+#define HPF_Fs22050_Gain10_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain10_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain10_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain10_Shift 2 /* Shift value */
+ /* Gain = 11.000000 dB */
+#define HPF_Fs22050_Gain11_A0 -3520 /* Floating point value -0.107417 */
+#define HPF_Fs22050_Gain11_A1 14667 /* Floating point value 0.447615 */
+#define HPF_Fs22050_Gain11_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain11_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain11_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain11_Shift 2 /* Shift value */
+ /* Gain = 12.000000 dB */
+#define HPF_Fs22050_Gain12_A0 -4629 /* Floating point value -0.141279 */
+#define HPF_Fs22050_Gain12_A1 15777 /* Floating point value 0.481477 */
+#define HPF_Fs22050_Gain12_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain12_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain12_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain12_Shift 2 /* Shift value */
+ /* Gain = 13.000000 dB */
+#define HPF_Fs22050_Gain13_A0 -2944 /* Floating point value -0.089849 */
+#define HPF_Fs22050_Gain13_A1 8531 /* Floating point value 0.260352 */
+#define HPF_Fs22050_Gain13_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain13_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain13_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain13_Shift 3 /* Shift value */
+ /* Gain = 14.000000 dB */
+#define HPF_Fs22050_Gain14_A0 -3644 /* Floating point value -0.111215 */
+#define HPF_Fs22050_Gain14_A1 9231 /* Floating point value 0.281718 */
+#define HPF_Fs22050_Gain14_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain14_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain14_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain14_Shift 3 /* Shift value */
+ /* Gain = 15.000000 dB */
+#define HPF_Fs22050_Gain15_A0 -4430 /* Floating point value -0.135187 */
+#define HPF_Fs22050_Gain15_A1 10017 /* Floating point value 0.305690 */
+#define HPF_Fs22050_Gain15_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain15_B1 12125 /* Floating point value 0.370033 */
+#define HPF_Fs22050_Gain15_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs22050_Gain15_Shift 3 /* Shift value */
+
+
+/* Coefficients for sample rate 24000Hz */
+ /* Gain = 1.000000 dB */
+#define HPF_Fs24000_Gain1_A0 3625 /* Floating point value 0.110628 */
+#define HPF_Fs24000_Gain1_A1 16960 /* Floating point value 0.517578 */
+#define HPF_Fs24000_Gain1_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain1_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain1_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain1_Shift 1 /* Shift value */
+ /* Gain = 2.000000 dB */
+#define HPF_Fs24000_Gain2_A0 2811 /* Floating point value 0.085800 */
+#define HPF_Fs24000_Gain2_A1 17774 /* Floating point value 0.542406 */
+#define HPF_Fs24000_Gain2_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain2_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain2_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain2_Shift 1 /* Shift value */
+ /* Gain = 3.000000 dB */
+#define HPF_Fs24000_Gain3_A0 1899 /* Floating point value 0.057943 */
+#define HPF_Fs24000_Gain3_A1 18686 /* Floating point value 0.570263 */
+#define HPF_Fs24000_Gain3_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain3_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain3_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain3_Shift 1 /* Shift value */
+ /* Gain = 4.000000 dB */
+#define HPF_Fs24000_Gain4_A0 874 /* Floating point value 0.026687 */
+#define HPF_Fs24000_Gain4_A1 19711 /* Floating point value 0.601519 */
+#define HPF_Fs24000_Gain4_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain4_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain4_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain4_Shift 1 /* Shift value */
+ /* Gain = 5.000000 dB */
+#define HPF_Fs24000_Gain5_A0 -275 /* Floating point value -0.008383 */
+#define HPF_Fs24000_Gain5_A1 20860 /* Floating point value 0.636589 */
+#define HPF_Fs24000_Gain5_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain5_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain5_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain5_Shift 1 /* Shift value */
+ /* Gain = 6.000000 dB */
+#define HPF_Fs24000_Gain6_A0 -1564 /* Floating point value -0.047733 */
+#define HPF_Fs24000_Gain6_A1 22149 /* Floating point value 0.675938 */
+#define HPF_Fs24000_Gain6_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain6_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain6_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain6_Shift 1 /* Shift value */
+ /* Gain = 7.000000 dB */
+#define HPF_Fs24000_Gain7_A0 -1509 /* Floating point value -0.046051 */
+#define HPF_Fs24000_Gain7_A1 11826 /* Floating point value 0.360899 */
+#define HPF_Fs24000_Gain7_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain7_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain7_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain7_Shift 2 /* Shift value */
+ /* Gain = 8.000000 dB */
+#define HPF_Fs24000_Gain8_A0 -2323 /* Floating point value -0.070878 */
+#define HPF_Fs24000_Gain8_A1 12640 /* Floating point value 0.385727 */
+#define HPF_Fs24000_Gain8_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain8_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain8_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain8_Shift 2 /* Shift value */
+ /* Gain = 9.000000 dB */
+#define HPF_Fs24000_Gain9_A0 -3235 /* Floating point value -0.098736 */
+#define HPF_Fs24000_Gain9_A1 13552 /* Floating point value 0.413584 */
+#define HPF_Fs24000_Gain9_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain9_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain9_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain9_Shift 2 /* Shift value */
+ /* Gain = 10.000000 dB */
+#define HPF_Fs24000_Gain10_A0 -4260 /* Floating point value -0.129992 */
+#define HPF_Fs24000_Gain10_A1 14577 /* Floating point value 0.444841 */
+#define HPF_Fs24000_Gain10_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain10_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain10_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain10_Shift 2 /* Shift value */
+ /* Gain = 11.000000 dB */
+#define HPF_Fs24000_Gain11_A0 -5409 /* Floating point value -0.165062 */
+#define HPF_Fs24000_Gain11_A1 15726 /* Floating point value 0.479911 */
+#define HPF_Fs24000_Gain11_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain11_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain11_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain11_Shift 2 /* Shift value */
+ /* Gain = 12.000000 dB */
+#define HPF_Fs24000_Gain12_A0 -6698 /* Floating point value -0.204411 */
+#define HPF_Fs24000_Gain12_A1 17015 /* Floating point value 0.519260 */
+#define HPF_Fs24000_Gain12_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain12_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain12_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain12_Shift 2 /* Shift value */
+ /* Gain = 13.000000 dB */
+#define HPF_Fs24000_Gain13_A0 -4082 /* Floating point value -0.124576 */
+#define HPF_Fs24000_Gain13_A1 9253 /* Floating point value 0.282374 */
+#define HPF_Fs24000_Gain13_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain13_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain13_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain13_Shift 3 /* Shift value */
+ /* Gain = 14.000000 dB */
+#define HPF_Fs24000_Gain14_A0 -4896 /* Floating point value -0.149404 */
+#define HPF_Fs24000_Gain14_A1 10066 /* Floating point value 0.307202 */
+#define HPF_Fs24000_Gain14_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain14_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain14_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain14_Shift 3 /* Shift value */
+ /* Gain = 15.000000 dB */
+#define HPF_Fs24000_Gain15_A0 -5808 /* Floating point value -0.177261 */
+#define HPF_Fs24000_Gain15_A1 10979 /* Floating point value 0.335059 */
+#define HPF_Fs24000_Gain15_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain15_B1 8780 /* Floating point value 0.267949 */
+#define HPF_Fs24000_Gain15_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs24000_Gain15_Shift 3 /* Shift value */
+
+
+/* Coefficients for sample rate 32000Hz */
+ /* Gain = 1.000000 dB */
+#define HPF_Fs32000_Gain1_A0 17225 /* Floating point value 0.525677 */
+#define HPF_Fs32000_Gain1_A1 -990 /* Floating point value -0.030227 */
+#define HPF_Fs32000_Gain1_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain1_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain1_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain1_Shift 1 /* Shift value */
+ /* Gain = 2.000000 dB */
+#define HPF_Fs32000_Gain2_A0 18337 /* Floating point value 0.559593 */
+#define HPF_Fs32000_Gain2_A1 -2102 /* Floating point value -0.064142 */
+#define HPF_Fs32000_Gain2_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain2_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain2_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain2_Shift 1 /* Shift value */
+ /* Gain = 3.000000 dB */
+#define HPF_Fs32000_Gain3_A0 19584 /* Floating point value 0.597646 */
+#define HPF_Fs32000_Gain3_A1 -3349 /* Floating point value -0.102196 */
+#define HPF_Fs32000_Gain3_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain3_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain3_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain3_Shift 1 /* Shift value */
+ /* Gain = 4.000000 dB */
+#define HPF_Fs32000_Gain4_A0 20983 /* Floating point value 0.640343 */
+#define HPF_Fs32000_Gain4_A1 -4748 /* Floating point value -0.144893 */
+#define HPF_Fs32000_Gain4_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain4_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain4_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain4_Shift 1 /* Shift value */
+ /* Gain = 5.000000 dB */
+#define HPF_Fs32000_Gain5_A0 22553 /* Floating point value 0.688250 */
+#define HPF_Fs32000_Gain5_A1 -6318 /* Floating point value -0.192799 */
+#define HPF_Fs32000_Gain5_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain5_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain5_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain5_Shift 1 /* Shift value */
+ /* Gain = 6.000000 dB */
+#define HPF_Fs32000_Gain6_A0 24314 /* Floating point value 0.742002 */
+#define HPF_Fs32000_Gain6_A1 -8079 /* Floating point value -0.246551 */
+#define HPF_Fs32000_Gain6_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain6_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain6_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain6_Shift 1 /* Shift value */
+ /* Gain = 7.000000 dB */
+#define HPF_Fs32000_Gain7_A0 13176 /* Floating point value 0.402109 */
+#define HPF_Fs32000_Gain7_A1 -5040 /* Floating point value -0.153795 */
+#define HPF_Fs32000_Gain7_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain7_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain7_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain7_Shift 2 /* Shift value */
+ /* Gain = 8.000000 dB */
+#define HPF_Fs32000_Gain8_A0 14288 /* Floating point value 0.436024 */
+#define HPF_Fs32000_Gain8_A1 -6151 /* Floating point value -0.187711 */
+#define HPF_Fs32000_Gain8_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain8_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain8_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain8_Shift 2 /* Shift value */
+ /* Gain = 9.000000 dB */
+#define HPF_Fs32000_Gain9_A0 15535 /* Floating point value 0.474078 */
+#define HPF_Fs32000_Gain9_A1 -7398 /* Floating point value -0.225764 */
+#define HPF_Fs32000_Gain9_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain9_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain9_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain9_Shift 2 /* Shift value */
+ /* Gain = 10.000000 dB */
+#define HPF_Fs32000_Gain10_A0 16934 /* Floating point value 0.516774 */
+#define HPF_Fs32000_Gain10_A1 -8797 /* Floating point value -0.268461 */
+#define HPF_Fs32000_Gain10_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain10_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain10_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain10_Shift 2 /* Shift value */
+ /* Gain = 11.000000 dB */
+#define HPF_Fs32000_Gain11_A0 18503 /* Floating point value 0.564681 */
+#define HPF_Fs32000_Gain11_A1 -10367 /* Floating point value -0.316368 */
+#define HPF_Fs32000_Gain11_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain11_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain11_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain11_Shift 2 /* Shift value */
+ /* Gain = 12.000000 dB */
+#define HPF_Fs32000_Gain12_A0 20265 /* Floating point value 0.618433 */
+#define HPF_Fs32000_Gain12_A1 -12128 /* Floating point value -0.370120 */
+#define HPF_Fs32000_Gain12_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain12_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain12_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain12_Shift 2 /* Shift value */
+ /* Gain = 13.000000 dB */
+#define HPF_Fs32000_Gain13_A0 11147 /* Floating point value 0.340178 */
+#define HPF_Fs32000_Gain13_A1 -7069 /* Floating point value -0.215726 */
+#define HPF_Fs32000_Gain13_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain13_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain13_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain13_Shift 3 /* Shift value */
+ /* Gain = 14.000000 dB */
+#define HPF_Fs32000_Gain14_A0 12258 /* Floating point value 0.374093 */
+#define HPF_Fs32000_Gain14_A1 -8180 /* Floating point value -0.249642 */
+#define HPF_Fs32000_Gain14_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain14_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain14_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain14_Shift 3 /* Shift value */
+ /* Gain = 15.000000 dB */
+#define HPF_Fs32000_Gain15_A0 13505 /* Floating point value 0.412147 */
+#define HPF_Fs32000_Gain15_A1 -9427 /* Floating point value -0.287695 */
+#define HPF_Fs32000_Gain15_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain15_B1 0 /* Floating point value -0.000000 */
+#define HPF_Fs32000_Gain15_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs32000_Gain15_Shift 3 /* Shift value */
+
+
+/* Coefficients for sample rate 44100Hz */
+ /* Gain = 1.000000 dB */
+#define HPF_Fs44100_Gain1_A0 17442 /* Floating point value 0.532294 */
+#define HPF_Fs44100_Gain1_A1 -4761 /* Floating point value -0.145294 */
+#define HPF_Fs44100_Gain1_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain1_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain1_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain1_Shift 1 /* Shift value */
+ /* Gain = 2.000000 dB */
+#define HPF_Fs44100_Gain2_A0 18797 /* Floating point value 0.573633 */
+#define HPF_Fs44100_Gain2_A1 -6116 /* Floating point value -0.186634 */
+#define HPF_Fs44100_Gain2_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain2_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain2_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain2_Shift 1 /* Shift value */
+ /* Gain = 3.000000 dB */
+#define HPF_Fs44100_Gain3_A0 20317 /* Floating point value 0.620016 */
+#define HPF_Fs44100_Gain3_A1 -7635 /* Floating point value -0.233017 */
+#define HPF_Fs44100_Gain3_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain3_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain3_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain3_Shift 1 /* Shift value */
+ /* Gain = 4.000000 dB */
+#define HPF_Fs44100_Gain4_A0 22022 /* Floating point value 0.672059 */
+#define HPF_Fs44100_Gain4_A1 -9341 /* Floating point value -0.285060 */
+#define HPF_Fs44100_Gain4_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain4_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain4_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain4_Shift 1 /* Shift value */
+ /* Gain = 5.000000 dB */
+#define HPF_Fs44100_Gain5_A0 23935 /* Floating point value 0.730452 */
+#define HPF_Fs44100_Gain5_A1 -11254 /* Floating point value -0.343453 */
+#define HPF_Fs44100_Gain5_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain5_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain5_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain5_Shift 1 /* Shift value */
+ /* Gain = 6.000000 dB */
+#define HPF_Fs44100_Gain6_A0 26082 /* Floating point value 0.795970 */
+#define HPF_Fs44100_Gain6_A1 -13401 /* Floating point value -0.408971 */
+#define HPF_Fs44100_Gain6_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain6_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain6_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain6_Shift 1 /* Shift value */
+ /* Gain = 7.000000 dB */
+#define HPF_Fs44100_Gain7_A0 14279 /* Floating point value 0.435774 */
+#define HPF_Fs44100_Gain7_A1 -7924 /* Floating point value -0.241815 */
+#define HPF_Fs44100_Gain7_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain7_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain7_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain7_Shift 2 /* Shift value */
+ /* Gain = 8.000000 dB */
+#define HPF_Fs44100_Gain8_A0 15634 /* Floating point value 0.477113 */
+#define HPF_Fs44100_Gain8_A1 -9278 /* Floating point value -0.283154 */
+#define HPF_Fs44100_Gain8_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain8_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain8_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain8_Shift 2 /* Shift value */
+ /* Gain = 9.000000 dB */
+#define HPF_Fs44100_Gain9_A0 17154 /* Floating point value 0.523496 */
+#define HPF_Fs44100_Gain9_A1 -10798 /* Floating point value -0.329537 */
+#define HPF_Fs44100_Gain9_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain9_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain9_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain9_Shift 2 /* Shift value */
+ /* Gain = 10.000000 dB */
+#define HPF_Fs44100_Gain10_A0 18859 /* Floating point value 0.575539 */
+#define HPF_Fs44100_Gain10_A1 -12504 /* Floating point value -0.381580 */
+#define HPF_Fs44100_Gain10_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain10_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain10_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain10_Shift 2 /* Shift value */
+ /* Gain = 11.000000 dB */
+#define HPF_Fs44100_Gain11_A0 20773 /* Floating point value 0.633932 */
+#define HPF_Fs44100_Gain11_A1 -14417 /* Floating point value -0.439973 */
+#define HPF_Fs44100_Gain11_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain11_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain11_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain11_Shift 2 /* Shift value */
+ /* Gain = 12.000000 dB */
+#define HPF_Fs44100_Gain12_A0 22920 /* Floating point value 0.699450 */
+#define HPF_Fs44100_Gain12_A1 -16564 /* Floating point value -0.505491 */
+#define HPF_Fs44100_Gain12_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain12_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain12_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain12_Shift 2 /* Shift value */
+ /* Gain = 13.000000 dB */
+#define HPF_Fs44100_Gain13_A0 12694 /* Floating point value 0.387399 */
+#define HPF_Fs44100_Gain13_A1 -9509 /* Floating point value -0.290189 */
+#define HPF_Fs44100_Gain13_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain13_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain13_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain13_Shift 3 /* Shift value */
+ /* Gain = 14.000000 dB */
+#define HPF_Fs44100_Gain14_A0 14049 /* Floating point value 0.428738 */
+#define HPF_Fs44100_Gain14_A1 -10864 /* Floating point value -0.331528 */
+#define HPF_Fs44100_Gain14_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain14_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain14_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain14_Shift 3 /* Shift value */
+ /* Gain = 15.000000 dB */
+#define HPF_Fs44100_Gain15_A0 15569 /* Floating point value 0.475121 */
+#define HPF_Fs44100_Gain15_A1 -12383 /* Floating point value -0.377912 */
+#define HPF_Fs44100_Gain15_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain15_B1 -7173 /* Floating point value -0.218894 */
+#define HPF_Fs44100_Gain15_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs44100_Gain15_Shift 3 /* Shift value */
+
+
+/* Coefficients for sample rate 48000Hz */
+ /* Gain = 1.000000 dB */
+#define HPF_Fs48000_Gain1_A0 17491 /* Floating point value 0.533777 */
+#define HPF_Fs48000_Gain1_A1 -5606 /* Floating point value -0.171082 */
+#define HPF_Fs48000_Gain1_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain1_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain1_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain1_Shift 1 /* Shift value */
+ /* Gain = 2.000000 dB */
+#define HPF_Fs48000_Gain2_A0 18900 /* Floating point value 0.576779 */
+#define HPF_Fs48000_Gain2_A1 -7015 /* Floating point value -0.214085 */
+#define HPF_Fs48000_Gain2_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain2_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain2_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain2_Shift 1 /* Shift value */
+ /* Gain = 3.000000 dB */
+#define HPF_Fs48000_Gain3_A0 20481 /* Floating point value 0.625029 */
+#define HPF_Fs48000_Gain3_A1 -8596 /* Floating point value -0.262335 */
+#define HPF_Fs48000_Gain3_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain3_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain3_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain3_Shift 1 /* Shift value */
+ /* Gain = 4.000000 dB */
+#define HPF_Fs48000_Gain4_A0 22255 /* Floating point value 0.679167 */
+#define HPF_Fs48000_Gain4_A1 -10370 /* Floating point value -0.316472 */
+#define HPF_Fs48000_Gain4_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain4_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain4_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain4_Shift 1 /* Shift value */
+ /* Gain = 5.000000 dB */
+#define HPF_Fs48000_Gain5_A0 24245 /* Floating point value 0.739910 */
+#define HPF_Fs48000_Gain5_A1 -12361 /* Floating point value -0.377215 */
+#define HPF_Fs48000_Gain5_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain5_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain5_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain5_Shift 1 /* Shift value */
+ /* Gain = 6.000000 dB */
+#define HPF_Fs48000_Gain6_A0 26479 /* Floating point value 0.808065 */
+#define HPF_Fs48000_Gain6_A1 -14594 /* Floating point value -0.445370 */
+#define HPF_Fs48000_Gain6_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain6_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain6_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain6_Shift 1 /* Shift value */
+ /* Gain = 7.000000 dB */
+#define HPF_Fs48000_Gain7_A0 14527 /* Floating point value 0.443318 */
+#define HPF_Fs48000_Gain7_A1 -8570 /* Floating point value -0.261540 */
+#define HPF_Fs48000_Gain7_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain7_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain7_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain7_Shift 2 /* Shift value */
+ /* Gain = 8.000000 dB */
+#define HPF_Fs48000_Gain8_A0 15936 /* Floating point value 0.486321 */
+#define HPF_Fs48000_Gain8_A1 -9979 /* Floating point value -0.304543 */
+#define HPF_Fs48000_Gain8_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain8_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain8_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain8_Shift 2 /* Shift value */
+ /* Gain = 9.000000 dB */
+#define HPF_Fs48000_Gain9_A0 17517 /* Floating point value 0.534571 */
+#define HPF_Fs48000_Gain9_A1 -11560 /* Floating point value -0.352793 */
+#define HPF_Fs48000_Gain9_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain9_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain9_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain9_Shift 2 /* Shift value */
+ /* Gain = 10.000000 dB */
+#define HPF_Fs48000_Gain10_A0 19291 /* Floating point value 0.588708 */
+#define HPF_Fs48000_Gain10_A1 -13334 /* Floating point value -0.406930 */
+#define HPF_Fs48000_Gain10_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain10_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain10_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain10_Shift 2 /* Shift value */
+ /* Gain = 11.000000 dB */
+#define HPF_Fs48000_Gain11_A0 21281 /* Floating point value 0.649452 */
+#define HPF_Fs48000_Gain11_A1 -15325 /* Floating point value -0.467674 */
+#define HPF_Fs48000_Gain11_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain11_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain11_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain11_Shift 2 /* Shift value */
+ /* Gain = 12.000000 dB */
+#define HPF_Fs48000_Gain12_A0 23515 /* Floating point value 0.717607 */
+#define HPF_Fs48000_Gain12_A1 -17558 /* Floating point value -0.535829 */
+#define HPF_Fs48000_Gain12_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain12_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain12_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain12_Shift 2 /* Shift value */
+ /* Gain = 13.000000 dB */
+#define HPF_Fs48000_Gain13_A0 13041 /* Floating point value 0.397982 */
+#define HPF_Fs48000_Gain13_A1 -10056 /* Floating point value -0.306877 */
+#define HPF_Fs48000_Gain13_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain13_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain13_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain13_Shift 3 /* Shift value */
+ /* Gain = 14.000000 dB */
+#define HPF_Fs48000_Gain14_A0 14450 /* Floating point value 0.440984 */
+#define HPF_Fs48000_Gain14_A1 -11465 /* Floating point value -0.349880 */
+#define HPF_Fs48000_Gain14_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain14_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain14_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain14_Shift 3 /* Shift value */
+ /* Gain = 15.000000 dB */
+#define HPF_Fs48000_Gain15_A0 16031 /* Floating point value 0.489234 */
+#define HPF_Fs48000_Gain15_A1 -13046 /* Floating point value -0.398130 */
+#define HPF_Fs48000_Gain15_A2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain15_B1 -8780 /* Floating point value -0.267949 */
+#define HPF_Fs48000_Gain15_B2 0 /* Floating point value 0.000000 */
+#define HPF_Fs48000_Gain15_Shift 3 /* Shift value */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
new file mode 100755
index 0000000..922f77d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -0,0 +1,1033 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1316 $
+ $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+*****************************************************************************************/
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+#include "LVM_Coeffs.h"
+#include "LVM_Tables.h"
+#include "LVM_Private.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LifeVibes module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS When hInstance, pParams or any control pointers are NULL */
+/* LVM_OUTOFRANGE When any of the control parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance,
+ LVM_ControlParams_t *pParams)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
+
+
+ if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+
+ pInstance->NewParams = *pParams;
+
+ if(
+ /* General parameters */
+ ((pParams->OperatingMode != LVM_MODE_OFF) && (pParams->OperatingMode != LVM_MODE_ON)) ||
+ ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000) &&
+ (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000) &&
+ (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)) ||
+ ((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
+ (pParams->SpeakerType > LVM_EX_HEADPHONES))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /*
+ * Cinema Sound parameters
+ */
+ if((pParams->VirtualizerOperatingMode != LVM_MODE_OFF) && (pParams->VirtualizerOperatingMode != LVM_MODE_ON))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ if(pParams->VirtualizerType != LVM_CONCERTSOUND)
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ if(pParams->VirtualizerReverbLevel > LVM_VIRTUALIZER_MAX_REVERB_LEVEL)
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ if(pParams->CS_EffectLevel < LVM_CS_MIN_EFFECT_LEVEL)
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /*
+ * N-Band Equalizer
+ */
+ if(pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands)
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /* Definition pointer */
+ if ((pParams->pEQNB_BandDefinition == LVM_NULL) &&
+ (pParams->EQNB_NBands != 0))
+ {
+ return (LVM_NULLADDRESS);
+ }
+
+ /*
+ * Copy the filter definitions for the Equaliser
+ */
+ {
+ LVM_INT16 i;
+
+ if (pParams->EQNB_NBands != 0)
+ {
+ for (i=0; i<pParams->EQNB_NBands; i++)
+ {
+ pInstance->pEQNB_BandDefs[i] = pParams->pEQNB_BandDefinition[i];
+ }
+ pInstance->NewParams.pEQNB_BandDefinition = pInstance->pEQNB_BandDefs;
+ }
+ }
+ if( /* N-Band Equaliser parameters */
+ ((pParams->EQNB_OperatingMode != LVM_EQNB_OFF) && (pParams->EQNB_OperatingMode != LVM_EQNB_ON)) ||
+ (pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ /* Band parameters*/
+ {
+ LVM_INT16 i;
+ for(i = 0; i < pParams->EQNB_NBands; i++)
+ {
+ if(((pParams->pEQNB_BandDefinition[i].Frequency < LVM_EQNB_MIN_BAND_FREQ) ||
+ (pParams->pEQNB_BandDefinition[i].Frequency > LVM_EQNB_MAX_BAND_FREQ)) ||
+ ((pParams->pEQNB_BandDefinition[i].Gain < LVM_EQNB_MIN_BAND_GAIN) ||
+ (pParams->pEQNB_BandDefinition[i].Gain > LVM_EQNB_MAX_BAND_GAIN)) ||
+ ((pParams->pEQNB_BandDefinition[i].QFactor < LVM_EQNB_MIN_QFACTOR) ||
+ (pParams->pEQNB_BandDefinition[i].QFactor > LVM_EQNB_MAX_QFACTOR)))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ }
+ }
+
+ /*
+ * Bass Enhancement parameters
+ */
+ if(((pParams->BE_OperatingMode != LVM_BE_OFF) && (pParams->BE_OperatingMode != LVM_BE_ON)) ||
+ ((pParams->BE_EffectLevel < LVM_BE_MIN_EFFECTLEVEL ) || (pParams->BE_EffectLevel > LVM_BE_MAX_EFFECTLEVEL ))||
+ ((pParams->BE_CentreFreq != LVM_BE_CENTRE_55Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_66Hz) &&
+ (pParams->BE_CentreFreq != LVM_BE_CENTRE_78Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_90Hz)) ||
+ ((pParams->BE_HPF != LVM_BE_HPF_OFF) && (pParams->BE_HPF != LVM_BE_HPF_ON)))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /*
+ * Volume Control parameters
+ */
+ if((pParams->VC_EffectLevel < LVM_VC_MIN_EFFECTLEVEL ) || (pParams->VC_EffectLevel > LVM_VC_MAX_EFFECTLEVEL ))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ if((pParams->VC_Balance < LVM_VC_BALANCE_MIN ) || (pParams->VC_Balance > LVM_VC_BALANCE_MAX ))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /*
+ * PSA parameters
+ */
+ if( (pParams->PSA_PeakDecayRate > LVPSA_SPEED_HIGH) ||
+ (pParams->PSA_Enable > LVM_PSA_ON))
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+
+ /*
+ * Set the flag to indicate there are new parameters to use
+ *
+ * Protect the copy of the new parameters from interrupts to avoid possible problems
+ * with loss control parameters. This problem can occur if this control function is called more
+ * than once before a call to the process function. If the process function interrupts
+ * the copy to NewParams then one frame may have mixed parameters, some old and some new.
+ */
+ pInstance->ControlPending = LVM_TRUE;
+ pInstance->NoSmoothVolume = LVM_FALSE;
+
+ return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetControlParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the LifeVibes module parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS when any of hInstance or pParams is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t hInstance,
+ LVM_ControlParams_t *pParams)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check pointer
+ */
+ if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+ *pParams = pInstance->NewParams;
+
+ /*
+ * Copy the filter definitions for the Equaliser
+ */
+ {
+ LVM_INT16 i;
+
+ if (pInstance->NewParams.EQNB_NBands != 0)
+ for (i=0; i<pInstance->NewParams.EQNB_NBands; i++)
+ {
+ pInstance->pEQNB_UserDefs[i] = pInstance->pEQNB_BandDefs[i];
+ }
+ pParams->pEQNB_BandDefinition = pInstance->pEQNB_UserDefs;
+ }
+
+ return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetTrebleBoost */
+/* */
+/* DESCRIPTION: */
+/* Enable the treble boost when the settings are appropriate, i.e. non-zero gain */
+/* and the sample rate is high enough for the effect to be heard. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance structure */
+/* pParams Pointer to the parameters to use */
+/* */
+/****************************************************************************************/
+void LVM_SetTrebleBoost(LVM_Instance_t *pInstance,
+ LVM_ControlParams_t *pParams)
+{
+ extern FO_C16_LShx_Coefs_t LVM_TrebleBoostCoefs[];
+ LVM_INT16 Offset;
+ LVM_INT16 EffectLevel = 0;
+
+ /*
+ * Load the coefficients
+ */
+ if ((pParams->TE_OperatingMode == LVM_TE_ON) &&
+ (pParams->SampleRate >= TrebleBoostMinRate) &&
+ (pParams->OperatingMode == LVM_MODE_ON) &&
+ (pParams->TE_EffectLevel > 0))
+ {
+ if((pParams->TE_EffectLevel == LVM_TE_LOW_MIPS) &&
+ ((pParams->SpeakerType == LVM_HEADPHONES)||
+ (pParams->SpeakerType == LVM_EX_HEADPHONES)))
+ {
+ pInstance->TE_Active = LVM_FALSE;
+ }
+ else
+ {
+ EffectLevel = pParams->TE_EffectLevel;
+ pInstance->TE_Active = LVM_TRUE;
+ }
+
+ if(pInstance->TE_Active == LVM_TRUE)
+ {
+ /*
+ * Load the coefficients and enabled the treble boost
+ */
+ Offset = (LVM_INT16)(EffectLevel - 1 + TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
+ FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
+ &pInstance->pTE_Taps->TrebleBoost_Taps,
+ &LVM_TrebleBoostCoefs[Offset]);
+
+ /*
+ * Clear the taps
+ */
+ LoadConst_16((LVM_INT16)0, /* Value */
+ (void *)&pInstance->pTE_Taps->TrebleBoost_Taps, /* Destination.\
+ Cast to void: no dereferencing in function */
+ (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps)/sizeof(LVM_INT16))); /* Number of words */
+ }
+ }
+ else
+ {
+ /*
+ * Disable the treble boost
+ */
+ pInstance->TE_Active = LVM_FALSE;
+ }
+
+ return;
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetVolume */
+/* */
+/* DESCRIPTION: */
+/* Converts the input volume demand from dBs to linear. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/************************************************************************************/
+void LVM_SetVolume(LVM_Instance_t *pInstance,
+ LVM_ControlParams_t *pParams)
+{
+
+ LVM_UINT16 dBShifts; /* 6dB shifts */
+ LVM_UINT16 dBOffset; /* Table offset */
+ LVM_INT16 Volume = 0; /* Required volume in dBs */
+
+ /*
+ * Limit the gain to the maximum allowed
+ */
+ if (pParams->VC_EffectLevel > 0)
+ {
+ Volume = 0;
+ }
+ else
+ {
+ Volume = pParams->VC_EffectLevel;
+ }
+
+ /* Compensate this volume in PSA plot */
+ if(Volume > -60) /* Limit volume loss to PSA Limits*/
+ pInstance->PSA_GainOffset=(LVM_INT16)(-Volume);/* Loss is compensated by Gain*/
+ else
+ pInstance->PSA_GainOffset=(LVM_INT16)60;/* Loss is compensated by Gain*/
+
+ pInstance->VC_AVLFixedVolume = 0;
+
+ /*
+ * Set volume control and AVL volumes according to headroom and volume user setting
+ */
+ if(pParams->OperatingMode == LVM_MODE_ON)
+ {
+ /* Default Situation with no AVL and no RS */
+ if(pParams->EQNB_OperatingMode == LVM_EQNB_ON)
+ {
+ if(Volume > -pInstance->Headroom)
+ Volume = (LVM_INT16)-pInstance->Headroom;
+ }
+ }
+
+ /*
+ * Activate volume control if necessary
+ */
+ pInstance->VC_Active = LVM_TRUE;
+ if (Volume != 0)
+ {
+ pInstance->VC_VolumedB = Volume;
+ }
+ else
+ {
+ pInstance->VC_VolumedB = 0;
+ }
+
+ /*
+ * Calculate the required gain and shifts
+ */
+ dBOffset = (LVM_UINT16)((-Volume) % 6); /* Get the dBs 0-5 */
+ dBShifts = (LVM_UINT16)(Volume / -6); /* Get the 6dB shifts */
+
+
+ /*
+ * Set the parameters
+ */
+ if(dBShifts == 0)
+ {
+ LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
+ (LVM_INT32)LVM_VolumeTable[dBOffset]);
+ }
+ else
+ {
+ LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
+ (((LVM_INT32)LVM_VolumeTable[dBOffset])>>dBShifts));
+ }
+ pInstance->VC_Volume.MixerStream[0].CallbackSet = 1;
+ if(pInstance->NoSmoothVolume == LVM_TRUE)
+ {
+ LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,pInstance->Params.SampleRate,2);
+ }
+ else
+ {
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],LVM_VC_MIXER_TIME,pInstance->Params.SampleRate,2);
+ }
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetHeadroom */
+/* */
+/* DESCRIPTION: */
+/* Find suitable headroom based on EQ settings. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/* RETURNS: */
+/* void Nothing */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+void LVM_SetHeadroom(LVM_Instance_t *pInstance,
+ LVM_ControlParams_t *pParams)
+{
+ LVM_INT16 ii, jj;
+ LVM_INT16 Headroom = 0;
+ LVM_INT16 MaxGain = 0;
+
+
+ if ((pParams->EQNB_OperatingMode == LVEQNB_ON) && (pInstance->HeadroomParams.Headroom_OperatingMode == LVM_HEADROOM_ON))
+ {
+ /* Find typical headroom value */
+ for(jj = 0; jj < pInstance->HeadroomParams.NHeadroomBands; jj++)
+ {
+ MaxGain = 0;
+ for( ii = 0; ii < pParams->EQNB_NBands; ii++)
+ {
+ if((pParams->pEQNB_BandDefinition[ii].Frequency >= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_Low) &&
+ (pParams->pEQNB_BandDefinition[ii].Frequency <= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_High))
+ {
+ if(pParams->pEQNB_BandDefinition[ii].Gain > MaxGain)
+ {
+ MaxGain = pParams->pEQNB_BandDefinition[ii].Gain;
+ }
+ }
+ }
+
+ if((MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset) > Headroom){
+ Headroom = (LVM_INT16)(MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset);
+ }
+ }
+
+ /* Saturate */
+ if(Headroom < 0)
+ Headroom = 0;
+ }
+ pInstance->Headroom = (LVM_UINT16)Headroom ;
+
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Applies changes to parametres. This function makes no assumptions about what */
+/* each module needs for initialisation and hence passes all parameters to all the */
+/* the modules in turn. */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVM_Success Succeeded */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t hInstance)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
+ LVM_ControlParams_t LocalParams;
+ LVM_INT16 Count = 5;
+
+
+ /*
+ * Copy the new parameters but make sure they didn't change while copying
+ */
+ do
+ {
+ pInstance->ControlPending = LVM_FALSE;
+ LocalParams = pInstance->NewParams;
+ pInstance->HeadroomParams = pInstance->NewHeadroomParams;
+ Count--;
+ } while ((pInstance->ControlPending != LVM_FALSE) &&
+ (Count > 0));
+
+ /* Clear all internal data if format change*/
+ if(LocalParams.SourceFormat != pInstance->Params.SourceFormat)
+ {
+ LVM_ClearAudioBuffers(pInstance);
+ pInstance->ControlPending = LVM_FALSE;
+ }
+
+ /*
+ * Update the treble boost if required
+ */
+ if ((pInstance->Params.SampleRate != LocalParams.SampleRate) ||
+ (pInstance->Params.TE_EffectLevel != LocalParams.TE_EffectLevel) ||
+ (pInstance->Params.TE_OperatingMode != LocalParams.TE_OperatingMode) ||
+ (pInstance->Params.OperatingMode != LocalParams.OperatingMode) ||
+ (pInstance->Params.SpeakerType != LocalParams.SpeakerType))
+ {
+ LVM_SetTrebleBoost(pInstance,
+ &LocalParams);
+ }
+
+ /*
+ * Update the headroom if required
+ */
+ LVM_SetHeadroom(pInstance, /* Instance pointer */
+ &LocalParams); /* New parameters */
+
+ /*
+ * Update the volume if required
+ */
+ {
+ LVM_SetVolume(pInstance, /* Instance pointer */
+ &LocalParams); /* New parameters */
+ }
+ /* Apply balance changes*/
+ if(pInstance->Params.VC_Balance != LocalParams.VC_Balance)
+ {
+ /* Configure Mixer module for gradual changes to volume*/
+ if(LocalParams.VC_Balance < 0)
+ {
+ LVM_INT32 Target;
+ /* Drop in right channel volume*/
+ Target = LVM_MAXINT_16;
+ LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+
+ Target = dB_to_Lin32((LVM_INT16)(LocalParams.VC_Balance<<4));
+ LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+ }
+ else if(LocalParams.VC_Balance >0)
+ {
+ LVM_INT32 Target;
+ /* Drop in left channel volume*/
+ Target = dB_to_Lin32((LVM_INT16)((-LocalParams.VC_Balance)<<4));
+ LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+
+ Target = LVM_MAXINT_16;
+ LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+ }
+ else
+ {
+ LVM_INT32 Target;
+ /* No drop*/
+ Target = LVM_MAXINT_16;
+ LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+
+ LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
+ }
+ }
+ /*
+ * Update the bass enhancement
+ */
+ {
+ LVDBE_ReturnStatus_en DBE_Status;
+ LVDBE_Params_t DBE_Params;
+ LVDBE_Handle_t *hDBEInstance = pInstance->hDBEInstance;
+
+
+ /*
+ * Set the new parameters
+ */
+ if(LocalParams.OperatingMode == LVM_MODE_OFF)
+ {
+ DBE_Params.OperatingMode = LVDBE_OFF;
+ }
+ else
+ {
+ DBE_Params.OperatingMode = (LVDBE_Mode_en)LocalParams.BE_OperatingMode;
+ }
+ DBE_Params.SampleRate = (LVDBE_Fs_en)LocalParams.SampleRate;
+ DBE_Params.EffectLevel = LocalParams.BE_EffectLevel;
+ DBE_Params.CentreFrequency = (LVDBE_CentreFreq_en)LocalParams.BE_CentreFreq;
+ DBE_Params.HPFSelect = (LVDBE_FilterSelect_en)LocalParams.BE_HPF;
+ DBE_Params.HeadroomdB = 0;
+ DBE_Params.VolumeControl = LVDBE_VOLUME_OFF;
+ DBE_Params.VolumedB = 0;
+
+ /*
+ * Make the changes
+ */
+ DBE_Status = LVDBE_Control(hDBEInstance,
+ &DBE_Params);
+
+
+ /*
+ * Quit if the changes were not accepted
+ */
+ if (DBE_Status != LVDBE_SUCCESS)
+ {
+ return((LVM_ReturnStatus_en)DBE_Status);
+ }
+
+
+ /*
+ * Set the control flag
+ */
+ pInstance->DBE_Active = LVM_TRUE;
+ }
+
+ /*
+ * Update the N-Band Equaliser
+ */
+ {
+ LVEQNB_ReturnStatus_en EQNB_Status;
+ LVEQNB_Params_t EQNB_Params;
+ LVEQNB_Handle_t *hEQNBInstance = pInstance->hEQNBInstance;
+
+
+ /*
+ * Set the new parameters
+ */
+
+ if(LocalParams.OperatingMode == LVM_MODE_OFF)
+ {
+ EQNB_Params.OperatingMode = LVEQNB_BYPASS;
+ }
+ else
+ {
+ EQNB_Params.OperatingMode = (LVEQNB_Mode_en)LocalParams.EQNB_OperatingMode;
+ }
+
+ EQNB_Params.SampleRate = (LVEQNB_Fs_en)LocalParams.SampleRate;
+ EQNB_Params.NBands = LocalParams.EQNB_NBands;
+ EQNB_Params.pBandDefinition = (LVEQNB_BandDef_t *)LocalParams.pEQNB_BandDefinition;
+ if (LocalParams.SourceFormat == LVM_STEREO) /* Mono format not supported */
+ {
+ EQNB_Params.SourceFormat = LVEQNB_STEREO;
+ }
+ else
+ {
+ EQNB_Params.SourceFormat = LVEQNB_MONOINSTEREO; /* Force to Mono-in-Stereo mode */
+ }
+
+
+ /*
+ * Set the control flag
+ */
+ if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
+ (LocalParams.EQNB_OperatingMode == LVM_EQNB_ON))
+ {
+ pInstance->EQNB_Active = LVM_TRUE;
+ }
+ else
+ {
+ EQNB_Params.OperatingMode = LVEQNB_BYPASS;
+ }
+
+ /*
+ * Make the changes
+ */
+ EQNB_Status = LVEQNB_Control(hEQNBInstance,
+ &EQNB_Params);
+
+
+ /*
+ * Quit if the changes were not accepted
+ */
+ if (EQNB_Status != LVEQNB_SUCCESS)
+ {
+ return((LVM_ReturnStatus_en)EQNB_Status);
+ }
+
+ }
+
+
+ /*
+ * Update concert sound
+ */
+ {
+ LVCS_ReturnStatus_en CS_Status;
+ LVCS_Params_t CS_Params;
+ LVCS_Handle_t *hCSInstance = pInstance->hCSInstance;
+ LVM_Mode_en CompressorMode=LVM_MODE_ON;
+
+ /*
+ * Set the new parameters
+ */
+ if(LocalParams.VirtualizerOperatingMode == LVM_MODE_ON)
+ {
+ CS_Params.OperatingMode = LVCS_ON;
+ }
+ else
+ {
+ CS_Params.OperatingMode = LVCS_OFF;
+ }
+
+ if((LocalParams.TE_OperatingMode == LVM_TE_ON) && (LocalParams.TE_EffectLevel == LVM_TE_LOW_MIPS))
+ {
+ CS_Params.SpeakerType = LVCS_EX_HEADPHONES;
+ }
+ else
+ {
+ CS_Params.SpeakerType = LVCS_HEADPHONES;
+ }
+
+ if (LocalParams.SourceFormat == LVM_STEREO) /* Mono format not supported */
+ {
+ CS_Params.SourceFormat = LVCS_STEREO;
+ }
+ else
+ {
+ CS_Params.SourceFormat = LVCS_MONOINSTEREO; /* Force to Mono-in-Stereo mode */
+ }
+ CS_Params.SampleRate = LocalParams.SampleRate;
+ CS_Params.ReverbLevel = LocalParams.VirtualizerReverbLevel;
+ CS_Params.EffectLevel = LocalParams.CS_EffectLevel;
+
+
+ /*
+ * Set the control flag
+ */
+ if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
+ (LocalParams.VirtualizerOperatingMode != LVCS_OFF))
+ {
+ pInstance->CS_Active = LVM_TRUE;
+ }
+ else
+ {
+ CS_Params.OperatingMode = LVCS_OFF;
+ }
+
+ CS_Params.CompressorMode=CompressorMode;
+
+ /*
+ * Make the changes
+ */
+ CS_Status = LVCS_Control(hCSInstance,
+ &CS_Params);
+
+
+ /*
+ * Quit if the changes were not accepted
+ */
+ if (CS_Status != LVCS_SUCCESS)
+ {
+ return((LVM_ReturnStatus_en)CS_Status);
+ }
+
+ }
+
+ /*
+ * Update the Power Spectrum Analyser
+ */
+ {
+ LVPSA_RETURN PSA_Status;
+ LVPSA_ControlParams_t PSA_Params;
+ pLVPSA_Handle_t *hPSAInstance = pInstance->hPSAInstance;
+
+
+ /*
+ * Set the new parameters
+ */
+ PSA_Params.Fs = LocalParams.SampleRate;
+ PSA_Params.LevelDetectionSpeed = (LVPSA_LevelDetectSpeed_en)LocalParams.PSA_PeakDecayRate;
+
+ /*
+ * Make the changes
+ */
+ if(pInstance->InstParams.PSA_Included==LVM_PSA_ON)
+ {
+ PSA_Status = LVPSA_Control(hPSAInstance,
+ &PSA_Params);
+
+ if (PSA_Status != LVPSA_OK)
+ {
+ return((LVM_ReturnStatus_en)PSA_Status);
+ }
+
+ /*
+ * Apply new settings
+ */
+ PSA_Status = LVPSA_ApplyNewSettings ((LVPSA_InstancePr_t*)hPSAInstance);
+ if(PSA_Status != LVPSA_OK)
+ {
+ return((LVM_ReturnStatus_en)PSA_Status);
+ }
+ }
+ }
+
+ /*
+ * Update the parameters and clear the flag
+ */
+ pInstance->Params = LocalParams;
+
+
+ return(LVM_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_SetHeadroomParams */
+/* */
+/* DESCRIPTION: */
+/* This function is used to set the automatiuc headroom management parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pHeadroomParams Pointer to headroom parameter structure */
+/* */
+/* RETURNS: */
+/* LVM_Success Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_SetHeadroomParams(LVM_Handle_t hInstance,
+ LVM_HeadroomParams_t *pHeadroomParams)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
+ LVM_UINT16 ii, NBands;
+
+ /* Check for NULL pointers */
+ if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+ if ((pHeadroomParams->NHeadroomBands != 0) && (pHeadroomParams->pHeadroomDefinition == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+
+ /* Consider only the LVM_HEADROOM_MAX_NBANDS first bands*/
+ if (pHeadroomParams->NHeadroomBands > LVM_HEADROOM_MAX_NBANDS)
+ {
+ NBands = LVM_HEADROOM_MAX_NBANDS;
+ }
+ else
+ {
+ NBands = pHeadroomParams->NHeadroomBands;
+ }
+ pInstance->NewHeadroomParams.NHeadroomBands = NBands;
+
+ /* Copy settings in memory */
+ for(ii = 0; ii < NBands; ii++)
+ {
+ pInstance->pHeadroom_BandDefs[ii] = pHeadroomParams->pHeadroomDefinition[ii];
+ }
+
+ pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
+ pInstance->NewHeadroomParams.Headroom_OperatingMode = pHeadroomParams->Headroom_OperatingMode;
+ pInstance->ControlPending = LVM_TRUE;
+
+ return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetHeadroomParams */
+/* */
+/* DESCRIPTION: */
+/* This function is used to get the automatic headroom management parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pHeadroomParams Pointer to headroom parameter structure (output) */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS When hInstance or pHeadroomParams are NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetHeadroomParams(LVM_Handle_t hInstance,
+ LVM_HeadroomParams_t *pHeadroomParams)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
+ LVM_UINT16 ii;
+
+ /* Check for NULL pointers */
+ if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+
+ pHeadroomParams->NHeadroomBands = pInstance->NewHeadroomParams.NHeadroomBands;
+
+
+ /* Copy settings in memory */
+ for(ii = 0; ii < pInstance->NewHeadroomParams.NHeadroomBands; ii++)
+ {
+ pInstance->pHeadroom_UserDefs[ii] = pInstance->pHeadroom_BandDefs[ii];
+ }
+
+
+ pHeadroomParams->pHeadroomDefinition = pInstance->pHeadroom_UserDefs;
+ pHeadroomParams->Headroom_OperatingMode = pInstance->NewHeadroomParams.Headroom_OperatingMode;
+ return(LVM_SUCCESS);
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_AlgoCallBack */
+/* */
+/* DESCRIPTION: */
+/* This is the callback function of the algorithm. */
+/* */
+/* PARAMETERS: */
+/* pBundleHandle Pointer to the Instance Handle */
+/* pData Pointer to the data */
+/* callbackId ID of the callback */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_INT32 LVM_AlgoCallBack( void *pBundleHandle,
+ void *pData,
+ LVM_INT16 callbackId)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)pBundleHandle;
+
+ (void) pData;
+
+ switch(callbackId & 0xFF00){
+ case ALGORITHM_CS_ID:
+ switch(callbackId & 0x00FF)
+ {
+ case LVCS_EVENT_ALGOFF:
+ pInstance->CS_Active = LVM_FALSE;
+ break;
+ default:
+ break;
+ }
+ break;
+ case ALGORITHM_EQNB_ID:
+ switch(callbackId & 0x00FF)
+ {
+ case LVEQNB_EVENT_ALGOFF:
+ pInstance->EQNB_Active = LVM_FALSE;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_VCCallBack */
+/* */
+/* DESCRIPTION: */
+/* This is the callback function of the Volume control. */
+/* */
+/* PARAMETERS: */
+/* pBundleHandle Pointer to the Instance Handle */
+/* pGeneralPurpose Pointer to the data */
+/* CallBackParam ID of the callback */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+LVM_INT32 LVM_VCCallBack(void* pBundleHandle,
+ void* pGeneralPurpose,
+ short CallBackParam)
+{
+ LVM_Instance_t *pInstance =(LVM_Instance_t *)pBundleHandle;
+ LVM_INT32 Target;
+
+ (void) pGeneralPurpose;
+ (void) CallBackParam;
+
+ /* When volume mixer has reached 0 dB target then stop it to avoid
+ unnecessary processing. */
+ Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
+
+ if(Target == 0x7FFF)
+ {
+ pInstance->VC_Active = LVM_FALSE;
+ }
+ return 1;
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
new file mode 100755
index 0000000..323a2a3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
@@ -0,0 +1,1003 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1316 $
+ $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVM_Private.h"
+#include "LVM_Tables.h"
+#include "VectorArithmetic.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetMemoryTable */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the default capabilities */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_NULLADDRESS When one of pMemoryTable or pInstParams is NULL */
+/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVM_Process function */
+/* 2. The scratch memory is the largest required by any of the sub-modules plus any */
+/* additional scratch requirements of the bundle */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetMemoryTable(LVM_Handle_t hInstance,
+ LVM_MemTab_t *pMemoryTable,
+ LVM_InstParams_t *pInstParams)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_UINT32 AlgScratchSize;
+ LVM_UINT32 BundleScratchSize;
+ LVM_UINT16 InternalBlockSize;
+ INST_ALLOC AllocMem[LVM_NR_MEMORY_REGIONS];
+ LVM_INT16 i;
+
+
+ /*
+ * Check parameters
+ */
+ if(pMemoryTable == LVM_NULL)
+ {
+ return LVM_NULLADDRESS;
+ }
+
+
+ /*
+ * Return memory table if the instance has already been created
+ */
+ if (hInstance != LVM_NULL)
+ {
+ /* Read back memory allocation table */
+ *pMemoryTable = pInstance->MemoryTable;
+ return(LVM_SUCCESS);
+ }
+
+ if(pInstParams == LVM_NULL)
+ {
+ return LVM_NULLADDRESS;
+ }
+
+ /*
+ * Power Spectrum Analyser
+ */
+ if(pInstParams->PSA_Included > LVM_PSA_ON)
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /*
+ * Check the instance parameters
+ */
+ if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /* N-Band Equalizer */
+ if( pInstParams->EQNB_NumBands > 32 )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ }
+ else
+ {
+ if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ }
+
+ /*
+ * Initialise the AllocMem structures
+ */
+ for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+ {
+ InstAlloc_Init(&AllocMem[i], LVM_NULL);
+ }
+ InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
+
+ if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
+ {
+ InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
+ }
+
+ /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
+ if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
+ {
+ InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
+ }
+
+ /*
+ * Bundle requirements
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+ sizeof(LVM_Instance_t));
+
+
+ /*
+ * Set the algorithm and bundle scratch requirements
+ */
+ AlgScratchSize = 0;
+ if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ BundleScratchSize = 6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16);
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST], /* Scratch buffer */
+ BundleScratchSize);
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+ sizeof(LVM_Buffer_t));
+ }
+
+ /*
+ * Treble Enhancement requirements
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ sizeof(LVM_TE_Data_t));
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ sizeof(LVM_TE_Coefs_t));
+
+ /*
+ * N-Band Equalizer requirements
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA], /* Local storage */
+ (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA], /* User storage */
+ (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+
+ /*
+ * Concert Sound requirements
+ */
+ {
+ LVCS_MemTab_t CS_MemTab;
+ LVCS_Capabilities_t CS_Capabilities;
+
+ /*
+ * Set the capabilities
+ */
+ CS_Capabilities.MaxBlockSize = InternalBlockSize;
+
+ /*
+ * Get the memory requirements
+ */
+ LVCS_Memory(LVM_NULL,
+ &CS_MemTab,
+ &CS_Capabilities);
+
+ /*
+ * Update the memory allocation structures
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ CS_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+ if (CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = CS_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+ }
+
+
+ /*
+ * Dynamic Bass Enhancement requirements
+ */
+ {
+ LVDBE_MemTab_t DBE_MemTab;
+ LVDBE_Capabilities_t DBE_Capabilities;
+
+ /*
+ * Set the capabilities
+ */
+ DBE_Capabilities.SampleRate = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
+ DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
+ DBE_Capabilities.MaxBlockSize = InternalBlockSize;
+
+ /*
+ * Get the memory requirements
+ */
+ LVDBE_Memory(LVM_NULL,
+ &DBE_MemTab,
+
+ &DBE_Capabilities);
+ /*
+ * Update the bundle table
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ DBE_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+ if (DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = DBE_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+ }
+
+
+ /*
+ * N-Band equaliser requirements
+ */
+ {
+ LVEQNB_MemTab_t EQNB_MemTab; /* For N-Band Equaliser */
+ LVEQNB_Capabilities_t EQNB_Capabilities;
+
+ /*
+ * Set the capabilities
+ */
+ EQNB_Capabilities.SampleRate = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
+ EQNB_Capabilities.SourceFormat = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
+ EQNB_Capabilities.MaxBlockSize = InternalBlockSize;
+ EQNB_Capabilities.MaxBands = pInstParams->EQNB_NumBands;
+
+ /*
+ * Get the memory requirements
+ */
+ LVEQNB_Memory(LVM_NULL,
+ &EQNB_MemTab,
+ &EQNB_Capabilities);
+
+ /*
+ * Update the bundle table
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size);
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ EQNB_MemTab.Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size);
+ if (EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size > AlgScratchSize) AlgScratchSize = EQNB_MemTab.Region[LVM_MEMREGION_TEMPORARY_FAST].Size;
+
+ }
+
+ /*
+ * Headroom management memory allocation
+ */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+
+
+ /*
+ * Spectrum Analyzer memory requirements
+ */
+ {
+ pLVPSA_Handle_t hPSAInst = LVM_NULL;
+ LVPSA_MemTab_t PSA_MemTab;
+ LVPSA_InitParams_t PSA_InitParams;
+ LVPSA_FilterParam_t FiltersParams[9];
+ LVPSA_RETURN PSA_Status;
+
+ if(pInstParams->PSA_Included == LVM_PSA_ON)
+ {
+ PSA_InitParams.SpectralDataBufferDuration = (LVM_UINT16) 500;
+ PSA_InitParams.MaxInputBlockSize = (LVM_UINT16) 1000;
+ PSA_InitParams.nBands = (LVM_UINT16) 9;
+
+ PSA_InitParams.pFiltersParams = &FiltersParams[0];
+ for(i = 0; i < PSA_InitParams.nBands; i++)
+ {
+ FiltersParams[i].CenterFrequency = (LVM_UINT16) 1000;
+ FiltersParams[i].QFactor = (LVM_UINT16) 25;
+ FiltersParams[i].PostGain = (LVM_INT16) 0;
+ }
+
+ /*
+ * Get the memory requirements
+ */
+ PSA_Status = LVPSA_Memory (hPSAInst,
+ &PSA_MemTab,
+ &PSA_InitParams);
+
+ if (PSA_Status != LVPSA_OK)
+ {
+ return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+ }
+
+ /*
+ * Update the bundle table
+ */
+ /* Slow Data */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+ PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
+
+ /* Fast Data */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
+
+ /* Fast Coef */
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
+
+ /* Fast Temporary */
+ InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+ MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
+
+ if (PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size > AlgScratchSize)
+ {
+ AlgScratchSize = PSA_MemTab.Region[LVM_TEMPORARY_FAST].Size;
+ }
+ }
+ }
+
+ /*
+ * Return the memory table
+ */
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Size = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA]);
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].Type = LVM_PERSISTENT_SLOW_DATA;
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA]);
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Type = LVM_PERSISTENT_FAST_DATA;
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+ if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size < 4)
+ {
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_DATA].Size = 0;
+ }
+
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF]);
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+ if (pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size < 4)
+ {
+ pMemoryTable->Region[LVM_MEMREGION_PERSISTENT_FAST_COEF].Size = 0;
+ }
+
+ InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+ AlgScratchSize);
+ pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST]);
+ pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Type = LVM_TEMPORARY_FAST;
+ pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+ if (pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size < 4)
+ {
+ pMemoryTable->Region[LVM_MEMREGION_TEMPORARY_FAST].Size = 0;
+ }
+
+ return(LVM_SUCCESS);
+
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_GetInstanceHandle */
+/* */
+/* DESCRIPTION: */
+/* This function is used to create a bundle instance. It returns the created instance */
+/* handle through phInstance. All parameters are set to their default, inactive state. */
+/* */
+/* PARAMETERS: */
+/* phInstance pointer to the instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pInstParams Pointer to the initialisation capabilities */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Initialisation succeeded */
+/* LVM_OUTOFRANGE When any of the Instance parameters are out of range */
+/* LVM_NULLADDRESS When one of phInstance, pMemoryTable or pInstParams are NULL*/
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_GetInstanceHandle(LVM_Handle_t *phInstance,
+ LVM_MemTab_t *pMemoryTable,
+ LVM_InstParams_t *pInstParams)
+{
+
+ LVM_ReturnStatus_en Status = LVM_SUCCESS;
+ LVM_Instance_t *pInstance;
+ INST_ALLOC AllocMem[LVM_NR_MEMORY_REGIONS];
+ LVM_INT16 i;
+ LVM_UINT16 InternalBlockSize;
+ LVM_INT32 BundleScratchSize;
+
+
+ /*
+ * Check valid points have been given
+ */
+ if ((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pInstParams == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+
+ /*
+ * Check the memory table for NULL pointers
+ */
+ for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+ {
+ if ((pMemoryTable->Region[i].Size != 0) &&
+ (pMemoryTable->Region[i].pBaseAddress==LVM_NULL))
+ {
+ return(LVM_NULLADDRESS);
+ }
+ }
+
+ /*
+ * Check the instance parameters
+ */
+ if( (pInstParams->BufferMode != LVM_MANAGED_BUFFERS) && (pInstParams->BufferMode != LVM_UNMANAGED_BUFFERS) )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ if( pInstParams->EQNB_NumBands > 32 )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ if(pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_MANAGED_MAX_MAXBLOCKSIZE ) )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ }
+ else
+ {
+ if( (pInstParams->MaxBlockSize < LVM_MIN_MAXBLOCKSIZE ) || (pInstParams->MaxBlockSize > LVM_UNMANAGED_MAX_MAXBLOCKSIZE) )
+ {
+ return (LVM_OUTOFRANGE);
+ }
+ }
+
+ if(pInstParams->PSA_Included > LVM_PSA_ON)
+ {
+ return (LVM_OUTOFRANGE);
+ }
+
+ /*
+ * Initialise the AllocMem structures
+ */
+ for (i=0; i<LVM_NR_MEMORY_REGIONS; i++)
+ {
+ InstAlloc_Init(&AllocMem[i],
+ pMemoryTable->Region[i].pBaseAddress);
+ }
+
+
+ /*
+ * Set the instance handle
+ */
+ *phInstance = (LVM_Handle_t)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+ sizeof(LVM_Instance_t));
+ pInstance =(LVM_Instance_t *)*phInstance;
+
+
+ /*
+ * Save the memory table, parameters and capabilities
+ */
+ pInstance->MemoryTable = *pMemoryTable;
+ pInstance->InstParams = *pInstParams;
+
+
+ /*
+ * Set the bundle scratch memory and initialse the buffer management
+ */
+ InternalBlockSize = (LVM_UINT16)((pInstParams->MaxBlockSize) & MIN_INTERNAL_BLOCKMASK); /* Force to a multiple of MIN_INTERNAL_BLOCKSIZE */
+ if (InternalBlockSize < MIN_INTERNAL_BLOCKSIZE)
+ {
+ InternalBlockSize = MIN_INTERNAL_BLOCKSIZE;
+ }
+
+ /* Maximum Internal Black Size should not be more than MAX_INTERNAL_BLOCKSIZE*/
+ if(InternalBlockSize > MAX_INTERNAL_BLOCKSIZE)
+ {
+ InternalBlockSize = MAX_INTERNAL_BLOCKSIZE;
+ }
+ pInstance->InternalBlockSize = (LVM_INT16)InternalBlockSize;
+
+
+ /*
+ * Common settings for managed and unmanaged buffers
+ */
+ pInstance->SamplesToProcess = 0; /* No samples left to process */
+ if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ /*
+ * Managed buffers required
+ */
+ pInstance->pBufferManagement = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+ sizeof(LVM_Buffer_t));
+ BundleScratchSize = (LVM_INT32)(6 * (MIN_INTERNAL_BLOCKSIZE + InternalBlockSize) * sizeof(LVM_INT16));
+ pInstance->pBufferManagement->pScratch = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST], /* Scratch 1 buffer */
+ (LVM_UINT32)BundleScratchSize);
+
+ LoadConst_16(0, /* Clear the input delay buffer */
+ (LVM_INT16 *)&pInstance->pBufferManagement->InDelayBuffer,
+ (LVM_INT16)(2 * MIN_INTERNAL_BLOCKSIZE));
+ pInstance->pBufferManagement->InDelaySamples = MIN_INTERNAL_BLOCKSIZE; /* Set the number of delay samples */
+ pInstance->pBufferManagement->OutDelaySamples = 0; /* No samples in the output buffer */
+ pInstance->pBufferManagement->BufferState = LVM_FIRSTCALL; /* Set the state ready for the first call */
+ }
+
+
+ /*
+ * Set default parameters
+ */
+ pInstance->Params.OperatingMode = LVM_MODE_OFF;
+ pInstance->Params.SampleRate = LVM_FS_8000;
+ pInstance->Params.SourceFormat = LVM_MONO;
+ pInstance->Params.SpeakerType = LVM_HEADPHONES;
+ pInstance->Params.VC_EffectLevel = 0;
+ pInstance->Params.VC_Balance = 0;
+
+ /*
+ * Set callback
+ */
+ pInstance->CallBack = LVM_AlgoCallBack;
+
+
+ /*
+ * DC removal filter
+ */
+ DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+
+
+ /*
+ * Treble Enhancement
+ */
+ pInstance->pTE_Taps = (LVM_TE_Data_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ sizeof(LVM_TE_Data_t));
+
+ pInstance->pTE_State = (LVM_TE_Coefs_t *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ sizeof(LVM_TE_Coefs_t));
+ pInstance->Params.TE_OperatingMode = LVM_TE_OFF;
+ pInstance->Params.TE_EffectLevel = 0;
+ pInstance->TE_Active = LVM_FALSE;
+
+
+ /*
+ * Set the volume control and initialise Current to Target
+ */
+ pInstance->VC_Volume.MixerStream[0].CallbackParam = 0;
+ pInstance->VC_Volume.MixerStream[0].CallbackSet = 0;
+ pInstance->VC_Volume.MixerStream[0].pCallbackHandle = pInstance;
+ pInstance->VC_Volume.MixerStream[0].pCallBack = LVM_VCCallBack;
+
+ /* In managed buffering, start with low signal level as delay in buffer management causes a click*/
+ if (pInstParams->BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],0,0);
+ }
+ else
+ {
+ LVC_Mixer_Init(&pInstance->VC_Volume.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
+ }
+
+ LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,LVM_FS_8000,2);
+
+ pInstance->VC_VolumedB = 0;
+ pInstance->VC_AVLFixedVolume = 0;
+ pInstance->VC_Active = LVM_FALSE;
+
+ pInstance->VC_BalanceMix.MixerStream[0].CallbackParam = 0;
+ pInstance->VC_BalanceMix.MixerStream[0].CallbackSet = 0;
+ pInstance->VC_BalanceMix.MixerStream[0].pCallbackHandle = pInstance;
+ pInstance->VC_BalanceMix.MixerStream[0].pCallBack = LVM_VCCallBack;
+ LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[0],LVM_MAXINT_16,LVM_MAXINT_16);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+
+ pInstance->VC_BalanceMix.MixerStream[1].CallbackParam = 0;
+ pInstance->VC_BalanceMix.MixerStream[1].CallbackSet = 0;
+ pInstance->VC_BalanceMix.MixerStream[1].pCallbackHandle = pInstance;
+ pInstance->VC_BalanceMix.MixerStream[1].pCallBack = LVM_VCCallBack;
+ LVC_Mixer_Init(&pInstance->VC_BalanceMix.MixerStream[1],LVM_MAXINT_16,LVM_MAXINT_16);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LVM_FS_8000,2);
+ /*
+ * Set the default EQNB pre-gain and pointer to the band definitions
+ */
+ pInstance->pEQNB_BandDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+ pInstance->pEQNB_UserDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ (pInstParams->EQNB_NumBands * sizeof(LVM_EQNB_BandDef_t)));
+
+
+ /*
+ * Initialise the Concert Sound module
+ */
+ {
+ LVCS_Handle_t hCSInstance; /* Instance handle */
+ LVCS_MemTab_t CS_MemTab; /* Memory table */
+ LVCS_Capabilities_t CS_Capabilities; /* Initial capabilities */
+ LVCS_ReturnStatus_en LVCS_Status; /* Function call status */
+
+ /*
+ * Set default parameters
+ */
+ pInstance->Params.VirtualizerReverbLevel = 100;
+ pInstance->Params.VirtualizerType = LVM_CONCERTSOUND;
+ pInstance->Params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ pInstance->CS_Active = LVM_FALSE;
+
+ /*
+ * Set the initialisation capabilities
+ */
+ CS_Capabilities.MaxBlockSize = (LVM_UINT16)InternalBlockSize;
+ CS_Capabilities.CallBack = pInstance->CallBack;
+ CS_Capabilities.pBundleInstance = (void*)pInstance;
+
+
+ /*
+ * Get the memory requirements and then set the address pointers, forcing alignment
+ */
+ LVCS_Status = LVCS_Memory(LVM_NULL, /* Get the memory requirements */
+ &CS_MemTab,
+ &CS_Capabilities);
+ CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = &pInstance->CS_Instance;
+ CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size);
+ CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ CS_MemTab.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size);
+ CS_MemTab.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+ 0);
+
+ /*
+ * Initialise the Concert Sound instance and save the instance handle
+ */
+ hCSInstance = LVM_NULL; /* Set to NULL to return handle */
+ LVCS_Status = LVCS_Init(&hCSInstance, /* Initiailse */
+ &CS_MemTab,
+ &CS_Capabilities);
+ if (LVCS_Status != LVCS_SUCCESS) return((LVM_ReturnStatus_en)LVCS_Status);
+ pInstance->hCSInstance = hCSInstance; /* Save the instance handle */
+
+ }
+
+ /*
+ * Initialise the Bass Enhancement module
+ */
+ {
+ LVDBE_Handle_t hDBEInstance; /* Instance handle */
+ LVDBE_MemTab_t DBE_MemTab; /* Memory table */
+ LVDBE_Capabilities_t DBE_Capabilities; /* Initial capabilities */
+ LVDBE_ReturnStatus_en LVDBE_Status; /* Function call status */
+
+
+ /*
+ * Set the initialisation parameters
+ */
+ pInstance->Params.BE_OperatingMode = LVM_BE_OFF;
+ pInstance->Params.BE_CentreFreq = LVM_BE_CENTRE_55Hz;
+ pInstance->Params.BE_EffectLevel = 0;
+ pInstance->Params.BE_HPF = LVM_BE_HPF_OFF;
+
+ pInstance->DBE_Active = LVM_FALSE;
+
+
+
+ /*
+ * Set the initialisation capabilities
+ */
+ DBE_Capabilities.SampleRate = LVDBE_CAP_FS_8000 | LVDBE_CAP_FS_11025 | LVDBE_CAP_FS_12000 | LVDBE_CAP_FS_16000 | LVDBE_CAP_FS_22050 | LVDBE_CAP_FS_24000 | LVDBE_CAP_FS_32000 | LVDBE_CAP_FS_44100 | LVDBE_CAP_FS_48000;
+ DBE_Capabilities.CentreFrequency = LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_55Hz | LVDBE_CAP_CENTRE_66Hz | LVDBE_CAP_CENTRE_78Hz | LVDBE_CAP_CENTRE_90Hz;
+ DBE_Capabilities.MaxBlockSize = (LVM_UINT16)InternalBlockSize;
+
+
+ /*
+ * Get the memory requirements and then set the address pointers
+ */
+ LVDBE_Status = LVDBE_Memory(LVM_NULL, /* Get the memory requirements */
+ &DBE_MemTab,
+ &DBE_Capabilities);
+ DBE_MemTab.Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = &pInstance->DBE_Instance;
+ DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size);
+ DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ DBE_MemTab.Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size);
+ DBE_MemTab.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+ 0);
+
+
+ /*
+ * Initialise the Dynamic Bass Enhancement instance and save the instance handle
+ */
+ hDBEInstance = LVM_NULL; /* Set to NULL to return handle */
+ LVDBE_Status = LVDBE_Init(&hDBEInstance, /* Initiailse */
+ &DBE_MemTab,
+ &DBE_Capabilities);
+ if (LVDBE_Status != LVDBE_SUCCESS) return((LVM_ReturnStatus_en)LVDBE_Status);
+ pInstance->hDBEInstance = hDBEInstance; /* Save the instance handle */
+ }
+
+
+ /*
+ * Initialise the N-Band Equaliser module
+ */
+ {
+ LVEQNB_Handle_t hEQNBInstance; /* Instance handle */
+ LVEQNB_MemTab_t EQNB_MemTab; /* Memory table */
+ LVEQNB_Capabilities_t EQNB_Capabilities; /* Initial capabilities */
+ LVEQNB_ReturnStatus_en LVEQNB_Status; /* Function call status */
+
+
+ /*
+ * Set the initialisation parameters
+ */
+ pInstance->Params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ pInstance->Params.EQNB_NBands = 0;
+ pInstance->Params.pEQNB_BandDefinition = LVM_NULL;
+ pInstance->EQNB_Active = LVM_FALSE;
+
+
+ /*
+ * Set the initialisation capabilities
+ */
+ EQNB_Capabilities.SampleRate = LVEQNB_CAP_FS_8000 | LVEQNB_CAP_FS_11025 | LVEQNB_CAP_FS_12000 | LVEQNB_CAP_FS_16000 | LVEQNB_CAP_FS_22050 | LVEQNB_CAP_FS_24000 | LVEQNB_CAP_FS_32000 | LVEQNB_CAP_FS_44100 | LVEQNB_CAP_FS_48000;
+ EQNB_Capabilities.MaxBlockSize = (LVM_UINT16)InternalBlockSize;
+ EQNB_Capabilities.MaxBands = pInstParams->EQNB_NumBands;
+ EQNB_Capabilities.SourceFormat = LVEQNB_CAP_STEREO | LVEQNB_CAP_MONOINSTEREO;
+ EQNB_Capabilities.CallBack = pInstance->CallBack;
+ EQNB_Capabilities.pBundleInstance = (void*)pInstance;
+
+
+ /*
+ * Get the memory requirements and then set the address pointers, forcing alignment
+ */
+ LVEQNB_Status = LVEQNB_Memory(LVM_NULL, /* Get the memory requirements */
+ &EQNB_MemTab,
+ &EQNB_Capabilities);
+ EQNB_MemTab.Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = &pInstance->EQNB_Instance;
+ EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size);
+ EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ EQNB_MemTab.Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size);
+ EQNB_MemTab.Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],
+ 0);
+
+
+ /*
+ * Initialise the Dynamic Bass Enhancement instance and save the instance handle
+ */
+ hEQNBInstance = LVM_NULL; /* Set to NULL to return handle */
+ LVEQNB_Status = LVEQNB_Init(&hEQNBInstance, /* Initiailse */
+ &EQNB_MemTab,
+ &EQNB_Capabilities);
+ if (LVEQNB_Status != LVEQNB_SUCCESS) return((LVM_ReturnStatus_en)LVEQNB_Status);
+ pInstance->hEQNBInstance = hEQNBInstance; /* Save the instance handle */
+ }
+
+ /*
+ * Headroom management memory allocation
+ */
+ {
+ pInstance->pHeadroom_BandDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+ pInstance->pHeadroom_UserDefs = InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ (LVM_HEADROOM_MAX_NBANDS * sizeof(LVM_HeadroomBandDef_t)));
+
+ /* Headroom management parameters initialisation */
+ pInstance->NewHeadroomParams.NHeadroomBands = 2;
+ pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
+ pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_Low = 20;
+ pInstance->NewHeadroomParams.pHeadroomDefinition[0].Limit_High = 4999;
+ pInstance->NewHeadroomParams.pHeadroomDefinition[0].Headroom_Offset = 3;
+ pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_Low = 5000;
+ pInstance->NewHeadroomParams.pHeadroomDefinition[1].Limit_High = 24000;
+ pInstance->NewHeadroomParams.pHeadroomDefinition[1].Headroom_Offset = 4;
+ pInstance->NewHeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
+
+ pInstance->Headroom =0;
+ }
+
+
+ /*
+ * Initialise the PSA module
+ */
+ {
+ pLVPSA_Handle_t hPSAInstance = LVM_NULL; /* Instance handle */
+ LVPSA_MemTab_t PSA_MemTab;
+ LVPSA_RETURN PSA_Status; /* Function call status */
+ LVPSA_FilterParam_t FiltersParams[9];
+
+ if(pInstParams->PSA_Included==LVM_PSA_ON)
+ {
+ pInstance->PSA_InitParams.SpectralDataBufferDuration = (LVM_UINT16) 500;
+ pInstance->PSA_InitParams.MaxInputBlockSize = (LVM_UINT16) 2048;
+ pInstance->PSA_InitParams.nBands = (LVM_UINT16) 9;
+ pInstance->PSA_InitParams.pFiltersParams = &FiltersParams[0];
+ for(i = 0; i < pInstance->PSA_InitParams.nBands; i++)
+ {
+ FiltersParams[i].CenterFrequency = (LVM_UINT16) 1000;
+ FiltersParams[i].QFactor = (LVM_UINT16) 100;
+ FiltersParams[i].PostGain = (LVM_INT16) 0;
+ }
+
+ /*Get the memory requirements and then set the address pointers*/
+ PSA_Status = LVPSA_Memory (hPSAInstance,
+ &PSA_MemTab,
+ &pInstance->PSA_InitParams);
+
+ if (PSA_Status != LVPSA_OK)
+ {
+ return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+ }
+
+ /* Slow Data */
+ PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_SLOW_DATA],
+ PSA_MemTab.Region[LVM_PERSISTENT_SLOW_DATA].Size);
+
+
+ /* Fast Data */
+ PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_DATA],
+ PSA_MemTab.Region[LVM_PERSISTENT_FAST_DATA].Size);
+
+
+ /* Fast Coef */
+ PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_PERSISTENT_FAST_COEF],
+ PSA_MemTab.Region[LVM_PERSISTENT_FAST_COEF].Size);
+
+ /* Fast Temporary */
+ pInstance->pPSAInput = InstAlloc_AddMember(&AllocMem[LVM_TEMPORARY_FAST],
+ (LVM_UINT32) MAX_INTERNAL_BLOCKSIZE * sizeof(LVM_INT16));
+
+ PSA_MemTab.Region[LVM_TEMPORARY_FAST].pBaseAddress = (void *)InstAlloc_AddMember(&AllocMem[LVM_MEMREGION_TEMPORARY_FAST],0);
+
+
+ /*Initialise PSA instance and save the instance handle*/
+ pInstance->PSA_ControlParams.Fs = LVM_FS_48000;
+ pInstance->PSA_ControlParams.LevelDetectionSpeed = LVPSA_SPEED_MEDIUM;
+ PSA_Status = LVPSA_Init (&hPSAInstance,
+ &pInstance->PSA_InitParams,
+ &pInstance->PSA_ControlParams,
+ &PSA_MemTab);
+
+ if (PSA_Status != LVPSA_OK)
+ {
+ return((LVM_ReturnStatus_en) LVM_ALGORITHMPSA);
+ }
+
+ pInstance->hPSAInstance = hPSAInstance; /* Save the instance handle */
+ pInstance->PSA_GainOffset = 0;
+ }
+ else
+ {
+ pInstance->hPSAInstance = LVM_NULL;
+ }
+
+ /*
+ * Set the initialisation parameters.
+ */
+ pInstance->Params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
+ pInstance->Params.PSA_Enable = LVM_PSA_OFF;
+ }
+
+ /*
+ * Copy the initial parameters to the new parameters for correct readback of
+ * the settings.
+ */
+ pInstance->NewParams = pInstance->Params;
+
+
+ /*
+ * Create configuration number
+ */
+ pInstance->ConfigurationNumber = 0x00000000;
+ pInstance->ConfigurationNumber += LVM_CS_MASK;
+ pInstance->ConfigurationNumber += LVM_EQNB_MASK;
+ pInstance->ConfigurationNumber += LVM_DBE_MASK;
+ pInstance->ConfigurationNumber += LVM_VC_MASK;
+ pInstance->ConfigurationNumber += LVM_PSA_MASK;
+
+ if(((pInstance->ConfigurationNumber & LVM_CS_MASK)!=0) ||
+ ((pInstance->ConfigurationNumber & LVM_DBE_MASK)!=0) ||
+ ((pInstance->ConfigurationNumber & LVM_EQNB_MASK)!=0)||
+ ((pInstance->ConfigurationNumber & LVM_TE_MASK)!=0) ||
+ ((pInstance->ConfigurationNumber & LVM_VC_MASK)!=0))
+ {
+ pInstance->BlickSizeMultiple = 4;
+ }
+ else
+ {
+ pInstance->BlickSizeMultiple = 1;
+ }
+
+ return(Status);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_ClearAudioBuffers */
+/* */
+/* DESCRIPTION: */
+/* This function is used to clear the internal audio buffers of the bundle. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Initialisation succeeded */
+/* LVM_NULLADDRESS Instance or scratch memory has a NULL pointer */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVM_Process function */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ClearAudioBuffers(LVM_Handle_t hInstance)
+{
+ LVM_MemTab_t MemTab; /* Memory table */
+ LVM_InstParams_t InstParams; /* Instance parameters */
+ LVM_ControlParams_t Params; /* Control Parameters */
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance; /* Pointer to Instance */
+
+
+ if(hInstance == LVM_NULL){
+ return LVM_NULLADDRESS;
+ }
+
+ /* Save the control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
+ LVM_GetControlParameters(hInstance, &Params);
+
+ /* Retrieve allocated buffers in memtab */
+ LVM_GetMemoryTable(hInstance, &MemTab, LVM_NULL);
+
+ /* Save the instance parameters */
+ InstParams = pInstance->InstParams;
+
+ /* Call LVM_GetInstanceHandle to re-initialise the bundle */
+ LVM_GetInstanceHandle( &hInstance,
+ &MemTab,
+ &InstParams);
+
+ /* Restore control parameters */ /* coverity[unchecked_value] */ /* Do not check return value internal function calls */
+ LVM_SetControlParameters(hInstance, &Params);
+
+ /* DC removal filter */
+ DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+
+
+ return LVM_SUCCESS;
+}
+
+
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
new file mode 100755
index 0000000..f70e473
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1082 $
+ $Date: 2010-07-05 12:44:39 +0200 (Mon, 05 Jul 2010) $
+
+***********************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Header file for the private layer interface of concert sound bundle */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the execution layer. */
+/* */
+/************************************************************************************/
+
+#ifndef __LVM_PRIVATE_H__
+#define __LVM_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVM.h" /* LifeVibes */
+#include "LVM_Common.h" /* LifeVibes common */
+#include "BIQUAD.h" /* Biquad library */
+#include "LVC_Mixer.h" /* Mixer library */
+#include "LVCS_Private.h" /* Concert Sound */
+#include "LVDBE_Private.h" /* Dynamic Bass Enhancement */
+#include "LVEQNB_Private.h" /* N-Band equaliser */
+#include "LVPSA_Private.h" /* Parametric Spectrum Analyzer */
+
+
+/************************************************************************************/
+/* */
+/* Defines */
+/* */
+/************************************************************************************/
+
+/* General */
+#define LVM_INVALID 0xFFFF /* Invalid init parameter */
+
+/* Memory */
+#define LVM_INSTANCE_ALIGN 4 /* 32-bit for structures */
+#define LVM_FIRSTCALL 0 /* First call to the buffer */
+#define LVM_MAXBLOCKCALL 1 /* Maximum block size calls to the buffer */
+#define LVM_LASTCALL 2 /* Last call to the buffer */
+#define LVM_FIRSTLASTCALL 3 /* Single call for small number of samples */
+
+/* Block Size */
+#define LVM_MIN_MAXBLOCKSIZE 16 /* Minimum MaxBlockSize Limit*/
+#define LVM_MANAGED_MAX_MAXBLOCKSIZE 8191 /* Maximum MaxBlockSzie Limit for Managed Buffer Mode*/
+#define LVM_UNMANAGED_MAX_MAXBLOCKSIZE 4096 /* Maximum MaxBlockSzie Limit for Unmanaged Buffer Mode */
+
+#define MAX_INTERNAL_BLOCKSIZE 8128 /* Maximum multiple of 64 below 8191*/
+
+#define MIN_INTERNAL_BLOCKSIZE 16 /* Minimum internal block size */
+#define MIN_INTERNAL_BLOCKSHIFT 4 /* Minimum internal block size as a power of 2 */
+#define MIN_INTERNAL_BLOCKMASK 0xFFF0 /* Minimum internal block size mask */
+
+#define LVM_PSA_DYNAMICRANGE 60 /* Spectral Dynamic range: used for offseting output*/
+#define LVM_PSA_BARHEIGHT 127 /* Spectral Bar Height*/
+
+#define LVM_TE_MIN_EFFECTLEVEL 0 /*TE Minimum EffectLevel*/
+#define LVM_TE_MAX_EFFECTLEVEL 15 /*TE Maximum Effect level*/
+
+#define LVM_VC_MIN_EFFECTLEVEL -96 /*VC Minimum EffectLevel*/
+#define LVM_VC_MAX_EFFECTLEVEL 0 /*VC Maximum Effect level*/
+
+#define LVM_BE_MIN_EFFECTLEVEL 0 /*BE Minimum EffectLevel*/
+#define LVM_BE_MAX_EFFECTLEVEL 15 /*BE Maximum Effect level*/
+
+#define LVM_EQNB_MIN_BAND_FREQ 20 /*EQNB Minimum Band Frequency*/
+#define LVM_EQNB_MAX_BAND_FREQ 24000 /*EQNB Maximum Band Frequency*/
+#define LVM_EQNB_MIN_BAND_GAIN -15 /*EQNB Minimum Band Frequency*/
+#define LVM_EQNB_MAX_BAND_GAIN 15 /*EQNB Maximum Band Frequency*/
+#define LVM_EQNB_MIN_QFACTOR 25 /*EQNB Minimum Q Factor*/
+#define LVM_EQNB_MAX_QFACTOR 1200 /*EQNB Maximum Q Factor*/
+#define LVM_EQNB_MIN_LPF_FREQ 1000 /*EQNB Minimum Low Pass Corner frequency*/
+#define LVM_EQNB_MIN_HPF_FREQ 20 /*EQNB Minimum High Pass Corner frequency*/
+#define LVM_EQNB_MAX_HPF_FREQ 1000 /*EQNB Maximum High Pass Corner frequency*/
+
+#define LVM_CS_MIN_EFFECT_LEVEL 0 /*CS Minimum Effect Level*/
+#define LVM_CS_MAX_REVERB_LEVEL 100 /*CS Maximum Reverb Level*/
+#define LVM_VIRTUALIZER_MAX_REVERB_LEVEL 100 /*Vitrualizer Maximum Reverb Level*/
+
+#define LVM_VC_MIXER_TIME 100 /*VC mixer time*/
+#define LVM_VC_BALANCE_MAX 96 /*VC balance max value*/
+#define LVM_VC_BALANCE_MIN -96 /*VC balance min value*/
+
+/* Algorithm masks */
+#define LVM_CS_MASK 1
+#define LVM_EQNB_MASK 2
+#define LVM_DBE_MASK 4
+#define LVM_VC_MASK 16
+#define LVM_TE_MASK 32
+#define LVM_PSA_MASK 2048
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+ LVM_UINT32 Size; /* Region size in bytes */
+ LVM_UINT16 Alignment; /* Byte alignment */
+ LVM_MemoryTypes_en Type; /* Region type */
+ void *pBaseAddress; /* Pointer to the region base address */
+} LVM_IntMemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVM_IntMemoryRegion_t Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVM_IntMemTab_t;
+
+
+/* Buffer Management */
+typedef struct
+{
+ LVM_INT16 *pScratch; /* Bundle scratch buffer */
+
+ LVM_INT16 BufferState; /* Buffer status */
+ LVM_INT16 InDelayBuffer[6*MIN_INTERNAL_BLOCKSIZE]; /* Input buffer delay line, left and right */
+ LVM_INT16 InDelaySamples; /* Number of samples in the input delay buffer */
+
+ LVM_INT16 OutDelayBuffer[2*MIN_INTERNAL_BLOCKSIZE]; /* Output buffer delay line */
+ LVM_INT16 OutDelaySamples; /* Number of samples in the output delay buffer, left and right */
+ LVM_INT16 SamplesToOutput; /* Samples to write to the output */
+} LVM_Buffer_t;
+
+
+/* Filter taps */
+typedef struct
+{
+ Biquad_2I_Order1_Taps_t TrebleBoost_Taps; /* Treble boost Taps */
+} LVM_TE_Data_t;
+
+
+/* Coefficients */
+typedef struct
+{
+ Biquad_Instance_t TrebleBoost_State; /* State for the treble boost filter */
+} LVM_TE_Coefs_t;
+
+
+typedef struct
+{
+ /* Public parameters */
+ LVM_MemTab_t MemoryTable; /* Instance memory allocation table */
+ LVM_ControlParams_t Params; /* Control parameters */
+ LVM_InstParams_t InstParams; /* Instance parameters */
+
+ /* Private parameters */
+ LVM_UINT16 ControlPending; /* Control flag to indicate update pending */
+ LVM_ControlParams_t NewParams; /* New control parameters pending update */
+
+ /* Buffer control */
+ LVM_INT16 InternalBlockSize; /* Maximum internal block size */
+ LVM_Buffer_t *pBufferManagement; /* Buffer management variables */
+ LVM_INT16 SamplesToProcess; /* Input samples left to process */
+ LVM_INT16 *pInputSamples; /* External input sample pointer */
+ LVM_INT16 *pOutputSamples; /* External output sample pointer */
+
+ /* Configuration number */
+ LVM_INT32 ConfigurationNumber;
+ LVM_INT32 BlickSizeMultiple;
+
+ /* DC removal */
+ Biquad_Instance_t DC_RemovalInstance; /* DC removal filter instance */
+
+ /* Concert Sound */
+ LVCS_Handle_t hCSInstance; /* Concert Sound instance handle */
+ LVCS_Instance_t CS_Instance; /* Concert Sound instance */
+ LVM_INT16 CS_Active; /* Control flag */
+
+ /* Equalizer */
+ LVEQNB_Handle_t hEQNBInstance; /* N-Band Equaliser instance handle */
+ LVEQNB_Instance_t EQNB_Instance; /* N-Band Equaliser instance */
+ LVM_EQNB_BandDef_t *pEQNB_BandDefs; /* Local storage for new definitions */
+ LVM_EQNB_BandDef_t *pEQNB_UserDefs; /* Local storage for the user's definitions */
+ LVM_INT16 EQNB_Active; /* Control flag */
+
+ /* Dynamic Bass Enhancement */
+ LVDBE_Handle_t hDBEInstance; /* Dynamic Bass Enhancement instance handle */
+ LVDBE_Instance_t DBE_Instance; /* Dynamic Bass Enhancement instance */
+ LVM_INT16 DBE_Active; /* Control flag */
+
+ /* Volume Control */
+ LVMixer3_1St_st VC_Volume; /* Volume scaler */
+ LVMixer3_2St_st VC_BalanceMix; /* VC balance mixer */
+ LVM_INT16 VC_VolumedB; /* Gain in dB */
+ LVM_INT16 VC_Active; /* Control flag */
+ LVM_INT16 VC_AVLFixedVolume; /* AVL fixed volume */
+
+ /* Treble Enhancement */
+ LVM_TE_Data_t *pTE_Taps; /* Treble boost Taps */
+ LVM_TE_Coefs_t *pTE_State; /* State for the treble boost filter */
+ LVM_INT16 TE_Active; /* Control flag */
+
+ /* Headroom */
+ LVM_HeadroomParams_t NewHeadroomParams; /* New headroom parameters pending update */
+ LVM_HeadroomParams_t HeadroomParams; /* Headroom parameters */
+ LVM_HeadroomBandDef_t *pHeadroom_BandDefs; /* Local storage for new definitions */
+ LVM_HeadroomBandDef_t *pHeadroom_UserDefs; /* Local storage for the user's definitions */
+ LVM_UINT16 Headroom; /* Value of the current headroom */
+
+ /* Spectrum Analyzer */
+ pLVPSA_Handle_t hPSAInstance; /* Spectrum Analyzer instance handle */
+ LVPSA_InstancePr_t PSA_Instance; /* Spectrum Analyzer instance */
+ LVPSA_InitParams_t PSA_InitParams; /* Spectrum Analyzer initialization parameters */
+ LVPSA_ControlParams_t PSA_ControlParams; /* Spectrum Analyzer control parameters */
+ LVM_INT16 PSA_GainOffset; /* Tone control flag */
+ LVM_Callback CallBack;
+ LVM_INT16 *pPSAInput; /* PSA input pointer */
+
+ LVM_INT16 NoSmoothVolume; /* Enable or disable smooth volume changes*/
+
+} LVM_Instance_t;
+
+
+/************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/************************************************************************************/
+
+LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t hInstance);
+
+void LVM_SetTrebleBoost( LVM_Instance_t *pInstance,
+ LVM_ControlParams_t *pParams);
+
+void LVM_SetVolume( LVM_Instance_t *pInstance,
+ LVM_ControlParams_t *pParams);
+
+LVM_INT32 LVM_VCCallBack(void* pBundleHandle,
+ void* pGeneralPurpose,
+ short CallBackParam);
+
+void LVM_SetHeadroom( LVM_Instance_t *pInstance,
+ LVM_ControlParams_t *pParams);
+
+void LVM_BufferIn( LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples);
+
+void LVM_BufferOut( LVM_Handle_t hInstance,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 *pNumSamples);
+
+LVM_INT32 LVM_AlgoCallBack( void *pBundleHandle,
+ void *pData,
+ LVM_INT16 callbackId);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVM_PRIVATE_H__ */
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
new file mode 100755
index 0000000..bad9450
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1002 $
+ $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+#include "LVM_Coeffs.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LifeVibes module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* AudioTime Audio Time of the current input buffer in ms */
+/* */
+/* RETURNS: */
+/* LVM_SUCCESS Succeeded */
+/* LVM_INVALIDNUMSAMPLES When the NumSamples is not a valied multiple in unmanaged */
+/* buffer mode */
+/* LVM_ALIGNMENTERROR When either the input our output buffers are not 32-bit */
+/* aligned in unmanaged mode */
+/* LVM_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVM_ReturnStatus_en LVM_Process(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples,
+ LVM_UINT32 AudioTime)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_UINT16 SampleCount = NumSamples;
+ LVM_INT16 *pInput = (LVM_INT16 *)pInData;
+ LVM_INT16 *pToProcess = (LVM_INT16 *)pInData;
+ LVM_INT16 *pProcessed = pOutData;
+ LVM_ReturnStatus_en Status;
+
+ /*
+ * Check if the number of samples is zero
+ */
+ if (NumSamples == 0)
+ {
+ return(LVM_SUCCESS);
+ }
+
+
+ /*
+ * Check valid points have been given
+ */
+ if ((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+ {
+ return (LVM_NULLADDRESS);
+ }
+
+ /*
+ * For unmanaged mode only
+ */
+ if(pInstance->InstParams.BufferMode == LVM_UNMANAGED_BUFFERS)
+ {
+ /*
+ * Check if the number of samples is a good multiple (unmanaged mode only)
+ */
+ if((NumSamples % pInstance->BlickSizeMultiple) != 0)
+ {
+ return(LVM_INVALIDNUMSAMPLES);
+ }
+
+ /*
+ * Check the buffer alignment
+ */
+ if((((LVM_UINT32)pInData % 4) != 0) || (((LVM_UINT32)pOutData % 4) != 0))
+ {
+ return(LVM_ALIGNMENTERROR);
+ }
+ }
+
+
+ /*
+ * Update new parameters if necessary
+ */
+ if (pInstance->ControlPending == LVM_TRUE)
+ {
+ Status = LVM_ApplyNewSettings(hInstance);
+
+ if(Status != LVM_SUCCESS)
+ {
+ return Status;
+ }
+ }
+
+
+ /*
+ * Convert from Mono if necessary
+ */
+ if (pInstance->Params.SourceFormat == LVM_MONO)
+ {
+ MonoTo2I_16(pInData, /* Source */
+ pOutData, /* Destination */
+ (LVM_INT16)NumSamples); /* Number of input samples */
+ pInput = pOutData;
+ pToProcess = pOutData;
+ }
+
+
+ /*
+ * Process the data with managed buffers
+ */
+ while (SampleCount != 0)
+ {
+ /*
+ * Manage the input buffer and frame processing
+ */
+ LVM_BufferIn(hInstance,
+ pInput,
+ &pToProcess,
+ &pProcessed,
+ &SampleCount);
+
+ /*
+ * Only process data when SampleCount is none zero, a zero count can occur when
+ * the BufferIn routine is working in managed mode.
+ */
+ if (SampleCount != 0)
+ {
+
+ /*
+ * Apply ConcertSound if required
+ */
+ if (pInstance->CS_Active == LVM_TRUE)
+ {
+ (void)LVCS_Process(pInstance->hCSInstance, /* Concert Sound instance handle */
+ pToProcess,
+ pProcessed,
+ SampleCount);
+ pToProcess = pProcessed;
+ }
+
+ /*
+ * Apply volume if required
+ */
+ if (pInstance->VC_Active!=0)
+ {
+ LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
+ pToProcess,
+ pProcessed,
+ (LVM_INT16)(2*SampleCount)); /* Left and right*/
+ pToProcess = pProcessed;
+ }
+
+ /*
+ * Call N-Band equaliser if enabled
+ */
+ if (pInstance->EQNB_Active == LVM_TRUE)
+ {
+ LVEQNB_Process(pInstance->hEQNBInstance, /* N-Band equaliser instance handle */
+ pToProcess,
+ pProcessed,
+ SampleCount);
+ pToProcess = pProcessed;
+ }
+
+ /*
+ * Call bass enhancement if enabled
+ */
+ if (pInstance->DBE_Active == LVM_TRUE)
+ {
+ LVDBE_Process(pInstance->hDBEInstance, /* Dynamic Bass Enhancement instance handle */
+ pToProcess,
+ pProcessed,
+ SampleCount);
+ pToProcess = pProcessed;
+ }
+
+ /*
+ * Bypass mode or everything off, so copy the input to the output
+ */
+ if (pToProcess != pProcessed)
+ {
+ Copy_16(pToProcess, /* Source */
+ pProcessed, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Left and right */
+ }
+
+ /*
+ * Apply treble boost if required
+ */
+ if (pInstance->TE_Active == LVM_TRUE)
+ {
+ /*
+ * Apply the filter
+ */
+ FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
+ pProcessed,
+ pProcessed,
+ (LVM_INT16)SampleCount);
+
+ }
+
+ /*
+ * Volume balance
+ */
+ LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
+ pProcessed,
+ pProcessed,
+ SampleCount);
+
+ /*
+ * Perform Parametric Spectum Analysis
+ */
+ if ((pInstance->Params.PSA_Enable == LVM_PSA_ON)&&(pInstance->InstParams.PSA_Included==LVM_PSA_ON))
+ {
+ From2iToMono_16(pProcessed,
+ pInstance->pPSAInput,
+ (LVM_INT16) (SampleCount));
+
+ LVPSA_Process(pInstance->hPSAInstance,
+ pInstance->pPSAInput,
+ (LVM_UINT16) (SampleCount),
+ AudioTime);
+ }
+
+
+ /*
+ * DC removal
+ */
+ DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
+ pProcessed,
+ pProcessed,
+ (LVM_INT16)SampleCount);
+
+
+ }
+
+ /*
+ * Manage the output buffer
+ */
+ LVM_BufferOut(hInstance,
+ pOutData,
+ &SampleCount);
+
+ }
+
+ return(LVM_SUCCESS);
+}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
new file mode 100755
index 0000000..cb33541
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1002 $
+ $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVM_Tables.h"
+#include "LVM_Coeffs.h"
+
+/************************************************************************************/
+/* */
+/* Treble Boost Filter Coefficients */
+/* */
+/************************************************************************************/
+
+FO_C16_LShx_Coefs_t LVM_TrebleBoostCoefs[] = {
+
+ /* 22kHz sampling rate */
+ {HPF_Fs22050_Gain1_A1, /* Gain setting 1 */
+ HPF_Fs22050_Gain1_A0,
+ -HPF_Fs22050_Gain1_B1,
+ HPF_Fs22050_Gain1_Shift},
+ {HPF_Fs22050_Gain2_A1, /* Gain setting 2 */
+ HPF_Fs22050_Gain2_A0,
+ -HPF_Fs22050_Gain2_B1,
+ HPF_Fs22050_Gain2_Shift},
+ {HPF_Fs22050_Gain3_A1, /* Gain setting 3 */
+ HPF_Fs22050_Gain3_A0,
+ -HPF_Fs22050_Gain3_B1,
+ HPF_Fs22050_Gain3_Shift},
+ {HPF_Fs22050_Gain4_A1, /* Gain setting 4 */
+ HPF_Fs22050_Gain4_A0,
+ -HPF_Fs22050_Gain4_B1,
+ HPF_Fs22050_Gain4_Shift},
+ {HPF_Fs22050_Gain5_A1, /* Gain setting 5 */
+ HPF_Fs22050_Gain5_A0,
+ -HPF_Fs22050_Gain5_B1,
+ HPF_Fs22050_Gain5_Shift},
+ {HPF_Fs22050_Gain6_A1, /* Gain setting 6 */
+ HPF_Fs22050_Gain6_A0,
+ -HPF_Fs22050_Gain6_B1,
+ HPF_Fs22050_Gain6_Shift},
+ {HPF_Fs22050_Gain7_A1, /* Gain setting 7 */
+ HPF_Fs22050_Gain7_A0,
+ -HPF_Fs22050_Gain7_B1,
+ HPF_Fs22050_Gain7_Shift},
+ {HPF_Fs22050_Gain8_A1, /* Gain setting 8 */
+ HPF_Fs22050_Gain8_A0,
+ -HPF_Fs22050_Gain8_B1,
+ HPF_Fs22050_Gain8_Shift},
+ {HPF_Fs22050_Gain9_A1, /* Gain setting 9 */
+ HPF_Fs22050_Gain9_A0,
+ -HPF_Fs22050_Gain9_B1,
+ HPF_Fs22050_Gain9_Shift},
+ {HPF_Fs22050_Gain10_A1, /* Gain setting 10 */
+ HPF_Fs22050_Gain10_A0,
+ -HPF_Fs22050_Gain10_B1,
+ HPF_Fs22050_Gain10_Shift},
+ {HPF_Fs22050_Gain11_A1, /* Gain setting 11 */
+ HPF_Fs22050_Gain11_A0,
+ -HPF_Fs22050_Gain11_B1,
+ HPF_Fs22050_Gain11_Shift},
+ {HPF_Fs22050_Gain12_A1, /* Gain setting 12 */
+ HPF_Fs22050_Gain12_A0,
+ -HPF_Fs22050_Gain12_B1,
+ HPF_Fs22050_Gain12_Shift},
+ {HPF_Fs22050_Gain13_A1, /* Gain setting 13 */
+ HPF_Fs22050_Gain13_A0,
+ -HPF_Fs22050_Gain13_B1,
+ HPF_Fs22050_Gain13_Shift},
+ {HPF_Fs22050_Gain14_A1, /* Gain setting 14 */
+ HPF_Fs22050_Gain14_A0,
+ -HPF_Fs22050_Gain14_B1,
+ HPF_Fs22050_Gain14_Shift},
+ {HPF_Fs22050_Gain15_A1, /* Gain setting 15 */
+ HPF_Fs22050_Gain15_A0,
+ -HPF_Fs22050_Gain15_B1,
+ HPF_Fs22050_Gain15_Shift},
+
+ /* 24kHz sampling rate */
+ {HPF_Fs24000_Gain1_A1, /* Gain setting 1 */
+ HPF_Fs24000_Gain1_A0,
+ -HPF_Fs24000_Gain1_B1,
+ HPF_Fs24000_Gain1_Shift},
+ {HPF_Fs24000_Gain2_A1, /* Gain setting 2 */
+ HPF_Fs24000_Gain2_A0,
+ -HPF_Fs24000_Gain2_B1,
+ HPF_Fs24000_Gain2_Shift},
+ {HPF_Fs24000_Gain3_A1, /* Gain setting 3 */
+ HPF_Fs24000_Gain3_A0,
+ -HPF_Fs24000_Gain3_B1,
+ HPF_Fs24000_Gain3_Shift},
+ {HPF_Fs24000_Gain4_A1, /* Gain setting 4 */
+ HPF_Fs24000_Gain4_A0,
+ -HPF_Fs24000_Gain4_B1,
+ HPF_Fs24000_Gain4_Shift},
+ {HPF_Fs24000_Gain5_A1, /* Gain setting 5 */
+ HPF_Fs24000_Gain5_A0,
+ -HPF_Fs24000_Gain5_B1,
+ HPF_Fs24000_Gain5_Shift},
+ {HPF_Fs24000_Gain6_A1, /* Gain setting 6 */
+ HPF_Fs24000_Gain6_A0,
+ -HPF_Fs24000_Gain6_B1,
+ HPF_Fs24000_Gain6_Shift},
+ {HPF_Fs24000_Gain7_A1, /* Gain setting 7 */
+ HPF_Fs24000_Gain7_A0,
+ -HPF_Fs24000_Gain7_B1,
+ HPF_Fs24000_Gain7_Shift},
+ {HPF_Fs24000_Gain8_A1, /* Gain setting 8 */
+ HPF_Fs24000_Gain8_A0,
+ -HPF_Fs24000_Gain8_B1,
+ HPF_Fs24000_Gain8_Shift},
+ {HPF_Fs24000_Gain9_A1, /* Gain setting 9 */
+ HPF_Fs24000_Gain9_A0,
+ -HPF_Fs24000_Gain9_B1,
+ HPF_Fs24000_Gain9_Shift},
+ {HPF_Fs24000_Gain10_A1, /* Gain setting 10 */
+ HPF_Fs24000_Gain10_A0,
+ -HPF_Fs24000_Gain10_B1,
+ HPF_Fs24000_Gain10_Shift},
+ {HPF_Fs24000_Gain11_A1, /* Gain setting 11 */
+ HPF_Fs24000_Gain11_A0,
+ -HPF_Fs24000_Gain11_B1,
+ HPF_Fs24000_Gain11_Shift},
+ {HPF_Fs24000_Gain12_A1, /* Gain setting 12 */
+ HPF_Fs24000_Gain12_A0,
+ -HPF_Fs24000_Gain12_B1,
+ HPF_Fs24000_Gain12_Shift},
+ {HPF_Fs24000_Gain13_A1, /* Gain setting 13 */
+ HPF_Fs24000_Gain13_A0,
+ -HPF_Fs24000_Gain13_B1,
+ HPF_Fs24000_Gain13_Shift},
+ {HPF_Fs24000_Gain14_A1, /* Gain setting 14 */
+ HPF_Fs24000_Gain14_A0,
+ -HPF_Fs24000_Gain14_B1,
+ HPF_Fs24000_Gain14_Shift},
+ {HPF_Fs24000_Gain15_A1, /* Gain setting 15 */
+ HPF_Fs24000_Gain15_A0,
+ -HPF_Fs24000_Gain15_B1,
+ HPF_Fs24000_Gain15_Shift},
+
+ /* 32kHz sampling rate */
+ {HPF_Fs32000_Gain1_A1, /* Gain setting 1 */
+ HPF_Fs32000_Gain1_A0,
+ -HPF_Fs32000_Gain1_B1,
+ HPF_Fs32000_Gain1_Shift},
+ {HPF_Fs32000_Gain2_A1, /* Gain setting 2 */
+ HPF_Fs32000_Gain2_A0,
+ -HPF_Fs32000_Gain2_B1,
+ HPF_Fs32000_Gain2_Shift},
+ {HPF_Fs32000_Gain3_A1, /* Gain setting 3 */
+ HPF_Fs32000_Gain3_A0,
+ -HPF_Fs32000_Gain3_B1,
+ HPF_Fs32000_Gain3_Shift},
+ {HPF_Fs32000_Gain4_A1, /* Gain setting 4 */
+ HPF_Fs32000_Gain4_A0,
+ -HPF_Fs32000_Gain4_B1,
+ HPF_Fs32000_Gain4_Shift},
+ {HPF_Fs32000_Gain5_A1, /* Gain setting 5 */
+ HPF_Fs32000_Gain5_A0,
+ -HPF_Fs32000_Gain5_B1,
+ HPF_Fs32000_Gain5_Shift},
+ {HPF_Fs32000_Gain6_A1, /* Gain setting 6 */
+ HPF_Fs32000_Gain6_A0,
+ -HPF_Fs32000_Gain6_B1,
+ HPF_Fs32000_Gain6_Shift},
+ {HPF_Fs32000_Gain7_A1, /* Gain setting 7 */
+ HPF_Fs32000_Gain7_A0,
+ -HPF_Fs32000_Gain7_B1,
+ HPF_Fs32000_Gain7_Shift},
+ {HPF_Fs32000_Gain8_A1, /* Gain setting 8 */
+ HPF_Fs32000_Gain8_A0,
+ -HPF_Fs32000_Gain8_B1,
+ HPF_Fs32000_Gain8_Shift},
+ {HPF_Fs32000_Gain9_A1, /* Gain setting 9 */
+ HPF_Fs32000_Gain9_A0,
+ -HPF_Fs32000_Gain9_B1,
+ HPF_Fs32000_Gain9_Shift},
+ {HPF_Fs32000_Gain10_A1, /* Gain setting 10 */
+ HPF_Fs32000_Gain10_A0,
+ -HPF_Fs32000_Gain10_B1,
+ HPF_Fs32000_Gain10_Shift},
+ {HPF_Fs32000_Gain11_A1, /* Gain setting 11 */
+ HPF_Fs32000_Gain11_A0,
+ -HPF_Fs32000_Gain11_B1,
+ HPF_Fs32000_Gain11_Shift},
+ {HPF_Fs32000_Gain12_A1, /* Gain setting 12 */
+ HPF_Fs32000_Gain12_A0,
+ -HPF_Fs32000_Gain12_B1,
+ HPF_Fs32000_Gain12_Shift},
+ {HPF_Fs32000_Gain13_A1, /* Gain setting 13 */
+ HPF_Fs32000_Gain13_A0,
+ -HPF_Fs32000_Gain13_B1,
+ HPF_Fs32000_Gain13_Shift},
+ {HPF_Fs32000_Gain14_A1, /* Gain setting 14 */
+ HPF_Fs32000_Gain14_A0,
+ -HPF_Fs32000_Gain14_B1,
+ HPF_Fs32000_Gain14_Shift},
+ {HPF_Fs32000_Gain15_A1, /* Gain setting 15 */
+ HPF_Fs32000_Gain15_A0,
+ -HPF_Fs32000_Gain15_B1,
+ HPF_Fs32000_Gain15_Shift},
+
+ /* 44kHz sampling rate */
+ {HPF_Fs44100_Gain1_A1, /* Gain setting 1 */
+ HPF_Fs44100_Gain1_A0,
+ -HPF_Fs44100_Gain1_B1,
+ HPF_Fs44100_Gain1_Shift},
+ {HPF_Fs44100_Gain2_A1, /* Gain setting 2 */
+ HPF_Fs44100_Gain2_A0,
+ -HPF_Fs44100_Gain2_B1,
+ HPF_Fs44100_Gain2_Shift},
+ {HPF_Fs44100_Gain3_A1, /* Gain setting 3 */
+ HPF_Fs44100_Gain3_A0,
+ -HPF_Fs44100_Gain3_B1,
+ HPF_Fs44100_Gain3_Shift},
+ {HPF_Fs44100_Gain4_A1, /* Gain setting 4 */
+ HPF_Fs44100_Gain4_A0,
+ -HPF_Fs44100_Gain4_B1,
+ HPF_Fs44100_Gain4_Shift},
+ {HPF_Fs44100_Gain5_A1, /* Gain setting 5 */
+ HPF_Fs44100_Gain5_A0,
+ -HPF_Fs44100_Gain5_B1,
+ HPF_Fs44100_Gain5_Shift},
+ {HPF_Fs44100_Gain6_A1, /* Gain setting 6 */
+ HPF_Fs44100_Gain6_A0,
+ -HPF_Fs44100_Gain6_B1,
+ HPF_Fs44100_Gain6_Shift},
+ {HPF_Fs44100_Gain7_A1, /* Gain setting 7 */
+ HPF_Fs44100_Gain7_A0,
+ -HPF_Fs44100_Gain7_B1,
+ HPF_Fs44100_Gain7_Shift},
+ {HPF_Fs44100_Gain8_A1, /* Gain setting 8 */
+ HPF_Fs44100_Gain8_A0,
+ -HPF_Fs44100_Gain8_B1,
+ HPF_Fs44100_Gain8_Shift},
+ {HPF_Fs44100_Gain9_A1, /* Gain setting 9 */
+ HPF_Fs44100_Gain9_A0,
+ -HPF_Fs44100_Gain9_B1,
+ HPF_Fs44100_Gain9_Shift},
+ {HPF_Fs44100_Gain10_A1, /* Gain setting 10 */
+ HPF_Fs44100_Gain10_A0,
+ -HPF_Fs44100_Gain10_B1,
+ HPF_Fs44100_Gain10_Shift},
+ {HPF_Fs44100_Gain11_A1, /* Gain setting 11 */
+ HPF_Fs44100_Gain11_A0,
+ -HPF_Fs44100_Gain11_B1,
+ HPF_Fs44100_Gain11_Shift},
+ {HPF_Fs44100_Gain12_A1, /* Gain setting 12 */
+ HPF_Fs44100_Gain12_A0,
+ -HPF_Fs44100_Gain12_B1,
+ HPF_Fs44100_Gain12_Shift},
+ {HPF_Fs44100_Gain13_A1, /* Gain setting 13 */
+ HPF_Fs44100_Gain13_A0,
+ -HPF_Fs44100_Gain13_B1,
+ HPF_Fs44100_Gain13_Shift},
+ {HPF_Fs44100_Gain14_A1, /* Gain setting 14 */
+ HPF_Fs44100_Gain14_A0,
+ -HPF_Fs44100_Gain14_B1,
+ HPF_Fs44100_Gain14_Shift},
+ {HPF_Fs44100_Gain15_A1, /* Gain setting 15 */
+ HPF_Fs44100_Gain15_A0,
+ -HPF_Fs44100_Gain15_B1,
+ HPF_Fs44100_Gain15_Shift},
+
+ /* 48kHz sampling rate */
+ {HPF_Fs48000_Gain1_A1, /* Gain setting 1 */
+ HPF_Fs48000_Gain1_A0,
+ -HPF_Fs48000_Gain1_B1,
+ HPF_Fs48000_Gain1_Shift},
+ {HPF_Fs48000_Gain2_A1, /* Gain setting 2 */
+ HPF_Fs48000_Gain2_A0,
+ -HPF_Fs48000_Gain2_B1,
+ HPF_Fs48000_Gain2_Shift},
+ {HPF_Fs48000_Gain3_A1, /* Gain setting 3 */
+ HPF_Fs48000_Gain3_A0,
+ -HPF_Fs48000_Gain3_B1,
+ HPF_Fs48000_Gain3_Shift},
+ {HPF_Fs48000_Gain4_A1, /* Gain setting 4 */
+ HPF_Fs48000_Gain4_A0,
+ -HPF_Fs48000_Gain4_B1,
+ HPF_Fs48000_Gain4_Shift},
+ {HPF_Fs48000_Gain5_A1, /* Gain setting 5 */
+ HPF_Fs48000_Gain5_A0,
+ -HPF_Fs48000_Gain5_B1,
+ HPF_Fs48000_Gain5_Shift},
+ {HPF_Fs48000_Gain6_A1, /* Gain setting 6 */
+ HPF_Fs48000_Gain6_A0,
+ -HPF_Fs48000_Gain6_B1,
+ HPF_Fs48000_Gain6_Shift},
+ {HPF_Fs48000_Gain7_A1, /* Gain setting 7 */
+ HPF_Fs48000_Gain7_A0,
+ -HPF_Fs48000_Gain7_B1,
+ HPF_Fs48000_Gain7_Shift},
+ {HPF_Fs48000_Gain8_A1, /* Gain setting 8 */
+ HPF_Fs48000_Gain8_A0,
+ -HPF_Fs48000_Gain8_B1,
+ HPF_Fs48000_Gain8_Shift},
+ {HPF_Fs48000_Gain9_A1, /* Gain setting 9 */
+ HPF_Fs48000_Gain9_A0,
+ -HPF_Fs48000_Gain9_B1,
+ HPF_Fs48000_Gain9_Shift},
+ {HPF_Fs48000_Gain10_A1, /* Gain setting 10 */
+ HPF_Fs48000_Gain10_A0,
+ -HPF_Fs48000_Gain10_B1,
+ HPF_Fs48000_Gain10_Shift},
+ {HPF_Fs48000_Gain11_A1, /* Gain setting 11 */
+ HPF_Fs48000_Gain11_A0,
+ -HPF_Fs48000_Gain11_B1,
+ HPF_Fs48000_Gain11_Shift},
+ {HPF_Fs48000_Gain12_A1, /* Gain setting 12 */
+ HPF_Fs48000_Gain12_A0,
+ -HPF_Fs48000_Gain12_B1,
+ HPF_Fs48000_Gain12_Shift},
+ {HPF_Fs48000_Gain13_A1, /* Gain setting 13 */
+ HPF_Fs48000_Gain13_A0,
+ -HPF_Fs48000_Gain13_B1,
+ HPF_Fs48000_Gain13_Shift},
+ {HPF_Fs48000_Gain14_A1, /* Gain setting 14 */
+ HPF_Fs48000_Gain14_A0,
+ -HPF_Fs48000_Gain14_B1,
+ HPF_Fs48000_Gain14_Shift},
+ {HPF_Fs48000_Gain15_A1, /* Gain setting 15 */
+ HPF_Fs48000_Gain15_A0,
+ -HPF_Fs48000_Gain15_B1,
+ HPF_Fs48000_Gain15_Shift}};
+
+
+/************************************************************************************/
+/* */
+/* Volume control gain and time constant tables */
+/* */
+/************************************************************************************/
+
+/* dB to linear conversion table */
+const LVM_INT16 LVM_VolumeTable[] = {
+ 0x7FFF, /* 0dB */
+ 0x7215, /* -1dB */
+ 0x65AD, /* -2dB */
+ 0x5A9E, /* -3dB */
+ 0x50C3, /* -4dB */
+ 0x47FB, /* -5dB */
+ 0x4000}; /* -6dB */
+
+/************************************************************************************/
+/* */
+/* Volume mixer time constants (100ms) */
+/* */
+/************************************************************************************/
+
+#define LVM_MIX_TC_Fs8000 32580 /* Floating point value 0.994262695 */
+#define LVM_MIX_TC_Fs11025 32632 /* Floating point value 0.995849609 */
+#define LVM_MIX_TC_Fs12000 32643 /* Floating point value 0.996185303 */
+#define LVM_MIX_TC_Fs16000 32674 /* Floating point value 0.997131348 */
+#define LVM_MIX_TC_Fs22050 32700 /* Floating point value 0.997924805 */
+#define LVM_MIX_TC_Fs24000 32705 /* Floating point value 0.998077393 */
+#define LVM_MIX_TC_Fs32000 32721 /* Floating point value 0.998565674 */
+#define LVM_MIX_TC_Fs44100 32734 /* Floating point value 0.998962402 */
+#define LVM_MIX_TC_Fs48000 32737 /* Floating point value 0.999053955 */
+
+
+const LVM_INT16 LVM_MixerTCTable[] = {
+ LVM_MIX_TC_Fs8000,
+ LVM_MIX_TC_Fs11025,
+ LVM_MIX_TC_Fs12000,
+ LVM_MIX_TC_Fs16000,
+ LVM_MIX_TC_Fs22050,
+ LVM_MIX_TC_Fs24000,
+ LVM_MIX_TC_Fs32000,
+ LVM_MIX_TC_Fs44100,
+ LVM_MIX_TC_Fs48000};
+
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
new file mode 100755
index 0000000..574f641
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Tables.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1002 $
+ $Date: 2010-06-28 13:40:09 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVM_TABLES_H__
+#define __LVM_TABLES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "BIQUAD.h"
+#include "LVM_Types.h"
+
+/************************************************************************************/
+/* */
+/* Treble Boost Filter Coefficients */
+/* */
+/************************************************************************************/
+
+extern FO_C16_LShx_Coefs_t LVM_TrebleBoostCoefs[];
+
+
+/************************************************************************************/
+/* */
+/* Volume control gain and time constant tables */
+/* */
+/************************************************************************************/
+
+extern const LVM_INT16 LVM_VolumeTable[];
+extern const LVM_INT16 LVM_MixerTCTable[];
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVM_TABLES_H__ */
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
new file mode 100755
index 0000000..980a8e3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __AGC_H__
+#define __AGC_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************/
+/* */
+/* Includes */
+/* */
+/**********************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/**********************************************************************************/
+/* */
+/* Types */
+/* */
+/**********************************************************************************/
+
+typedef struct
+{
+ LVM_INT32 AGC_Gain; /* The current AGC gain */
+ LVM_INT32 AGC_MaxGain; /* The maximum AGC gain */
+ LVM_INT32 Volume; /* The current volume setting */
+ LVM_INT32 Target; /* The target volume setting */
+ LVM_INT32 AGC_Target; /* AGC target level */
+ LVM_INT16 AGC_Attack; /* AGC attack scaler */
+ LVM_INT16 AGC_Decay; /* AGC decay scaler */
+ LVM_INT16 AGC_GainShift; /* The gain shift */
+ LVM_INT16 VolumeShift; /* Volume shift scaling */
+ LVM_INT16 VolumeTC; /* Volume update time constant */
+
+} AGC_MIX_VOL_2St1Mon_D32_t;
+
+
+/**********************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/**********************************************************************************/
+
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t *pInstance, /* Instance pointer */
+ const LVM_INT32 *pStSrc, /* Stereo source */
+ const LVM_INT32 *pMonoSrc, /* Mono source */
+ LVM_INT32 *pDst, /* Stereo destination */
+ LVM_UINT16 n); /* Number of samples */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __AGC_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
new file mode 100755
index 0000000..08e5a6f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 722 $
+ $Date: 2010-06-10 15:12:34 +0200 (Thu, 10 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _BIQUAD_H_
+#define _BIQUAD_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+/**********************************************************************************
+ INSTANCE MEMORY TYPE DEFINITION
+***********************************************************************************/
+
+typedef struct
+{
+ LVM_INT32 Storage[6];
+
+} Biquad_Instance_t;
+
+
+/**********************************************************************************
+ COEFFICIENT TYPE DEFINITIONS
+***********************************************************************************/
+
+/*** Biquad coefficients **********************************************************/
+typedef struct
+{
+ LVM_INT16 A2; /* a2 */
+ LVM_INT16 A1; /* a1 */
+ LVM_INT16 A0; /* a0 */
+ LVM_INT16 B2; /* -b2! */
+ LVM_INT16 B1; /* -b1! */
+} BQ_C16_Coefs_t;
+
+typedef struct
+{
+ LVM_INT32 A2; /* a2 */
+ LVM_INT32 A1; /* a1 */
+ LVM_INT32 A0; /* a0 */
+ LVM_INT32 B2; /* -b2! */
+ LVM_INT32 B1; /* -b1! */
+} BQ_C32_Coefs_t;
+
+/*** First order coefficients *****************************************************/
+typedef struct
+{
+ LVM_INT16 A1; /* a1 */
+ LVM_INT16 A0; /* a0 */
+ LVM_INT16 B1; /* -b1! */
+} FO_C16_Coefs_t;
+
+typedef struct
+{
+ LVM_INT32 A1; /* a1 */
+ LVM_INT32 A0; /* a0 */
+ LVM_INT32 B1; /* -b1! */
+} FO_C32_Coefs_t;
+
+/*** First order coefficients with Shift*****************************************************/
+typedef struct
+{
+ LVM_INT16 A1; /* a1 */
+ LVM_INT16 A0; /* a0 */
+ LVM_INT16 B1; /* -b1! */
+ LVM_INT16 Shift; /* Shift */
+} FO_C16_LShx_Coefs_t;
+
+/*** Band pass coefficients *******************************************************/
+typedef struct
+{
+ LVM_INT16 A0; /* a0 */
+ LVM_INT16 B2; /* -b2! */
+ LVM_INT16 B1; /* -b1! */
+} BP_C16_Coefs_t;
+
+typedef struct
+{
+ LVM_INT32 A0; /* a0 */
+ LVM_INT32 B2; /* -b2! */
+ LVM_INT32 B1; /* -b1! */
+} BP_C32_Coefs_t;
+
+/*** Peaking coefficients *********************************************************/
+typedef struct
+{
+ LVM_INT16 A0; /* a0 */
+ LVM_INT16 B2; /* -b2! */
+ LVM_INT16 B1; /* -b1! */
+ LVM_INT16 G; /* Gain */
+} PK_C16_Coefs_t;
+
+typedef struct
+{
+ LVM_INT32 A0; /* a0 */
+ LVM_INT32 B2; /* -b2! */
+ LVM_INT32 B1; /* -b1! */
+ LVM_INT16 G; /* Gain */
+} PK_C32_Coefs_t;
+
+
+/**********************************************************************************
+ TAPS TYPE DEFINITIONS
+***********************************************************************************/
+
+/*** Types used for first order and shelving filter *******************************/
+
+typedef struct
+{
+ LVM_INT32 Storage[ (1*2) ]; /* One channel, two taps of size LVM_INT32 */
+} Biquad_1I_Order1_Taps_t;
+
+typedef struct
+{
+ LVM_INT32 Storage[ (2*2) ]; /* Two channels, two taps of size LVM_INT32 */
+} Biquad_2I_Order1_Taps_t;
+
+
+/*** Types used for biquad, band pass and peaking filter **************************/
+
+typedef struct
+{
+ LVM_INT32 Storage[ (1*4) ]; /* One channel, four taps of size LVM_INT32 */
+} Biquad_1I_Order2_Taps_t;
+
+typedef struct
+{
+ LVM_INT32 Storage[ (2*4) ]; /* Two channels, four taps of size LVM_INT32 */
+} Biquad_2I_Order2_Taps_t;
+
+/* The names of the functions are changed to satisfy QAC rules: Name should be Unique withing 16 characters*/
+#define BQ_2I_D32F32Cll_TRC_WRA_01_Init Init_BQ_2I_D32F32Cll_TRC_WRA_01
+#define BP_1I_D32F32C30_TRC_WRA_02 TWO_BP_1I_D32F32C30_TRC_WRA_02
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES: BIQUAD FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path *************************************************************/
+
+void BQ_2I_D16F32Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef);
+
+void BQ_2I_D16F32C15_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BQ_2I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BQ_2I_D16F32C13_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BQ_2I_D16F16Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef);
+
+void BQ_2I_D16F16C15_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BQ_2I_D16F16C14_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BQ_1I_D16F16Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef);
+
+void BQ_1I_D16F16C15_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BQ_1I_D16F32Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef);
+
+void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+/*** 32 bit data path *************************************************************/
+
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ BQ_C32_Coefs_t *pCoef);
+
+void BQ_2I_D32F32C30_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples);
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES: FIRST ORDER FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path *************************************************************/
+
+void FO_1I_D16F16Css_TRC_WRA_01_Init( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order1_Taps_t *pTaps,
+ FO_C16_Coefs_t *pCoef);
+
+void FO_1I_D16F16C15_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t *pInstance,
+ Biquad_2I_Order1_Taps_t *pTaps,
+ FO_C16_LShx_Coefs_t *pCoef);
+
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+/*** 32 bit data path *************************************************************/
+
+void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order1_Taps_t *pTaps,
+ FO_C32_Coefs_t *pCoef);
+
+void FO_1I_D32F32C31_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples);
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES: BAND PASS FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path *************************************************************/
+
+void BP_1I_D16F16Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BP_C16_Coefs_t *pCoef);
+
+void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void BP_1I_D16F32Cll_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BP_C32_Coefs_t *pCoef);
+
+void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+
+/*** 32 bit data path *************************************************************/
+
+void BP_1I_D32F32Cll_TRC_WRA_02_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BP_C32_Coefs_t *pCoef);
+
+void BP_1I_D32F32C30_TRC_WRA_02( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples);
+
+
+/*** 32 bit data path STEREO ******************************************************/
+
+void PK_2I_D32F32CllGss_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ PK_C32_Coefs_t *pCoef);
+
+void PK_2I_D32F32C30G11_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples);
+
+void PK_2I_D32F32CssGss_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ PK_C16_Coefs_t *pCoef);
+
+void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples);
+
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES: DC REMOVAL FILTERS
+***********************************************************************************/
+
+/*** 16 bit data path STEREO ******************************************************/
+
+void DC_2I_D16_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance);
+
+void DC_2I_D16_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/**********************************************************************************/
+
+#endif /** _BIQUAD_H_ **/
+
diff --git a/media/libeffects/lvm/lib/Common/lib/CompLim.h b/media/libeffects/lvm/lib/Common/lib/CompLim.h
new file mode 100755
index 0000000..df9b583
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/CompLim.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: nxp27078 $
+ $Revision: 672 $
+ $Date: 2010-06-08 19:39:38 +0200 (Tue, 08 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _COMP_LIM_H
+#define _COMP_LIM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVM_Types.h"
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+typedef struct /* Compressor state */
+{
+ /* Normaliser */
+ LVM_INT16 Norm_Attack; /* Attack time constant of the Normaliser integrator */
+ LVM_INT16 Norm_Decay; /* Decay time constant of the Normaliser integrator */
+ LVM_INT32 NormInt; /* Normaliser integrator current value */
+ LVM_INT16 Shift; /* Shift gain */
+ LVM_INT16 Threshold; /* Target threshold */
+
+ /* Compressor */
+ LVM_INT16 Comp_Atten; /* Attenuation applied before soft knee compressor */
+ LVM_INT16 Comp_Attack_S; /* Attack time constant of the slow integrator */
+ LVM_INT16 Comp_Decay_S; /* Decay time constant of slow the integrator */
+ LVM_INT16 Comp_Attack_F; /* Attack time constant of fast the integrator */
+ LVM_INT16 Comp_Decay_F; /* Decay time constant of fast the integrator */
+ LVM_INT16 SoftClipGain; /* Soft clip gain control */
+ LVM_INT32 CompIntSlow; /* Compressor slow integrator current value */
+ LVM_INT32 CompIntFast; /* Compressor fast integrator current value */
+
+
+} CompLim_Instance_t;
+
+
+/************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/************************************************************************************/
+
+void NonLinComp_D16(LVM_INT16 Gain,
+ LVM_INT16 *pSterBfIn,
+ LVM_INT16 *pSterBfOut,
+ LVM_INT32 BlockLength);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* #ifndef _COMP_LIM_H */
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/Filter.h b/media/libeffects/lvm/lib/Common/lib/Filter.h
new file mode 100755
index 0000000..93ccbcb
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/Filter.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 771 $*/
+/* $Date: 2010-06-14 10:41:36 +0200 (Mon, 14 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#ifndef _FILTER_H_
+#define _FILTER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+ INCLUDES
+***********************************************************************************/
+#include "LVM_Types.h"
+#include "BIQUAD.h"
+
+
+/**********************************************************************************
+ DEFINES
+***********************************************************************************/
+#define FILTER_LOSS 32730 /* -0.01dB loss to avoid wrapping due to band ripple */
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES
+***********************************************************************************/
+
+LVM_INT32 LVM_Polynomial(LVM_UINT16 N,
+ LVM_INT32 *pCoefficients,
+ LVM_INT32 X);
+
+LVM_INT32 LVM_Power10( LVM_INT32 X);
+
+LVM_INT32 LVM_FO_LPF( LVM_INT32 w,
+ FO_C32_Coefs_t *pCoeffs);
+
+LVM_INT32 LVM_FO_HPF( LVM_INT32 w,
+ FO_C32_Coefs_t *pCoeffs);
+
+LVM_INT32 LVM_GetOmega(LVM_UINT16 Fc,
+ LVM_Fs_en SampleRate);
+
+/**********************************************************************************/
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /** _FILTER_H_ **/
+
diff --git a/media/libeffects/lvm/lib/Common/lib/InstAlloc.h b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
new file mode 100755
index 0000000..31409bf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/InstAlloc.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#ifndef __INSTALLOC_H__
+#define __INSTALLOC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+/*######################################################################################*/
+/* Type declarations */
+/*######################################################################################*/
+typedef struct
+{
+ LVM_UINT32 TotalSize; /* Accumulative total memory size */
+ LVM_UINT32 pNextMember; /* Pointer to the next instance member to be allocated */
+} INST_ALLOC;
+
+
+/*######################################################################################*/
+/* Function prototypes */
+/*######################################################################################*/
+
+/****************************************************************************************
+ * Name : InstAlloc_Init()
+ * Input : pms - Pointer to the INST_ALLOC instance
+ StartAddr - Base address of the instance memory
+ * Returns : Error code
+ * Description : Initializes the instance distribution and memory size calculation function
+ * Remarks :
+ ****************************************************************************************/
+
+void InstAlloc_Init( INST_ALLOC *pms, void *StartAddr );
+
+
+/****************************************************************************************
+ * Name : InstAlloc_AddMember()
+ * Input : pms - Pointer to the INST_ALLOC instance
+ Size - The size in bytes of the new added member
+ * Returns : A pointer to the new added member
+ * Description : Allocates space for a new member in the instance memory and returns
+ a pointer to this new member. The start address of all members will
+ be 32 bit alligned.
+ * Remarks :
+ ****************************************************************************************/
+
+void* InstAlloc_AddMember( INST_ALLOC *pms, LVM_UINT32 Size );
+
+/****************************************************************************************
+ * Name : InstAlloc_GetTotal()
+ * Input : pms - Pointer to the INST_ALLOC instance
+ * Returns : The instance memory size
+ * Description : This functions returns the calculated instance memory size
+ * Remarks :
+ ****************************************************************************************/
+
+LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms);
+
+void* InstAlloc_AddMemberAllRet( INST_ALLOC *pms,
+ LVM_UINT32 Size[],
+ void **ptr);
+
+void* InstAlloc_AddMemberAll( INST_ALLOC *pms,
+ LVM_UINT32 Size[],
+ LVM_MemoryTable_st *pMemoryTable);
+
+void InstAlloc_InitAll( INST_ALLOC *pms,
+ LVM_MemoryTable_st *pMemoryTable);
+
+void InstAlloc_InitAll_NULL( INST_ALLOC *pms);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __JBS_INSTALLOC_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Common.h b/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
new file mode 100755
index 0000000..f0f893d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Common.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*****************************************************************************************
+
+ $Author: nxp27078 $
+ $Revision: 672 $
+ $Date: 2010-06-08 19:39:38 +0200 (Tue, 08 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the common definitions used within the bundle and its algorithms. */
+/* */
+/* This files includes all definitions, types, structures and function prototypes. */
+/* */
+/****************************************************************************************/
+
+
+#ifndef __LVM_COMMON_H__
+#define __LVM_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVM_Types.h"
+
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+/* Algorithm identification */
+#define ALGORITHM_NONE_ID 0x0000
+#define ALGORITHM_CS_ID 0x0100
+#define ALGORITHM_EQNB_ID 0x0200
+#define ALGORITHM_DBE_ID 0x0300
+#define ALGORITHM_VC_ID 0x0500
+#define ALGORITHM_TE_ID 0x0600
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVM_COMMON_H__ */
+
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
new file mode 100755
index 0000000..8bd363d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Macros.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _LVM_MACROS_H_
+#define _LVM_MACROS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+ MUL32x32INTO32(A,B,C,ShiftR)
+ C = (A * B) >> ShiftR
+
+ A, B and C are all 32 bit SIGNED numbers and ShiftR can vary from 0 to 64
+
+ The user has to take care that C does not overflow. The result in case
+ of overflow is undefined.
+
+***********************************************************************************/
+#ifndef MUL32x32INTO32
+#define MUL32x32INTO32(A,B,C,ShiftR) \
+ {LVM_INT32 MUL32x32INTO32_temp,MUL32x32INTO32_temp2,MUL32x32INTO32_mask,MUL32x32INTO32_HH,MUL32x32INTO32_HL,MUL32x32INTO32_LH,MUL32x32INTO32_LL;\
+ LVM_INT32 shiftValue;\
+ shiftValue = (ShiftR);\
+ MUL32x32INTO32_mask=0x0000FFFF;\
+ MUL32x32INTO32_HH= ((LVM_INT32)((LVM_INT16)((A)>>16))*((LVM_INT16)((B)>>16)) );\
+ MUL32x32INTO32_HL= ((LVM_INT32)((B)&MUL32x32INTO32_mask)*((LVM_INT16)((A)>>16))) ;\
+ MUL32x32INTO32_LH= ((LVM_INT32)((A)&MUL32x32INTO32_mask)*((LVM_INT16)((B)>>16)));\
+ MUL32x32INTO32_LL= (LVM_INT32)((A)&MUL32x32INTO32_mask)*(LVM_INT32)((B)&MUL32x32INTO32_mask);\
+ MUL32x32INTO32_temp= (LVM_INT32)(MUL32x32INTO32_HL&MUL32x32INTO32_mask)+(LVM_INT32)(MUL32x32INTO32_LH&MUL32x32INTO32_mask)+(LVM_INT32)((MUL32x32INTO32_LL>>16)&MUL32x32INTO32_mask);\
+ MUL32x32INTO32_HH= MUL32x32INTO32_HH+(LVM_INT32)(MUL32x32INTO32_HL>>16)+(LVM_INT32)(MUL32x32INTO32_LH>>16)+(LVM_INT32)(MUL32x32INTO32_temp>>16);\
+ MUL32x32INTO32_LL=MUL32x32INTO32_LL+(LVM_INT32)(MUL32x32INTO32_HL<<16)+(LVM_INT32)(MUL32x32INTO32_LH<<16);\
+ if(shiftValue<32)\
+ {\
+ MUL32x32INTO32_HH=MUL32x32INTO32_HH<<(32-shiftValue);\
+ MUL32x32INTO32_mask=((LVM_INT32)1<<(32-shiftValue))-1;\
+ MUL32x32INTO32_LL=(MUL32x32INTO32_LL>>shiftValue)&MUL32x32INTO32_mask;\
+ MUL32x32INTO32_temp2=MUL32x32INTO32_HH|MUL32x32INTO32_LL;\
+ }\
+ else\
+ {\
+ MUL32x32INTO32_temp2=(LVM_INT32)MUL32x32INTO32_HH>>(shiftValue-32);\
+ }\
+ (C) = MUL32x32INTO32_temp2;\
+ }
+#endif
+
+/**********************************************************************************
+ MUL32x16INTO32(A,B,C,ShiftR)
+ C = (A * B) >> ShiftR
+
+ A and C are 32 bit SIGNED numbers. B is a 16 bit SIGNED number.
+ ShiftR can vary from 0 to 48
+
+ The user has to take care that C does not overflow. The result in case
+ of overflow is undefined.
+
+***********************************************************************************/
+#ifndef MUL32x16INTO32
+#define MUL32x16INTO32(A,B,C,ShiftR) \
+ {LVM_INT32 MUL32x16INTO32_mask,MUL32x16INTO32_HH,MUL32x16INTO32_LL;\
+ LVM_INT32 shiftValue;\
+ shiftValue = (ShiftR);\
+ MUL32x16INTO32_mask=0x0000FFFF;\
+ MUL32x16INTO32_HH= ((LVM_INT32)(B)*((LVM_INT16)((A)>>16)));\
+ MUL32x16INTO32_LL= ((LVM_INT32)((A)&MUL32x16INTO32_mask)*(B));\
+ if(shiftValue<16)\
+ {\
+ MUL32x16INTO32_HH=(LVM_INT32)((LVM_UINT32)MUL32x16INTO32_HH<<(16-shiftValue));\
+ (C)=MUL32x16INTO32_HH+(LVM_INT32)(MUL32x16INTO32_LL>>shiftValue);\
+ }\
+ else if(shiftValue<32) {\
+ MUL32x16INTO32_HH=(LVM_INT32)(MUL32x16INTO32_HH>>(shiftValue-16));\
+ (C)=MUL32x16INTO32_HH+(LVM_INT32)(MUL32x16INTO32_LL>>shiftValue);\
+ }\
+ else {\
+ (C)=MUL32x16INTO32_HH>>(shiftValue-16);}\
+ }
+#endif
+
+/**********************************************************************************
+ ADD2_SAT_32x32(A,B,C)
+ C = SAT(A + B)
+
+ A,B and C are 32 bit SIGNED numbers.
+***********************************************************************************/
+#ifndef ADD2_SAT_32x32
+#define ADD2_SAT_32x32(A,B,C) \
+ {(C)=(A)+(B);\
+ if ((((C) ^ (A)) & ((C) ^ (B))) >> 31)\
+ {\
+ if((A)<0)\
+ (C)=0x80000000l;\
+ else\
+ (C)=0x7FFFFFFFl;\
+ }\
+ }
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVM_MACROS_H_ */
+
+/*** End of file ******************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
new file mode 100755
index 0000000..22a16d6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LVM_TIMER_H__
+#define __LVM_TIMER_H__
+/************************************************************************/
+/* */
+/* Project:: My Project */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVM_Types.h"
+
+/****************************************************************************************/
+/* */
+/* Header file for the LVM_Timer library */
+/* */
+/* Functionality: */
+/* The timer will count down a number of ms, based on the number of samples it */
+/* sees and the curent sampling rate. When the timer expires, a registered */
+/* callback function will be called. */
+/* The maximal number of sampless that can be called by the timer is 2^32, which */
+/* corresponds to 24.8 hours at a sampling rate of 48 kHz */
+/* The timer currently does not suport changes in sampling rate while timing. */
+/****************************************************************************************/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/****************************************************************************************/
+/* TYPE DEFINITIONS */
+/****************************************************************************************/
+
+typedef struct
+{
+ LVM_INT32 Storage[6];
+
+} LVM_Timer_Instance_t;
+
+typedef struct
+{
+ LVM_INT32 SamplingRate;
+ LVM_INT16 TimeInMs;
+ LVM_INT32 CallBackParam;
+ void *pCallBackParams;
+ void *pCallbackInstance;
+ void (*pCallBack)(void*,void*,LVM_INT32);
+
+} LVM_Timer_Params_t;
+
+/****************************************************************************************/
+/* FUNCTION PROTOTYPES */
+/****************************************************************************************/
+
+void LVM_Timer_Init ( LVM_Timer_Instance_t *pInstance,
+ LVM_Timer_Params_t *pParams );
+
+
+void LVM_Timer ( LVM_Timer_Instance_t *pInstance,
+ LVM_INT16 BlockSize );
+
+
+/****************************************************************************************/
+/* END OF HEADER */
+/****************************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVM_TIMER_H__ */
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
new file mode 100755
index 0000000..e4649ba
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file defining the standard LifeVibes types for use in the application layer */
+/* interface of all LifeVibes modules */
+/* */
+/****************************************************************************************/
+
+#ifndef LVM_TYPES_H
+#define LVM_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* definitions */
+/* */
+/****************************************************************************************/
+
+#define LVM_NULL 0 /* NULL pointer */
+
+#define LVM_TRUE 1 /* Booleans */
+#define LVM_FALSE 0
+
+#define LVM_MAXINT_8 127 /* Maximum positive integer size */
+#define LVM_MAXINT_16 32767
+#define LVM_MAXINT_32 2147483647
+#define LVM_MAXENUM 2147483647
+
+#define LVM_MODULEID_MASK 0xFF00 /* Mask to extract the calling module ID from callbackId */
+#define LVM_EVENTID_MASK 0x00FF /* Mask to extract the callback event from callbackId */
+
+/* Memory table*/
+#define LVM_MEMREGION_PERSISTENT_SLOW_DATA 0 /* Offset to the instance memory region */
+#define LVM_MEMREGION_PERSISTENT_FAST_DATA 1 /* Offset to the persistent data memory region */
+#define LVM_MEMREGION_PERSISTENT_FAST_COEF 2 /* Offset to the persistent coefficient memory region */
+#define LVM_MEMREGION_TEMPORARY_FAST 3 /* Offset to temporary memory region */
+
+#define LVM_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+/* Memory partition type */
+#define LVM_MEM_PARTITION0 0 /* 1st memory partition */
+#define LVM_MEM_PARTITION1 1 /* 2nd memory partition */
+#define LVM_MEM_PARTITION2 2 /* 3rd memory partition */
+#define LVM_MEM_PARTITION3 3 /* 4th memory partition */
+
+/* Use type */
+#define LVM_MEM_PERSISTENT 0 /* Persistent memory type */
+#define LVM_MEM_SCRATCH 4 /* Scratch memory type */
+
+/* Access type */
+#define LVM_MEM_INTERNAL 0 /* Internal (fast) access memory */
+#define LVM_MEM_EXTERNAL 8 /* External (slow) access memory */
+
+/* Platform specific */
+#define LVM_PERSISTENT LVM_MEM_PARTITION0+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
+#define LVM_PERSISTENT_DATA LVM_MEM_PARTITION1+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
+#define LVM_PERSISTENT_COEF LVM_MEM_PARTITION2+LVM_MEM_PERSISTENT+LVM_MEM_INTERNAL
+#define LVM_SCRATCH LVM_MEM_PARTITION3+LVM_MEM_SCRATCH+LVM_MEM_INTERNAL
+
+/****************************************************************************************/
+/* */
+/* Basic types */
+/* */
+/****************************************************************************************/
+
+typedef char LVM_CHAR; /* ASCII character */
+
+typedef char LVM_INT8; /* Signed 8-bit word */
+typedef unsigned char LVM_UINT8; /* Unsigned 8-bit word */
+
+typedef short LVM_INT16; /* Signed 16-bit word */
+typedef unsigned short LVM_UINT16; /* Unsigned 16-bit word */
+
+typedef long LVM_INT32; /* Signed 32-bit word */
+typedef unsigned long LVM_UINT32; /* Unsigned 32-bit word */
+
+
+/****************************************************************************************/
+/* */
+/* Standard Enumerated types */
+/* */
+/****************************************************************************************/
+
+/* Operating mode */
+typedef enum
+{
+ LVM_MODE_OFF = 0,
+ LVM_MODE_ON = 1,
+ LVM_MODE_DUMMY = LVM_MAXENUM
+} LVM_Mode_en;
+
+
+/* Format */
+typedef enum
+{
+ LVM_STEREO = 0,
+ LVM_MONOINSTEREO = 1,
+ LVM_MONO = 2,
+ LVM_SOURCE_DUMMY = LVM_MAXENUM
+} LVM_Format_en;
+
+
+/* LVM sampling rates */
+typedef enum
+{
+ LVM_FS_8000 = 0,
+ LVM_FS_11025 = 1,
+ LVM_FS_12000 = 2,
+ LVM_FS_16000 = 3,
+ LVM_FS_22050 = 4,
+ LVM_FS_24000 = 5,
+ LVM_FS_32000 = 6,
+ LVM_FS_44100 = 7,
+ LVM_FS_48000 = 8,
+ LVM_FS_INVALID = LVM_MAXENUM-1,
+ LVM_FS_DUMMY = LVM_MAXENUM
+} LVM_Fs_en;
+
+
+/* Memory Types */
+typedef enum
+{
+ LVM_PERSISTENT_SLOW_DATA = LVM_MEMREGION_PERSISTENT_SLOW_DATA,
+ LVM_PERSISTENT_FAST_DATA = LVM_MEMREGION_PERSISTENT_FAST_DATA,
+ LVM_PERSISTENT_FAST_COEF = LVM_MEMREGION_PERSISTENT_FAST_COEF,
+ LVM_TEMPORARY_FAST = LVM_MEMREGION_TEMPORARY_FAST,
+ LVM_MEMORYTYPE_DUMMY = LVM_MAXENUM
+} LVM_MemoryTypes_en;
+
+
+/* Memory region definition */
+typedef struct
+{
+ LVM_UINT32 Size; /* Region size in bytes */
+ LVM_MemoryTypes_en Type; /* Region type */
+ void *pBaseAddress; /* Pointer to the region base address */
+} LVM_MemoryRegion_st;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVM_MemoryRegion_st Region[LVM_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVM_MemoryTable_st;
+
+
+/****************************************************************************************/
+/* */
+/* Standard Function Prototypes */
+/* */
+/****************************************************************************************/
+typedef LVM_INT32 (*LVM_Callback)(void *pCallbackData, /* Pointer to the callback data structure */
+ void *pGeneralPurpose, /* General purpose pointer (e.g. to a data structure needed in the callback) */
+ LVM_INT16 GeneralPurpose ); /* General purpose variable (e.g. to be used as callback ID) */
+
+
+/****************************************************************************************/
+/* */
+/* End of file */
+/* */
+/****************************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LVM_TYPES_H */
diff --git a/media/libeffects/lvm/lib/Common/lib/Mixer.h b/media/libeffects/lvm/lib/Common/lib/Mixer.h
new file mode 100755
index 0000000..d741980
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/Mixer.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __MIXER_H__
+#define __MIXER_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "LVM_Types.h"
+
+/**********************************************************************************
+ INSTANCE MEMORY TYPE DEFINITION
+***********************************************************************************/
+
+typedef struct
+{
+ LVM_INT32 Alpha; /* Time constant. Set by calling application. Can be changed at any time */
+ LVM_INT32 Target; /* Target value. Set by calling application. Can be changed at any time */
+ LVM_INT32 Current; /* Current value. Set by the mixer function. */
+ LVM_INT16 CallbackSet; /* Boolean. Should be set by calling application each time the target value is updated */
+ LVM_INT16 CallbackParam; /* Parameter that will be used in the calback function */
+ void *pCallbackHandle; /* Pointer to the instance of the callback function */
+ void *pGeneralPurpose; /* Pointer for general purpose usage */
+ LVM_Callback pCallBack; /* Pointer to the callback function */
+} Mix_1St_Cll_t;
+
+typedef struct
+{
+ LVM_INT32 Alpha1;
+ LVM_INT32 Target1;
+ LVM_INT32 Current1;
+ LVM_INT16 CallbackSet1;
+ LVM_INT16 CallbackParam1;
+ void *pCallbackHandle1;
+ void *pGeneralPurpose1;
+ LVM_Callback pCallBack1;
+
+ LVM_INT32 Alpha2; /* Warning the address of this location is passed as a pointer to Mix_1St_Cll_t in some functions */
+ LVM_INT32 Target2;
+ LVM_INT32 Current2;
+ LVM_INT16 CallbackSet2;
+ LVM_INT16 CallbackParam2;
+ void *pCallbackHandle2;
+ void *pGeneralPurpose2;
+ LVM_Callback pCallBack2;
+
+} Mix_2St_Cll_t;
+
+
+/*** General functions ************************************************************/
+
+LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32 tc,
+ LVM_UINT16 Fs,
+ LVM_UINT16 NumChannels);
+
+
+void MixSoft_1St_D32C31_WRA( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void MixSoft_2St_D32C31_SAT( Mix_2St_Cll_t *pInstance,
+ const LVM_INT32 *src1,
+ const LVM_INT32 *src2,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void MixInSoft_D32C31_SAT( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES (LOW LEVEL SUBFUNCTIONS)
+***********************************************************************************/
+
+void Core_MixSoft_1St_D32C31_WRA( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void Core_MixHard_2St_D32C31_SAT( Mix_2St_Cll_t *pInstance,
+ const LVM_INT32 *src1,
+ const LVM_INT32 *src2,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void Core_MixInSoft_D32C31_SAT( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/**********************************************************************************/
+
+#endif /* __MIXER_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
new file mode 100755
index 0000000..c66e201
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/ScalarArithmetic.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#ifndef __SCALARARITHMETIC_H__
+#define __SCALARARITHMETIC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*######################################################################################*/
+/* Include files */
+/*######################################################################################*/
+
+#include "LVM_Types.h"
+
+/*######################################################################################*/
+/* Extern function prototypes */
+/*######################################################################################*/
+
+/* Absolute value including the corner case for the extreme negative value */
+LVM_INT32 Abs_32(LVM_INT32 input);
+
+/****************************************************************************************
+ * Name : dB_to_Lin32()
+ * Input : Signed 16-bit integer
+ * MSB (16) = sign bit
+ * (15->05) = integer part
+ * (04->01) = decimal part
+ * Output : Signed 32-bit integer
+ * MSB (32) = sign bit
+ * (31->16) = integer part
+ * (15->01) = decimal part
+ * Returns : Lin value format 1.16.15
+ ****************************************************************************************/
+
+LVM_INT32 dB_to_Lin32(LVM_INT16 db_fix);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SCALARARITHMETIC_H__ */
+
+
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
new file mode 100755
index 0000000..290a996
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 853 $
+ $Date: 2010-06-16 15:10:28 +0200 (Wed, 16 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _VECTOR_ARITHMETIC_H_
+#define _VECTOR_ARITHMETIC_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+
+/**********************************************************************************
+ VARIOUS FUNCTIONS
+***********************************************************************************/
+
+void LoadConst_16( const LVM_INT16 val,
+ LVM_INT16 *dst,
+ LVM_INT16 n );
+
+void LoadConst_32( const LVM_INT32 val,
+ LVM_INT32 *dst,
+ LVM_INT16 n );
+
+void Copy_16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n );
+
+/*********************************************************************************
+ * note: In Mult3s_16x16() saturation of result is not taken care when *
+ * overflow occurs. *
+ * For example when *src = 0x8000, val = *0x8000 *
+ * The function gives the output as 0x8000 instead of 0x7fff *
+ * This is the only case which will give wrong result. *
+ * For more information refer to Vector_Arithmetic.doc in /doc folder *
+ *********************************************************************************/
+void Mult3s_16x16( const LVM_INT16 *src,
+ const LVM_INT16 val,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+/*********************************************************************************
+ * note: In Mult3s_32x16() saturation of result is not taken care when *
+ * overflow occurs. *
+ * For example when *src = 0x8000000, val = *0x8000 *
+ * The function gives the output as 0x8000000 instead of 0x7fffffff *
+ * This is the only extreme condition which is giving unexpected result *
+ * For more information refer to Vector_Arithmetic.doc in /doc folder *
+ *********************************************************************************/
+void Mult3s_32x16( const LVM_INT32 *src,
+ const LVM_INT16 val,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void DelayMix_16x16( const LVM_INT16 *src,
+ LVM_INT16 *delay,
+ LVM_INT16 size,
+ LVM_INT16 *dst,
+ LVM_INT16 *pOffset,
+ LVM_INT16 n);
+
+void DelayWrite_32( const LVM_INT32 *src, /* Source 1, to be delayed */
+ LVM_INT32 *delay, /* Delay buffer */
+ LVM_UINT16 size, /* Delay size */
+ LVM_UINT16 *pOffset, /* Delay offset */
+ LVM_INT16 n);
+
+void Add2_Sat_16x16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n );
+
+void Add2_Sat_32x32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n );
+
+void Mac3s_Sat_16x16( const LVM_INT16 *src,
+ const LVM_INT16 val,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void Mac3s_Sat_32x16( const LVM_INT32 *src,
+ const LVM_INT16 val,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void DelayAllPass_Sat_32x16To32( LVM_INT32 *delay, /* Delay buffer */
+ LVM_UINT16 size, /* Delay size */
+ LVM_INT16 coeff, /* All pass filter coefficient */
+ LVM_UINT16 DelayOffset, /* Simple delay offset */
+ LVM_UINT16 *pAllPassOffset, /* All pass filter delay offset */
+ LVM_INT32 *dst, /* Source/destination */
+ LVM_INT16 n);
+
+/**********************************************************************************
+ SHIFT FUNCTIONS
+***********************************************************************************/
+
+void Shift_Sat_v16xv16 ( const LVM_INT16 val,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void Shift_Sat_v32xv32 ( const LVM_INT16 val,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+/**********************************************************************************
+ AUDIO FORMAT CONVERSION FUNCTIONS
+***********************************************************************************/
+
+void MonoTo2I_16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void MonoTo2I_32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void From2iToMono_32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void MSTo2i_Sat_16x16( const LVM_INT16 *srcM,
+ const LVM_INT16 *srcS,
+ LVM_INT16 *dst,
+ LVM_INT16 n );
+
+void From2iToMS_16x16( const LVM_INT16 *src,
+ LVM_INT16 *dstM,
+ LVM_INT16 *dstS,
+ LVM_INT16 n );
+
+void From2iToMono_16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void JoinTo2i_32x32( const LVM_INT32 *srcL,
+ const LVM_INT32 *srcR,
+ LVM_INT32 *dst,
+ LVM_INT16 n );
+
+/**********************************************************************************
+ DATA TYPE CONVERSION FUNCTIONS
+***********************************************************************************/
+
+void Int16LShiftToInt32_16x32(const LVM_INT16 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n,
+ LVM_INT16 shift );
+
+void Int32RShiftToInt16_Sat_32x16(const LVM_INT32 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n,
+ LVM_INT16 shift );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+/**********************************************************************************/
+
+#endif /* _VECTOR_ARITHMETIC_H_ */
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
new file mode 100755
index 0000000..40e0dbf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1070 $
+ $Date: 2010-07-02 11:22:18 +0200 (Fri, 02 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "AGC.h"
+#include "ScalarArithmetic.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+
+#define VOL_TC_SHIFT 21 /* As a power of 2 */
+#define DECAY_SHIFT 10 /* As a power of 2 */
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: AGC_MIX_VOL_2St1Mon_D32_WRA */
+/* */
+/* DESCRIPTION: */
+/* Apply AGC and mix signals */
+/* */
+/* */
+/* StSrc ------------------| */
+/* | */
+/* ______ _|_ ________ */
+/* | | | | | | */
+/* MonoSrc -->| AGC |---->| + |----->| Volume |------------------------------+---> */
+/* | Gain | |___| | Gain | | */
+/* |______| |________| | */
+/* /|\ __________ ________ | */
+/* | | | | | | */
+/* |-------------------------------| AGC Gain |<--| Peak |<--| */
+/* | Update | | Detect | */
+/* |__________| |________| */
+/* */
+/* */
+/* PARAMETERS: */
+/* pInstance Instance pointer */
+/* pStereoIn Stereo source */
+/* pMonoIn Mono band pass source */
+/* pStereoOut Stereo destination */
+/* */
+/* RETURNS: */
+/* Void */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t *pInstance, /* Instance pointer */
+ const LVM_INT32 *pStSrc, /* Stereo source */
+ const LVM_INT32 *pMonoSrc, /* Mono source */
+ LVM_INT32 *pDst, /* Stereo destination */
+ LVM_UINT16 NumSamples) /* Number of samples */
+{
+
+ /*
+ * General variables
+ */
+ LVM_UINT16 i; /* Sample index */
+ LVM_INT32 Left; /* Left sample */
+ LVM_INT32 Right; /* Right sample */
+ LVM_INT32 Mono; /* Mono sample */
+ LVM_INT32 AbsPeak; /* Absolute peak signal */
+ LVM_INT32 HighWord; /* High word in intermediate calculations */
+ LVM_INT32 LowWord; /* Low word in intermediate calculations */
+ LVM_INT16 AGC_Mult; /* Short AGC gain */
+ LVM_INT16 Vol_Mult; /* Short volume */
+
+
+ /*
+ * Instance control variables
+ */
+ LVM_INT32 AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */
+ LVM_INT32 AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */
+ LVM_INT16 AGC_GainShift = pInstance->AGC_GainShift; /* Get the AGC shift */
+ LVM_INT16 AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */
+ LVM_INT16 AGC_Decay = pInstance->AGC_Decay; /* Decay scaler */
+ LVM_INT32 AGC_Target = pInstance->AGC_Target; /* Get the target level */
+ LVM_INT32 Vol_Current = pInstance->Volume; /* Actual volume setting */
+ LVM_INT32 Vol_Target = pInstance->Target; /* Target volume setting */
+ LVM_INT16 Vol_Shift = pInstance->VolumeShift; /* Volume shift scaling */
+ LVM_INT16 Vol_TC = pInstance->VolumeTC; /* Time constant */
+
+
+ /*
+ * Process on a sample by sample basis
+ */
+ for (i=0;i<NumSamples;i++) /* For each sample */
+ {
+
+ /*
+ * Get the short scalers
+ */
+ AGC_Mult = (LVM_INT16)(AGC_Gain >> 16); /* Get the short AGC gain */
+ Vol_Mult = (LVM_INT16)(Vol_Current >> 16); /* Get the short volume gain */
+
+
+ /*
+ * Get the input samples
+ */
+ Left = *pStSrc++; /* Get the left sample */
+ Right = *pStSrc++; /* Get the right sample */
+ Mono = *pMonoSrc++; /* Get the mono sample */
+
+
+ /*
+ * Apply the AGC gain to the mono input and mix with the stereo signal
+ */
+ HighWord = (AGC_Mult * (Mono >> 16)); /* signed long (Mono) by unsigned short (AGC_Mult) multiply */
+ LowWord = (AGC_Mult * (Mono & 0xffff));
+ Mono = (HighWord + (LowWord >> 16)) << (AGC_GainShift);
+ Left += Mono; /* Mix in the mono signal */
+ Right += Mono;
+
+
+ /*
+ * Apply the volume and write to the output stream
+ */
+ HighWord = (Vol_Mult * (Left >> 16)); /* signed long (Left) by unsigned short (Vol_Mult) multiply */
+ LowWord = (Vol_Mult * (Left & 0xffff));
+ Left = (HighWord + (LowWord >> 16)) << (Vol_Shift);
+ HighWord = (Vol_Mult * (Right >> 16)); /* signed long (Right) by unsigned short (Vol_Mult) multiply */
+ LowWord = (Vol_Mult * (Right & 0xffff));
+ Right = (HighWord + (LowWord >> 16)) << (Vol_Shift);
+ *pDst++ = Left; /* Save the results */
+ *pDst++ = Right;
+
+
+ /*
+ * Update the AGC gain
+ */
+ AbsPeak = (Abs_32(Left)>Abs_32(Right)) ? Abs_32(Left) : Abs_32(Right); /* Get the absolute peak */
+ if (AbsPeak > AGC_Target)
+ {
+ /*
+ * The signal is too large so decrease the gain
+ */
+ HighWord = (AGC_Attack * (AGC_Gain >> 16)); /* signed long (AGC_Gain) by unsigned short (AGC_Attack) multiply */
+ LowWord = (AGC_Attack * (AGC_Gain & 0xffff));
+ AGC_Gain = (HighWord + (LowWord >> 16)) << 1;
+ }
+ else
+ {
+ /*
+ * The signal is too small so increase the gain
+ */
+ if (AGC_Gain > AGC_MaxGain)
+ {
+ AGC_Gain -= (AGC_Decay << DECAY_SHIFT);
+ }
+ else
+ {
+ AGC_Gain += (AGC_Decay << DECAY_SHIFT);
+ }
+ }
+
+ /*
+ * Update the gain
+ */
+ Vol_Current += Vol_TC * ((Vol_Target - Vol_Current) >> VOL_TC_SHIFT);
+ }
+
+
+ /*
+ * Update the parameters
+ */
+ pInstance->Volume = Vol_Current; /* Actual volume setting */
+ pInstance->AGC_Gain = AGC_Gain;
+
+ return;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/Abs_32.c b/media/libeffects/lvm/lib/Common/src/Abs_32.c
new file mode 100755
index 0000000..635315d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Abs_32.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/*######################################################################################*/
+/* Include files */
+/*######################################################################################*/
+
+#include "ScalarArithmetic.h"
+
+/****************************************************************************************
+ * Name : Abs_32()
+ * Input : Signed 32-bit integer
+ * Output :
+ * Returns : Absolute value
+ * Description : Absolute value with maximum negative value corner case
+ * Remarks :
+ ****************************************************************************************/
+
+LVM_INT32 Abs_32(LVM_INT32 input)
+{
+ if(input < 0)
+ {
+ if (input == (LVM_INT32)(0x80000000U))
+ {
+ /* The corner case, so set to the maximum positive value */
+ input=(LVM_INT32) 0x7fffffff;
+ }
+ else
+ {
+ /* Negative input, so invert */
+ input = (LVM_INT32)(-input);
+ }
+ }
+ return input;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c
new file mode 100755
index 0000000..18026c5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_16x16.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION ADD2_SAT_16X16
+***********************************************************************************/
+
+void Add2_Sat_16x16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT32 Temp;
+ LVM_INT16 ii;
+ for (ii = n; ii != 0; ii--)
+ {
+ Temp = ((LVM_INT32) *src) + ((LVM_INT32) *dst);
+ src++;
+
+ if (Temp > 0x00007FFF)
+ {
+ *dst = 0x7FFF;
+ }
+ else if (Temp < -0x00008000)
+ {
+ *dst = - 0x8000;
+ }
+ else
+ {
+ *dst = (LVM_INT16)Temp;
+ }
+ dst++;
+ }
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
new file mode 100755
index 0000000..96fc7e6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+
+/**********************************************************************************
+ FUNCTION ADD2_SAT_32X32
+***********************************************************************************/
+
+void Add2_Sat_32x32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT32 a,b,c;
+ LVM_INT16 ii;
+ for (ii = n; ii != 0; ii--)
+ {
+ a=*src;
+ src++;
+
+ b=*dst;
+ c=a+b;
+ if ((((c ^ a) & (c ^ b)) >> 31)!=0) /* overflow / underflow */
+ {
+ if(a<0)
+ {
+ c=0x80000000l;
+ }
+ else
+ {
+ c=0x7FFFFFFFl;
+ }
+ }
+
+ *dst = c;
+ dst++;
+ }
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
new file mode 100755
index 0000000..76d8e42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16C14_TRC_WRA_01.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+
+void BP_1I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+
+
+ {
+ LVM_INT32 ynL;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL= (A0 (Q14) * (x(n)L (Q0) - x(n-2)L (Q0) ) ) in Q14
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* ((*pDataIn)-pBiquadState->pDelays[1]);
+
+ // ynL+= ((-B2 (Q14) * y(n-2)L (Q0) ) ) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[3];
+
+ // ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) ) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]*pBiquadState->pDelays[2];
+
+ ynL=(LVM_INT16)(ynL>>14); // ynL in Q0
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..9338eb2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BP_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BP_1I_D16F16Css_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D16F16Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BP_C16_Coefs_t *pCoef)
+{
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps;
+
+ pBiquadState->coefs[0]=pCoef->A0;
+ pBiquadState->coefs[1]=pCoef->B2;
+ pBiquadState->coefs[2]=pCoef->B1;
+ }
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D16F16Css_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..2a0d7d5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BP_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
new file mode 100755
index 0000000..f52d3db
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32C30_TRC_WRA_01.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q16 format
+***************************************************************************/
+
+void BP_1I_D16F32C30_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+
+
+ {
+ LVM_INT32 ynL,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>14) in Q16
+ templ= (LVM_INT32) *pDataIn-pBiquadState->pDelays[1];
+ MUL32x32INTO32(pBiquadState->coefs[0],templ,ynL,14)
+
+ // ynL+= ((-B2 (Q30) * y(n-2)L (Q16) ) >>30) in Q16
+ MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[3],templ,30)
+ ynL+=templ;
+
+ // ynL+= ((-B1 (Q30) * y(n-1)L (Q16) ) >>30) in Q16
+ MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[2],templ,30)
+ ynL+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q16
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)(ynL>>16); // Write Left output in Q0
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..c560085
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Init.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BP_1I_D16F32Cll_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BP_1I_D16F32Cll_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a Band pass filter (BIQUAD) */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* */
+/* The coefficients are modified in the init() function such that lower */
+/* half word is right shifted by one and most significant bit of the lower */
+/* word is made to be zero. */
+/* */
+/* Reason: For MIPS effciency,we are using DSP 32*16 multiplication */
+/* instruction. But we have 32*32 multiplication. This can be realized by two 32*16 */
+/* multiplication. But 16th bit in the 32 bit word is not a sign bit. So this is done */
+/* by putting 16th bit to zero and lossing one bit precision by division of lower */
+/* half word by 2. */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D16F32Cll_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BP_C32_Coefs_t *pCoef)
+{
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps;
+
+ pBiquadState->coefs[0] = pCoef->A0;
+ pBiquadState->coefs[1] = pCoef->B2;
+ pBiquadState->coefs[2] = pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D16F32Cll_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..76777f6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D16F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
+#define _BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BP_1I_D16F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
new file mode 100755
index 0000000..2b3555f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32C30_TRC_WRA_02.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+
+void BP_1I_D32F32C30_TRC_WRA_02 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>30) in Q0
+ templ=(*pDataIn)-pBiquadState->pDelays[1];
+ MUL32x32INTO32(pBiquadState->coefs[0],templ,ynL,30)
+
+ // ynL+= ((-B2 (Q30) * y(n-2)L (Q0) ) >>30) in Q0
+ MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[3],templ,30)
+ ynL+=templ;
+
+ // ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) >>30) in Q0
+ MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[2],templ,30)
+ ynL+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=ynL; // Write Left output in Q0
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
new file mode 100755
index 0000000..f3f4571
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Init.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BP_1I_D32F32Cll_TRC_WRA_02_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BP_1I_D32F32Cll_TRC_WRA_02_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BP_1I_D32F32Cll_TRC_WRA_02_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BP_C32_Coefs_t *pCoef)
+{
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps;
+
+ pBiquadState->coefs[0]=pCoef->A0;
+
+ pBiquadState->coefs[1]=pCoef->B2;
+
+ pBiquadState->coefs[2]=pCoef->B1;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BP_1I_D32F32Cll_TRC_WRA_02_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
new file mode 100755
index 0000000..8884537
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BP_1I_D32F32Cll_TRC_WRA_02_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
+#define _BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BP_1I_D32F32CLL_TRC_WRA_02_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
new file mode 100755
index 0000000..00e3b52
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q0 format
+***************************************************************************/
+
+void BQ_1I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL=A2 (Q15) * x(n-2)L (Q0) in Q15
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[1];
+
+ // ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ // ynL+= (-B2 (Q15) * y(n-2)L (Q0) ) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[3];
+
+ // ynL+= (-B1 (Q15) * y(n-1)L (Q0) ) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[2];
+
+ ynL=ynL>>15; // ynL in Q0 format
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[2]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..3fedc45
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BQ_1I_D16F16Css_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BQ_1I_D16F16Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef)
+{
+ LVM_INT16 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps ;
+
+ temp=pCoef->A2;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A1;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[2]=temp;
+ temp=pCoef->B2;
+ pBiquadState->coefs[3]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_1I_D16F16Css_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..18dacd3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BQ_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
new file mode 100755
index 0000000..cdff1d9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32C14_TRC_WRA_01.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[2] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[3] is y(n-2)L in Q16 format
+***************************************************************************/
+
+void BQ_1I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL=A2 (Q14) * x(n-2)L (Q0) in Q14
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[1];
+
+ // ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ // ynL+=A0 (Q14) * x(n)L (Q0) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ // ynL+= ( (-B2 (Q14) * y(n-2)L (Q16) )>>16) in Q14
+ MUL32x16INTO32(pBiquadState->pDelays[3],pBiquadState->coefs[3],templ,16)
+ ynL+=templ;
+
+ // ynL+= ( (-B1 (Q14) * y(n-1)L (Q16) )>>16) in Q14
+ MUL32x16INTO32(pBiquadState->pDelays[2],pBiquadState->coefs[4],templ,16)
+ ynL+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[2]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[1]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[2]=ynL<<2; // Update y(n-1)L in Q16
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)(ynL>>14); // Write Left output in Q0
+
+ }
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..bc88847
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_Private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /*_BQ_1I_D16F32CSS_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
new file mode 100755
index 0000000..520c969
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_1I_D16F32Css_TRC_WRA_01_init.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_1I_D16F32Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BQ_1I_D16F32Css_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BQ_1I_D16F32Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef)
+{
+ LVM_INT16 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps ;
+
+ temp=pCoef->A2;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A1;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[2]=temp;
+ temp=pCoef->B2;
+ pBiquadState->coefs[3]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_1I_D16F32Css_TRC_WRA_01_Init */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
new file mode 100755
index 0000000..c267a90
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C14_TRC_WRA_01.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+
+void BQ_2I_D16F16C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL=A2 (Q14) * x(n-2)L (Q0) in Q14
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+ // ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ // ynL+=A0 (Q14) * x(n)L (Q0) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ // ynL+= ( -B2 (Q14) * y(n-2)L (Q0) ) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[6];
+
+ // ynL+=( -B1 (Q14) * y(n-1)L (Q0) ) in Q14
+ ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[4];
+
+ ynL=ynL>>14; // ynL in Q0 format
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ // ynR=A2 (Q14) * x(n-2)R (Q0) in Q14
+ ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+ // ynR+=A1 (Q14) * x(n-1)R (Q0) in Q14
+ ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+ // ynR+=A0 (Q14) * x(n)R (Q0) in Q14
+ ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+ // ynR+= ( -B2 (Q14) * y(n-2)R (Q0) ) in Q14
+ ynR+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[7];
+
+ // ynR+=( -B1 (Q14) * y(n-1)R (Q0) ) in Q14
+ ynR+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[5];
+
+ ynR=ynR>>14; // ynL in Q0 format
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; // y(n-2)R=y(n-1)R
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; // x(n-2)R=x(n-1)R
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[5]=ynR; // Update y(n-1)R in Q0
+ pBiquadState->pDelays[4]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+ pBiquadState->pDelays[1]=(*pDataIn++); // Update x(n-1)R in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+ *pDataOut++=(LVM_INT16)ynR; // Write Right ouput in Q0
+
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
new file mode 100755
index 0000000..ded2bb3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+
+void BQ_2I_D16F16C15_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL=A2 (Q15) * x(n-2)L (Q0) in Q15
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+ // ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ // ynL+= ( -B2 (Q15) * y(n-2)L (Q0) ) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[6];
+
+ // ynL+=( -B1 (Q15) * y(n-1)L (Q0) ) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[4];
+
+ ynL=ynL>>15; // ynL in Q0 format
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ // ynR=A2 (Q15) * x(n-2)R (Q0) in Q15
+ ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+ // ynR+=A1 (Q15) * x(n-1)R (Q0) in Q15
+ ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+ // ynR+=A0 (Q15) * x(n)R (Q0) in Q15
+ ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+ // ynR+= ( -B2 (Q15) * y(n-2)R (Q0) ) in Q15
+ ynR+=(LVM_INT32)pBiquadState->coefs[3]*pBiquadState->pDelays[7];
+
+ // ynR+=( -B1 (Q15) * y(n-1)R (Q0) ) in Q15
+ ynR+=(LVM_INT32)pBiquadState->coefs[4]*pBiquadState->pDelays[5];
+
+ ynR=ynR>>15; // ynL in Q0 format
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; // y(n-2)R=y(n-1)R
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; // y(n-2)L=y(n-1)L
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; // x(n-2)R=x(n-1)R
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; // x(n-2)L=x(n-1)L
+ pBiquadState->pDelays[5]=ynR; // Update y(n-1)R in Q0
+ pBiquadState->pDelays[4]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+ pBiquadState->pDelays[1]=(*pDataIn++); // Update x(n-1)R in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+ *pDataOut++=(LVM_INT16)ynR; // Write Right ouput in Q0
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..b0cd1b9
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_2I_D16F16Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BQ_2I_D16F16Css_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D16F16Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef)
+{
+ LVM_INT16 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps ;
+
+ temp=pCoef->A2;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A1;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[2]=temp;
+ temp=pCoef->B2;
+ pBiquadState->coefs[3]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D16F16Css_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..bcb0093
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _BQ_2I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
new file mode 100755
index 0000000..ae743f2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C13_TRC_WRA_01.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q13 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+
+void BQ_2I_D16F32C13_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ /* ynL=A2 (Q13) * x(n-2)L (Q0) in Q13*/
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+ /* ynL+=A1 (Q13) * x(n-1)L (Q0) in Q13*/
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ /* ynL+=A0 (Q13) * x(n)L (Q0) in Q13*/
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ /* ynL+= ( (-B2 (Q13) * y(n-2)L (Q16) )>>16) in Q13 */
+ MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
+ ynL+=templ;
+
+ /* ynL+=( (-B1 (Q13) * y(n-1)L (Q16) )>>16) in Q13 */
+ MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
+ ynL+=templ;
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ /* ynR=A2 (Q13) * x(n-2)R (Q0) in Q13*/
+ ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+ /* ynR+=A1 (Q13) * x(n-1)R (Q0) in Q13*/
+ ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+ /* ynR+=A0 (Q13) * x(n)R (Q0) in Q13*/
+ ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+ /* ynR+= ( (-B2 (Q13) * y(n-2)R (Q16) )>>16) in Q13*/
+ MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
+ ynR+=templ;
+
+ /* ynR+=( (-B1 (Q13) * y(n-1)R (Q16) )>>16) in Q13 */
+ MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
+ ynR+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+ pBiquadState->pDelays[5]=ynR<<3; /* Update y(n-1)R in Q16*/
+ pBiquadState->pDelays[4]=ynL<<3; /* Update y(n-1)L in Q16*/
+ pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+ pDataIn++;
+ pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut=(LVM_INT16)(ynL>>13); /* Write Left output in Q0*/
+ pDataOut++;
+ *pDataOut=(LVM_INT16)(ynR>>13); /* Write Right ouput in Q0*/
+ pDataOut++;
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
new file mode 100755
index 0000000..a0ca2cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C14_TRC_WRA_01.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q14 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+
+void BQ_2I_D16F32C14_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ /* ynL=A2 (Q14) * x(n-2)L (Q0) in Q14*/
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+ /* ynL+=A1 (Q14) * x(n-1)L (Q0) in Q14*/
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ /* ynL+=A0 (Q14) * x(n)L (Q0) in Q14*/
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ /* ynL+= ( (-B2 (Q14) * y(n-2)L (Q16) )>>16) in Q14 */
+ MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
+ ynL+=templ;
+
+ /* ynL+=( (-B1 (Q14) * y(n-1)L (Q16) )>>16) in Q14 */
+ MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
+ ynL+=templ;
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ /* ynR=A2 (Q14) * x(n-2)R (Q0) in Q14*/
+ ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+ /* ynR+=A1 (Q14) * x(n-1)R (Q0) in Q14*/
+ ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+ /* ynR+=A0 (Q14) * x(n)R (Q0) in Q14*/
+ ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+ /* ynR+= ( (-B2 (Q14) * y(n-2)R (Q16) )>>16) in Q14*/
+ MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
+ ynR+=templ;
+
+ /* ynR+=( (-B1 (Q14) * y(n-1)R (Q16) )>>16) in Q14 */
+ MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
+ ynR+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+ pBiquadState->pDelays[5]=ynR<<2; /* Update y(n-1)R in Q16*/
+ pBiquadState->pDelays[4]=ynL<<2; /* Update y(n-1)L in Q16*/
+ pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+ pDataIn++;
+ pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut=(LVM_INT16)(ynL>>14); /* Write Left output in Q0*/
+ pDataOut++;
+ *pDataOut=(LVM_INT16)(ynR>>14); /* Write Right ouput in Q0*/
+ pDataOut++;
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
new file mode 100755
index 0000000..f1ab815
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32C15_TRC_WRA_01.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q16 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q16 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q16 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q16 format
+***************************************************************************/
+
+void BQ_2I_D16F32C15_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ /* ynL=A2 (Q15) * x(n-2)L (Q0) in Q15*/
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+ /* ynL+=A1 (Q15) * x(n-1)L (Q0) in Q15*/
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* pBiquadState->pDelays[0];
+
+ /* ynL+=A0 (Q15) * x(n)L (Q0) in Q15*/
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]* (*pDataIn);
+
+ /* ynL+= ( (-B2 (Q15) * y(n-2)L (Q16) )>>16) in Q15 */
+ MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[3],templ,16)
+ ynL+=templ;
+
+ /* ynL+=( (-B1 (Q15) * y(n-1)L (Q16) )>>16) in Q15 */
+ MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[4],templ,16)
+ ynL+=templ;
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ /* ynR=A2 (Q15) * x(n-2)R (Q0) in Q15*/
+ ynR=(LVM_INT32)pBiquadState->coefs[0]*pBiquadState->pDelays[3];
+
+ /* ynR+=A1 (Q15) * x(n-1)R (Q0) in Q15*/
+ ynR+=(LVM_INT32)pBiquadState->coefs[1]*pBiquadState->pDelays[1];
+
+ /* ynR+=A0 (Q15) * x(n)R (Q0) in Q15*/
+ ynR+=(LVM_INT32)pBiquadState->coefs[2]*(*(pDataIn+1));
+
+ /* ynR+= ( (-B2 (Q15) * y(n-2)R (Q16) )>>16) in Q15 */
+ MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[3],templ,16)
+ ynR+=templ;
+
+ /* ynR+=( (-B1 (Q15) * y(n-1)R (Q16) )>>16) in Q15 */
+ MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[4],templ,16)
+ ynR+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+ pBiquadState->pDelays[5]=ynR<<1; /* Update y(n-1)R in Q16*/
+ pBiquadState->pDelays[4]=ynL<<1; /* Update y(n-1)L in Q16*/
+ pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+ pDataIn++;
+ pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut=(LVM_INT16)(ynL>>15); /* Write Left output in Q0*/
+ pDataOut++;
+ *pDataOut=(LVM_INT16)(ynR>>15); /* Write Right ouput in Q0*/
+ pDataOut++;
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..3cbb58b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+#define _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT16 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _BQ_2I_D16F32CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
new file mode 100755
index 0000000..0c6b33e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D16F32Css_TRC_WRA_01_init.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "BIQUAD.h"
+#include "BQ_2I_D16F32Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BQ_2I_D16F32Css_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D16F32Css_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ BQ_C16_Coefs_t *pCoef)
+{
+ LVM_INT16 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps ;
+
+ temp=pCoef->A2;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A1;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[2]=temp;
+ temp=pCoef->B2;
+ pBiquadState->coefs[3]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D16F32Css_TRC_WRA_01_Init */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
new file mode 100755
index 0000000..51278cf
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1, these are in Q30 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+
+void BQ_2I_D32F32C30_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples)
+
+
+ {
+ LVM_INT32 ynL,ynR,templ,tempd;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ /* ynL= ( A2 (Q30) * x(n-2)L (Q0) ) >>30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[2],ynL,30)
+
+ /* ynL+= ( A1 (Q30) * x(n-1)L (Q0) ) >> 30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[0],templ,30)
+ ynL+=templ;
+
+ /* ynL+= ( A0 (Q30) * x(n)L (Q0) ) >> 30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[2],*pDataIn,templ,30)
+ ynL+=templ;
+
+ /* ynL+= (-B2 (Q30) * y(n-2)L (Q0) ) >> 30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[3],pBiquadState->pDelays[6],templ,30)
+ ynL+=templ;
+
+ /* ynL+= (-B1 (Q30) * y(n-1)L (Q0) ) >> 30 in Q0 */
+ MUL32x32INTO32(pBiquadState->coefs[4],pBiquadState->pDelays[4],templ,30)
+ ynL+=templ;
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ /* ynR= ( A2 (Q30) * x(n-2)R (Q0) ) >> 30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[3],ynR,30)
+
+ /* ynR+= ( A1 (Q30) * x(n-1)R (Q0) ) >> 30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[1],pBiquadState->pDelays[1],templ,30)
+ ynR+=templ;
+
+ /* ynR+= ( A0 (Q30) * x(n)R (Q0) ) >> 30 in Q0*/
+ tempd=*(pDataIn+1);
+ MUL32x32INTO32(pBiquadState->coefs[2],tempd,templ,30)
+ ynR+=templ;
+
+ /* ynR+= (-B2 (Q30) * y(n-2)R (Q0) ) >> 30 in Q0*/
+ MUL32x32INTO32(pBiquadState->coefs[3],pBiquadState->pDelays[7],templ,30)
+ ynR+=templ;
+
+ /* ynR+= (-B1 (Q30) * y(n-1)R (Q0) ) >> 30 in Q0 */
+ MUL32x32INTO32(pBiquadState->coefs[4],pBiquadState->pDelays[5],templ,30)
+ ynR+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+ pBiquadState->pDelays[5]=(LVM_INT32)ynR; /* Update y(n-1)R in Q0*/
+ pBiquadState->pDelays[4]=(LVM_INT32)ynL; /* Update y(n-1)L in Q0*/
+ pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+ pDataIn++;
+ pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut=(LVM_INT32)ynL; /* Write Left output in Q0*/
+ pDataOut++;
+ *pDataOut=(LVM_INT32)ynR; /* Write Right ouput in Q0*/
+ pDataOut++;
+
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..7c460d3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Init.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "BQ_2I_D32F32Cll_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* BQ_2I_D32F32Cll_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void BQ_2I_D32F32Cll_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ BQ_C32_Coefs_t *pCoef)
+{
+ LVM_INT32 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps ;
+
+ temp=pCoef->A2;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A1;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[2]=temp;
+ temp=pCoef->B2;
+ pBiquadState->coefs[3]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[4]=temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: BQ_2I_D32F32C32_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..fb4f2dd
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+#define _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _BQ_2I_D32F32CLL_TRC_WRA_01_PRIVATE_H_*/
diff --git a/media/libeffects/lvm/lib/Common/src/CompLim_private.h b/media/libeffects/lvm/lib/Common/src/CompLim_private.h
new file mode 100755
index 0000000..07a8833
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/CompLim_private.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef _COMP_LIM_PRIVATE_
+#define _COMP_LIM_PRIVATE_
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "CompLim.h"
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+#define FS_48K 48000
+
+#define INTEGER_16 0xFFFF /* 65535*/
+#define INTEGER_15 0x7FFF /* 32767*/
+
+#define GAIN_6DB 1
+#define GAIN_12DB 2
+#define GAIN_18DB 3
+#define GAIN_24DB 4
+
+#endif /* #ifndef _COMP_LIM_PRIVATE_ */
+
+/*** End of file ******************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.c b/media/libeffects/lvm/lib/Common/src/Copy_16.c
new file mode 100755
index 0000000..6ee1ff6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION COPY_16
+***********************************************************************************/
+
+void Copy_16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT16 ii;
+
+ if (src > dst)
+ {
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = *src;
+ dst++;
+ src++;
+ }
+ }
+ else
+ {
+ src += n - 1;
+ dst += n - 1;
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = *src;
+ dst--;
+ src--;
+ }
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
new file mode 100755
index 0000000..adac24f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixHard_2St_D32C31_SAT.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION CORE_MIXHARD_2ST_D32C31_SAT
+***********************************************************************************/
+
+void Core_MixHard_2St_D32C31_SAT( Mix_2St_Cll_t *pInstance,
+ const LVM_INT32 *src1,
+ const LVM_INT32 *src2,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 Temp1,Temp2,Temp3;
+ LVM_INT16 ii;
+ LVM_INT16 Current1Short;
+ LVM_INT16 Current2Short;
+
+ Current1Short = (LVM_INT16)(pInstance->Current1 >> 16);
+ Current2Short = (LVM_INT16)(pInstance->Current2 >> 16);
+
+ for (ii = n; ii != 0; ii--){
+ Temp1=*src1++;
+ MUL32x16INTO32(Temp1,Current1Short,Temp3,15)
+ Temp2=*src2++;
+ MUL32x16INTO32(Temp2,Current2Short,Temp1,15)
+ Temp2=(Temp1>>1)+(Temp3>>1);
+ if (Temp2 > 0x3FFFFFFF)
+ Temp2 = 0x7FFFFFFF;
+ else if (Temp2 < - 0x40000000)
+ Temp2 = 0x80000000;
+ else
+ Temp2=(Temp2<<1);
+ *dst++ = Temp2;
+ }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
new file mode 100755
index 0000000..d557f6e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixInSoft_D32C31_SAT.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void Core_MixInSoft_D32C31_SAT( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 Temp1,Temp2,Temp3;
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT32 TargetTimesOneMinAlpha;
+ LVM_INT32 CurrentTimesAlpha;
+ LVM_INT16 ii,jj;
+ LVM_INT16 CurrentShort;
+
+ InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+ OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+ MUL32x32INTO32((0x7FFFFFFF-pInstance->Alpha),pInstance->Target,TargetTimesOneMinAlpha,31); /* Q31 * Q0 in Q0 */
+ if (pInstance->Target >= pInstance->Current){
+ TargetTimesOneMinAlpha +=2; /* Ceil*/
+ }
+
+ if (OutLoop){
+ MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31); /* Q0 * Q31 in Q0 */
+ pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha; /* Q0 + Q0 into Q0*/
+ CurrentShort = (LVM_INT16)(pInstance->Current>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop; ii != 0; ii--){
+ Temp1=*src++;
+ Temp2=*dst;
+ MUL32x16INTO32(Temp1,CurrentShort,Temp3,15)
+ Temp1=(Temp2>>1)+(Temp3>>1);
+
+ if (Temp1 > 0x3FFFFFFF)
+ Temp1 = 0x7FFFFFFF;
+ else if (Temp1 < - 0x40000000)
+ Temp1 = 0x80000000;
+ else
+ Temp1=(Temp1<<1);
+ *dst++ = Temp1;
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--){
+ MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31); /* Q0 * Q31 in Q0 */
+ pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha; /* Q0 + Q0 into Q0*/
+ CurrentShort = (LVM_INT16)(pInstance->Current>>16); /* From Q31 to Q15*/
+
+ for (jj = 4; jj!=0 ; jj--){
+ Temp1=*src++;
+ Temp2=*dst;
+ MUL32x16INTO32(Temp1,CurrentShort,Temp3,15)
+ Temp1=(Temp2>>1)+(Temp3>>1);
+
+ if (Temp1 > 0x3FFFFFFF)
+ Temp1 = 0x7FFFFFFF;
+ else if (Temp1 < - 0x40000000)
+ Temp1 = 0x80000000;
+ else
+ Temp1=(Temp1<<1);
+ *dst++ = Temp1;
+ }
+ }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
new file mode 100755
index 0000000..7b4e66d
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Core_MixSoft_1St_D32C31_WRA.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION CORE_MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void Core_MixSoft_1St_D32C31_WRA( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 Temp1,Temp2;
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT32 TargetTimesOneMinAlpha;
+ LVM_INT32 CurrentTimesAlpha;
+ LVM_INT16 CurrentShort;
+ LVM_INT16 ii;
+
+ InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+ OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+ MUL32x32INTO32((0x7FFFFFFF-pInstance->Alpha),pInstance->Target,TargetTimesOneMinAlpha,31) /* Q31 * Q31 in Q31 */
+ if (pInstance->Target >= pInstance->Current)
+ {
+ TargetTimesOneMinAlpha +=2; /* Ceil*/
+ }
+
+ if (OutLoop!=0)
+ {
+ MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31) /* Q31 * Q31 in Q31 */
+ pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha; /* Q31 + Q31 into Q31*/
+ CurrentShort = (LVM_INT16)(pInstance->Current>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop; ii != 0; ii--)
+ {
+ Temp1=*src;
+ src++;
+
+ MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+ *dst = Temp2;
+ dst++;
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--)
+ {
+ MUL32x32INTO32(pInstance->Current,pInstance->Alpha,CurrentTimesAlpha,31) /* Q31 * Q31 in Q31 */
+ pInstance->Current = TargetTimesOneMinAlpha + CurrentTimesAlpha; /* Q31 + Q31 into Q31*/
+ CurrentShort = (LVM_INT16)(pInstance->Current>>16); /* From Q31 to Q15*/
+ Temp1=*src;
+ src++;
+
+ MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+ *dst = Temp2;
+ dst++;
+
+ Temp1=*src;
+ src++;
+
+ MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+ *dst = Temp2;
+ dst++;
+
+ Temp1=*src;
+ src++;
+
+ MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+ *dst = Temp2;
+ dst++;
+
+ Temp1=*src;
+ src++;
+ MUL32x16INTO32(Temp1,CurrentShort,Temp2,15)
+ *dst = Temp2;
+ dst++;
+ }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
new file mode 100755
index 0000000..187fe68
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "DC_2I_D16_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+void DC_2I_D16_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 LeftDC,RightDC;
+ LVM_INT32 Diff;
+ LVM_INT32 j;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ LeftDC = pBiquadState->LeftDC;
+ RightDC = pBiquadState->RightDC;
+ for(j=NrSamples-1;j>=0;j--)
+ {
+ /* Subtract DC an saturate */
+ Diff=*(pDataIn++)-(LeftDC>>16);
+ if (Diff > 32767) {
+ Diff = 32767; }
+ else if (Diff < -32768) {
+ Diff = -32768; }
+ *(pDataOut++)=(LVM_INT16)Diff;
+ if (Diff < 0) {
+ LeftDC -= DC_D16_STEP; }
+ else {
+ LeftDC += DC_D16_STEP; }
+
+
+ /* Subtract DC an saturate */
+ Diff=*(pDataIn++)-(RightDC>>16);
+ if (Diff > 32767) {
+ Diff = 32767; }
+ else if (Diff < -32768) {
+ Diff = -32768; }
+ *(pDataOut++)=(LVM_INT16)Diff;
+ if (Diff < 0) {
+ RightDC -= DC_D16_STEP; }
+ else {
+ RightDC += DC_D16_STEP; }
+
+ }
+ pBiquadState->LeftDC = LeftDC;
+ pBiquadState->RightDC = RightDC;
+
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..292641b
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "DC_2I_D16_TRC_WRA_01_Private.h"
+
+void DC_2I_D16_TRC_WRA_01_Init(Biquad_Instance_t *pInstance)
+{
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->LeftDC = 0;
+ pBiquadState->RightDC = 0;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..2514a77
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
+#define _DC_2I_D16_TRC_WRA_01_PRIVATE_H_
+
+#define DC_D16_STEP 0x200;
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use.*/
+typedef struct _Filter_State_
+{
+ LVM_INT32 LeftDC; /* LeftDC */
+ LVM_INT32 RightDC; /* RightDC */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _DC_2I_D16_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
new file mode 100755
index 0000000..cda72ac
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION DelayAllPass_32x32
+***********************************************************************************/
+
+void DelayAllPass_Sat_32x16To32( LVM_INT32 *delay, /* Delay buffer */
+ LVM_UINT16 size, /* Delay size */
+ LVM_INT16 coeff, /* All pass filter coefficient */
+ LVM_UINT16 DelayOffset, /* Simple delay offset */
+ LVM_UINT16 *pAllPassOffset, /* All pass filter delay offset */
+ LVM_INT32 *dst, /* Source/destination */
+ LVM_INT16 n) /* Number of samples */
+{
+ LVM_INT16 i;
+ LVM_UINT16 AllPassOffset = *pAllPassOffset;
+ LVM_INT32 temp;
+ LVM_INT32 a,b,c;
+
+ for (i = 0; i < n; i++)
+ {
+
+ MUL32x16INTO32(delay[AllPassOffset], coeff, temp, 15)
+ a = temp;
+ b = delay[DelayOffset];
+ DelayOffset++;
+
+ c = a + b;
+ if ((((c ^ a) & (c ^ b)) >> 31) != 0) /* overflow / underflow */
+ {
+ if(a < 0)
+ {
+ c = 0x80000000l;
+ }
+ else
+ {
+ c = 0x7FFFFFFFl;
+ }
+ }
+ *dst = c;
+ dst++;
+
+
+ MUL32x16INTO32(c, -coeff, temp, 15)
+ a = temp;
+ b = delay[AllPassOffset];
+ c = a + b;
+ if ((((c ^ a) & (c ^ b)) >> 31)!=0) /* overflow / underflow */
+ {
+ if(a < 0)
+ {
+ c = 0x80000000l;
+ }
+ else
+ {
+ c = 0x7FFFFFFFl;
+ }
+ }
+ delay[AllPassOffset] = c;
+ AllPassOffset++;
+
+ /* Make the delay buffer a circular buffer */
+ if (DelayOffset >= size)
+ {
+ DelayOffset = 0;
+ }
+
+ if (AllPassOffset >= size)
+ {
+ AllPassOffset = 0;
+ }
+ }
+
+ /* Update the offset */
+ *pAllPassOffset = AllPassOffset;
+
+ return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
new file mode 100755
index 0000000..ee41701
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayMix_16x16.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION DelayMix_16x16
+***********************************************************************************/
+
+void DelayMix_16x16(const LVM_INT16 *src, /* Source 1, to be delayed */
+ LVM_INT16 *delay, /* Delay buffer */
+ LVM_INT16 size, /* Delay size */
+ LVM_INT16 *dst, /* Source/destination */
+ LVM_INT16 *pOffset, /* Delay offset */
+ LVM_INT16 n) /* Number of stereo samples */
+{
+ LVM_INT16 i;
+ LVM_INT16 Offset = *pOffset;
+ LVM_INT16 temp;
+
+ for (i=0; i<n; i++)
+ {
+ /* Left channel */
+ temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) + (LVM_INT32)delay[Offset]) >> 1);
+ *dst = temp;
+ dst++;
+
+ delay[Offset] = *src;
+ Offset++;
+ src++;
+
+
+ /* Right channel */
+ temp = (LVM_INT16)((LVM_UINT32)((LVM_INT32)(*dst) - (LVM_INT32)delay[Offset]) >> 1);
+ *dst = temp;
+ dst++;
+
+ delay[Offset] = *src;
+ Offset++;
+ src++;
+
+ /* Make the reverb delay buffer a circular buffer */
+ if (Offset >= size)
+ {
+ Offset = 0;
+ }
+ }
+
+ /* Update the offset */
+ *pOffset = Offset;
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c
new file mode 100755
index 0000000..0ae4c42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/DelayWrite_32.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION DelayMix_16x16
+***********************************************************************************/
+
+void DelayWrite_32(const LVM_INT32 *src, /* Source 1, to be delayed */
+ LVM_INT32 *delay, /* Delay buffer */
+ LVM_UINT16 size, /* Delay size */
+ LVM_UINT16 *pOffset, /* Delay offset */
+ LVM_INT16 n) /* Number of samples */
+{
+ LVM_INT16 i;
+ LVM_INT16 Offset = (LVM_INT16)*pOffset;
+
+ for (i=0; i<n; i++)
+ {
+ delay[Offset] = *src;
+ Offset++;
+ src++;
+
+ /* Make the delay buffer a circular buffer */
+ if (Offset >= size)
+ {
+ Offset = 0;
+ }
+ }
+
+ /* Update the offset */
+ *pOffset = (LVM_UINT16)Offset;
+
+ return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
new file mode 100755
index 0000000..831a115
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16C15_TRC_WRA_01.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A1,
+ pBiquadState->coefs[1] is A0,
+ pBiquadState->coefs[2] is -B1, these are in Q15 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is y(n-1)L in Q0 format
+***************************************************************************/
+
+void FO_1I_D16F16C15_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL=A1 (Q15) * x(n-1)L (Q0) in Q15
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[0];
+
+ // ynL+=A0 (Q15) * x(n)L (Q0) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* (*pDataIn);
+
+ // ynL+= (-B1 (Q15) * y(n-1)L (Q0) ) in Q15
+ ynL+=(LVM_INT32)pBiquadState->coefs[2]*pBiquadState->pDelays[1];
+
+
+ ynL=(LVM_INT16)(ynL>>15); // ynL in Q0 format
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT16)ynL; // Write Left output in Q0
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..4675084
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Init.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "FO_1I_D16F16Css_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* FO_1I_D16F16Css_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void FO_1I_D16F16Css_TRC_WRA_01_Init( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order1_Taps_t *pTaps,
+ FO_C16_Coefs_t *pCoef)
+{
+ LVM_INT16 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps;
+
+ temp=pCoef->A1;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[2]=temp;
+}
+/*------------------------------------------------*/
+/* End Of File: FO_1I_D16F16Css_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..e1a818c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D16F16Css_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+#define _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $ */
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32* pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT16 coefs[3]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _FO_1I_D16F16CSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
new file mode 100755
index 0000000..9bdc5b4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32C31_TRC_WRA_01.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A1,
+ pBiquadState->coefs[1] is A0,
+ pBiquadState->coefs[2] is -B1, these are in Q31 format
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is y(n-1)L in Q0 format
+***************************************************************************/
+
+void FO_1I_D32F32C31_TRC_WRA_01( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ // ynL=A1 (Q31) * x(n-1)L (Q0) >>31 in Q0
+ MUL32x32INTO32(pBiquadState->coefs[0],pBiquadState->pDelays[0],ynL,31)
+
+ // ynL+=A0 (Q31) * x(n)L (Q0) >> 31 in Q0
+ MUL32x32INTO32(pBiquadState->coefs[1],*pDataIn,templ,31)
+ ynL+=templ;
+
+ // ynL+= (-B1 (Q31) * y(n-1)L (Q0) ) >> 31 in Q0
+ MUL32x32INTO32(pBiquadState->coefs[2],pBiquadState->pDelays[1],templ,31)
+ ynL+=templ;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q0
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q0
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut++=(LVM_INT32)ynL; // Write Left output in Q0
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..eea0b64
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Init.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_1I_D32F32Cll_TRC_WRA_01_Private.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* FO_1I_D32F32Cll_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_Instance_t *pInstance,
+ Biquad_1I_Order1_Taps_t *pTaps,
+ FO_C32_Coefs_t *pCoef)
+{
+ LVM_INT32 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays = (LVM_INT32 *) pTaps;
+
+ temp=pCoef->A1;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[2]=temp;
+}
+/*------------------------------------------------*/
+/* End Of File: FO_1I_D32F32Cll_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..9329150
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_1I_D32F32Cll_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#ifndef _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+#define _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_
+
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[3]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _FO_1I_D32F32CLL_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
new file mode 100755
index 0000000..4b219a2
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ASSUMPTIONS:
+COEFS-
+pBiquadState->coefs[0] is A1,
+pBiquadState->coefs[1] is A0,
+pBiquadState->coefs[2] is -B1, these are in Q15 format
+pBiquadState->Shift is Shift value
+DELAYS-
+pBiquadState->pDelays[0] is x(n-1)L in Q15 format
+pBiquadState->pDelays[1] is y(n-1)L in Q30 format
+pBiquadState->pDelays[2] is x(n-1)R in Q15 format
+pBiquadState->pDelays[3] is y(n-1)R in Q30 format
+***************************************************************************/
+
+void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t *pInstance,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR;
+ LVM_INT32 Temp;
+ LVM_INT32 NegSatValue;
+ LVM_INT16 ii;
+ LVM_INT16 Shift;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ NegSatValue = LVM_MAXINT_16 +1;
+ NegSatValue = -NegSatValue;
+
+ Shift = pBiquadState->Shift;
+
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+
+ // ynL =A1 (Q15) * x(n-1)L (Q15) in Q30
+ ynL=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[0];
+ // ynR =A1 (Q15) * x(n-1)R (Q15) in Q30
+ ynR=(LVM_INT32)pBiquadState->coefs[0]* pBiquadState->pDelays[2];
+
+
+ // ynL+=A0 (Q15) * x(n)L (Q15) in Q30
+ ynL+=(LVM_INT32)pBiquadState->coefs[1]* (*pDataIn);
+ // ynR+=A0 (Q15) * x(n)L (Q15) in Q30
+ ynR+=(LVM_INT32)pBiquadState->coefs[1]* (*(pDataIn+1));
+
+
+ // ynL += (-B1 (Q15) * y(n-1)L (Q30) ) in Q30
+ MUL32x16INTO32(pBiquadState->pDelays[1],pBiquadState->coefs[2],Temp,15);
+ ynL +=Temp;
+ // ynR += (-B1 (Q15) * y(n-1)R (Q30) ) in Q30
+ MUL32x16INTO32(pBiquadState->pDelays[3],pBiquadState->coefs[2],Temp,15);
+ ynR +=Temp;
+
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[1]=ynL; // Update y(n-1)L in Q30
+ pBiquadState->pDelays[0]=(*pDataIn++); // Update x(n-1)L in Q15
+
+ pBiquadState->pDelays[3]=ynR; // Update y(n-1)R in Q30
+ pBiquadState->pDelays[2]=(*pDataIn++); // Update x(n-1)R in Q15
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ /*Apply shift: Instead of left shift on 16-bit result, right shift of (15-shift) is applied
+ for better SNR*/
+ ynL = ynL>>(15-Shift);
+ ynR = ynR>>(15-Shift);
+
+ /*Saturate results*/
+ if(ynL > LVM_MAXINT_16)
+ {
+ ynL = LVM_MAXINT_16;
+ }
+ else
+ {
+ if(ynL < NegSatValue)
+ {
+ ynL = NegSatValue;
+ }
+ }
+
+ if(ynR > LVM_MAXINT_16)
+ {
+ ynR = LVM_MAXINT_16;
+ }
+ else
+ {
+ if(ynR < NegSatValue)
+ {
+ ynR = NegSatValue;
+ }
+ }
+
+ *pDataOut++=(LVM_INT16)ynL;
+ *pDataOut++=(LVM_INT16)ynR;
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..7f212f5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/*-------------------------------------------------------------------------*/
+#include "BIQUAD.h"
+#include "FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* FO_2I_D16F32Css_LShx_TRC_WRA_01_Init */
+/* */
+/* DESCRIPTION: */
+/* These functions initializes a BIQUAD filter defined as a cascade of */
+/* biquadratic Filter Sections. */
+/* */
+/* PARAMETERS: */
+/* pInstance - output, returns the pointer to the State Variable */
+/* This state pointer must be passed to any subsequent */
+/* call to "Biquad" functions. */
+/* pTaps - input, pointer to the taps memory */
+/* pCoef - input, pointer to the coefficient structure */
+/* N - M coefficient factor of QM.N */
+/* RETURNS: */
+/* void return code */
+/*-------------------------------------------------------------------------*/
+void FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(Biquad_Instance_t *pInstance,
+ Biquad_2I_Order1_Taps_t *pTaps,
+ FO_C16_LShx_Coefs_t *pCoef)
+{
+ LVM_INT16 temp;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps ;
+
+ temp=pCoef->A1;
+ pBiquadState->coefs[0]=temp;
+ temp=pCoef->A0;
+ pBiquadState->coefs[1]=temp;
+ temp=pCoef->B1;
+ pBiquadState->coefs[2]=temp;
+
+ temp=pCoef->Shift;
+ pBiquadState->Shift = temp;
+}
+/*-------------------------------------------------------------------------*/
+/* End Of File: FO_2I_D16F32Css_LShx_TRC_WRA_01_Init.c */
+
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..6a4564a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32Css_LShx_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
+#define _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 *pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT16 coefs[3]; /* pointer to the filter coefficients */
+ LVM_INT16 Shift; /* Shift value*/
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _FO_2I_D16F32CSS_LSHX_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/Filters.h b/media/libeffects/lvm/lib/Common/src/Filters.h
new file mode 100755
index 0000000..a274f32
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Filters.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef FILTERS_H
+#define FILTERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "LVM_Types.h"
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+/*
+ * Biquad with coefficients A0, A1, A2, B1 and B2 coefficients
+ */
+/* Single precision (16-bit) Biquad section coefficients */
+typedef struct
+{
+ LVM_INT16 A0;
+ LVM_INT16 A1;
+ LVM_INT16 A2;
+ LVM_INT16 B1;
+ LVM_INT16 B2;
+ LVM_UINT16 Scale;
+} BiquadA012B12CoefsSP_t;
+
+
+/*
+ * Biquad with coefficients A0, A1 and B1 coefficients
+ */
+/* Single precision (16-bit) Biquad section coefficients */
+typedef struct
+{
+ LVM_INT16 A0;
+ LVM_INT16 A1;
+ LVM_INT16 B1;
+ LVM_UINT16 Scale;
+} BiquadA01B1CoefsSP_t;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* FILTERS_H */
+
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
new file mode 100755
index 0000000..fb00768
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMS_16x16.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION From2iToMS_16x16
+***********************************************************************************/
+
+void From2iToMS_16x16( const LVM_INT16 *src,
+ LVM_INT16 *dstM,
+ LVM_INT16 *dstS,
+ LVM_INT16 n )
+{
+ LVM_INT32 temp1,left,right;
+ LVM_INT16 ii;
+ for (ii = n; ii != 0; ii--)
+ {
+ left = (LVM_INT32)*src;
+ src++;
+
+ right = (LVM_INT32)*src;
+ src++;
+
+ /* Compute M signal*/
+ temp1 = (left+right)>>1;
+ *dstM = (LVM_INT16)temp1;
+ dstM++;
+
+ /* Compute S signal*/
+ temp1 = (left-right)>>1;
+ *dstS = (LVM_INT16)temp1;
+ dstS++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c
new file mode 100755
index 0000000..0ebb4ae
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_16.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION From2iToMono_16
+***********************************************************************************/
+
+void From2iToMono_16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT32 Temp;
+ for (ii = n; ii != 0; ii--)
+ {
+ Temp = (LVM_INT32)*src;
+ src++;
+
+ Temp += (LVM_INT32)*src;
+ src++;
+
+ *dst = (LVM_INT16)(Temp >>1);
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
new file mode 100755
index 0000000..5181368
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION From2iToMono_32
+***********************************************************************************/
+
+void From2iToMono_32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT32 Temp;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ Temp = (*src>>1);
+ src++;
+
+ Temp +=(*src>>1);
+ src++;
+
+ *dst = Temp;
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/InstAlloc.c b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
new file mode 100755
index 0000000..ff900e0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/InstAlloc.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "InstAlloc.h"
+
+/****************************************************************************************
+ * Name : InstAlloc_Init()
+ * Input : pms - Pointer to the INST_ALLOC instance
+ StartAddr - Base address of the instance memory
+ * Returns : Error code
+ * Description : Initializes the instance distribution and memory size calculation function
+ * Remarks :
+ ****************************************************************************************/
+
+void InstAlloc_Init( INST_ALLOC *pms,
+ void *StartAddr )
+{
+ pms->TotalSize = 3;
+ pms->pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);/* This code will fail if the platform address space is more than 32-bits*/
+}
+
+
+/****************************************************************************************
+ * Name : InstAlloc_AddMember()
+ * Input : pms - Pointer to the INST_ALLOC instance
+ Size - The size in bytes of the new added member
+ * Returns : A pointer to the new added member
+ * Description : Allocates space for a new member in the instance memory and returns
+ a pointer to this new member. The start address of all members will
+ be 32 bit alligned.
+ * Remarks :
+ ****************************************************************************************/
+
+void* InstAlloc_AddMember( INST_ALLOC *pms,
+ LVM_UINT32 Size )
+{
+ void *NewMemberAddress; /* Variable to temporarily store the return value */
+ NewMemberAddress = (void*)pms->pNextMember;
+
+ Size = ((Size + 3) & 0xFFFFFFFC); /* Ceil the size to a multiple of four */
+
+ pms->TotalSize += Size;
+ pms->pNextMember += Size;
+
+ return(NewMemberAddress);
+}
+
+
+/****************************************************************************************
+ * Name : InstAlloc_GetTotal()
+ * Input : pms - Pointer to the INST_ALLOC instance
+ * Returns : The instance memory size
+ * Description : This functions returns the calculated instance memory size
+ * Remarks :
+ ****************************************************************************************/
+
+LVM_UINT32 InstAlloc_GetTotal( INST_ALLOC *pms)
+{
+ if (pms->TotalSize > 3)
+ {
+ return(pms->TotalSize);
+ }
+ else
+ {
+ return 0; /* No memory added */
+ }
+}
+
+
+void InstAlloc_InitAll( INST_ALLOC *pms,
+ LVM_MemoryTable_st *pMemoryTable)
+{
+ LVM_UINT32 StartAddr;
+
+ StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress;
+
+ pms[0].TotalSize = 3;
+ pms[0].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+
+ StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress;
+
+ pms[1].TotalSize = 3;
+ pms[1].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+
+ StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress;
+
+ pms[2].TotalSize = 3;
+ pms[2].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+
+ StartAddr = (LVM_UINT32)pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress;
+
+ pms[3].TotalSize = 3;
+ pms[3].pNextMember = (LVM_UINT32)(((LVM_UINT32)StartAddr + 3) & 0xFFFFFFFC);
+
+}
+
+/****************************************************************************************
+ * Name : InstAlloc_InitAll_NULL()
+ * Input : pms - Pointer to array of four INST_ALLOC instances
+ * Returns : Nothing
+ * Description : This function reserves Size of 3 bytes for all memory regions and
+ * intializes pNextMember for all regions to 0
+ * Remarks :
+ ****************************************************************************************/
+
+void InstAlloc_InitAll_NULL( INST_ALLOC *pms)
+{
+ pms[0].TotalSize = 3;
+ pms[0].pNextMember = 0;
+
+
+ pms[1].TotalSize = 3;
+ pms[1].pNextMember = 0;
+
+ pms[2].TotalSize = 3;
+ pms[2].pNextMember = 0;
+
+ pms[3].TotalSize = 3;
+ pms[3].pNextMember = 0;
+
+}
+
+
+void* InstAlloc_AddMemberAll( INST_ALLOC *pms,
+ LVM_UINT32 Size[],
+ LVM_MemoryTable_st *pMemoryTable)
+{
+ void *NewMemberAddress; /* Variable to temporarily store the return value */
+
+ /* coverity[returned_pointer] Ignore coverity warning that ptr is not used */
+ NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
+
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Size = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_SLOW_DATA]);
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].Type = LVM_PERSISTENT_SLOW_DATA;
+ pMemoryTable->Region[LVM_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+ NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
+
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Size = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_DATA]);
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].Type = LVM_PERSISTENT_FAST_DATA;
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+ NewMemberAddress = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
+
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Size = InstAlloc_GetTotal(&pms[LVM_PERSISTENT_FAST_COEF]);
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].Type = LVM_PERSISTENT_FAST_COEF;
+ pMemoryTable->Region[LVM_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+ NewMemberAddress = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
+
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].Size = InstAlloc_GetTotal(&pms[LVM_TEMPORARY_FAST]);
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].Type = LVM_TEMPORARY_FAST;
+ pMemoryTable->Region[LVM_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+
+ return(NewMemberAddress);
+}
+
+
+void* InstAlloc_AddMemberAllRet( INST_ALLOC *pms,
+ LVM_UINT32 Size[],
+ void **ptr)
+{
+ ptr[0] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_SLOW_DATA], Size[LVM_PERSISTENT_SLOW_DATA]);
+ ptr[1] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_DATA], Size[LVM_PERSISTENT_FAST_DATA]);
+ ptr[2] = InstAlloc_AddMember(&pms[LVM_PERSISTENT_FAST_COEF], Size[LVM_PERSISTENT_FAST_COEF]);
+ ptr[3] = InstAlloc_AddMember(&pms[LVM_TEMPORARY_FAST], Size[LVM_TEMPORARY_FAST]);
+
+ return (ptr[0]);
+}
diff --git a/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c
new file mode 100755
index 0000000..e6be756
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Int16LShiftToInt32_16x32.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION INT16LSHIFTTOINT32_16X32
+***********************************************************************************/
+
+void Int16LShiftToInt32_16x32(const LVM_INT16 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n,
+ LVM_INT16 shift )
+{
+ LVM_INT16 ii;
+
+ src += n-1;
+ dst += n-1;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = ( ((LVM_INT32)*src) << shift);
+ src--;
+ dst--;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c
new file mode 100755
index 0000000..b21eef5
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Int32RShiftToInt16_Sat_32x16.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION INT32RSHIFTTOINT16_SAT_32X16
+***********************************************************************************/
+
+void Int32RShiftToInt16_Sat_32x16(const LVM_INT32 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n,
+ LVM_INT16 shift )
+{
+ LVM_INT32 temp;
+ LVM_INT16 ii;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ temp = *src >> shift;
+ src++;
+
+ if (temp > 0x00007FFF)
+ {
+ *dst = 0x7FFF;
+ }
+ else if (temp < -0x00008000)
+ {
+ *dst = - 0x8000;
+ }
+ else
+ {
+ *dst = (LVM_INT16)temp;
+ }
+
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
new file mode 100755
index 0000000..e04f1c3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/JoinTo2i_32x32.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION JoinTo2i_32x32
+***********************************************************************************/
+
+void JoinTo2i_32x32( const LVM_INT32 *srcL,
+ const LVM_INT32 *srcR,
+ LVM_INT32 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT16 ii;
+
+ srcL += n-1;
+ srcR += n-1;
+ dst += ((2*n)-1);
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = *srcR;
+ dst--;
+ srcR--;
+
+ *dst = *srcL;
+ dst--;
+ srcL--;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
new file mode 100755
index 0000000..c1d2b2c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_1St_2i_D16C31_SAT.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+
+/**********************************************************************************
+ FUNCTION LVC_Core_MixHard_1St_2i_D16C31_SAT
+***********************************************************************************/
+
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st *ptrInstance1,
+ LVMixer3_st *ptrInstance2,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 Temp;
+ LVM_INT16 ii;
+ LVM_INT16 Current1Short;
+ LVM_INT16 Current2Short;
+ Mix_Private_st *pInstance1=(Mix_Private_st *)(ptrInstance1->PrivateParams);
+ Mix_Private_st *pInstance2=(Mix_Private_st *)(ptrInstance2->PrivateParams);
+
+
+ Current1Short = (LVM_INT16)(pInstance1->Current >> 16);
+ Current2Short = (LVM_INT16)(pInstance2->Current >> 16);
+
+ for (ii = n; ii != 0; ii--)
+ {
+ Temp = ((LVM_INT32)*(src++) * (LVM_INT32)Current1Short)>>15;
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+
+ Temp = ((LVM_INT32)*(src++) * (LVM_INT32)Current2Short)>>15;
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+ }
+
+
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
new file mode 100755
index 0000000..2bb212c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixHard_2St_D16C31_SAT.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+
+/**********************************************************************************
+ FUNCTION LVCore_MIXHARD_2ST_D16C31_SAT
+***********************************************************************************/
+
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *ptrInstance1,
+ LVMixer3_st *ptrInstance2,
+ const LVM_INT16 *src1,
+ const LVM_INT16 *src2,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 Temp;
+ LVM_INT16 ii;
+ LVM_INT16 Current1Short;
+ LVM_INT16 Current2Short;
+ Mix_Private_st *pInstance1=(Mix_Private_st *)(ptrInstance1->PrivateParams);
+ Mix_Private_st *pInstance2=(Mix_Private_st *)(ptrInstance2->PrivateParams);
+
+
+ Current1Short = (LVM_INT16)(pInstance1->Current >> 16);
+ Current2Short = (LVM_INT16)(pInstance2->Current >> 16);
+
+ for (ii = n; ii != 0; ii--){
+ Temp = (((LVM_INT32)*(src1++) * (LVM_INT32)Current1Short)>>15) +
+ (((LVM_INT32)*(src2++) * (LVM_INT32)Current2Short)>>15);
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+ }
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
new file mode 100755
index 0000000..0408f42
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
+***********************************************************************************/
+
+void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *ptrInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT16 CurrentShort;
+ LVM_INT32 ii,jj;
+ Mix_Private_st *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
+ LVM_INT32 Delta=pInstance->Delta;
+ LVM_INT32 Current=pInstance->Current;
+ LVM_INT32 Target=pInstance->Target;
+ LVM_INT32 Temp;
+
+ InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+ OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+ if(Current<Target){
+ if (OutLoop){
+ ADD2_SAT_32x32(Current,Delta,Temp); /* Q31 + Q31 into Q31*/
+ Current=Temp;
+ if (Current > Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop; ii != 0; ii--){
+ Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--){
+ ADD2_SAT_32x32(Current,Delta,Temp); /* Q31 + Q31 into Q31*/
+ Current=Temp;
+ if (Current > Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ for (jj = 4; jj!=0 ; jj--){
+ Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+ }
+ }
+ }
+ else{
+ if (OutLoop){
+ Current -= Delta; /* Q31 + Q31 into Q31*/
+ if (Current < Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop; ii != 0; ii--){
+ Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--){
+ Current -= Delta; /* Q31 + Q31 into Q31*/
+ if (Current < Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ for (jj = 4; jj!=0 ; jj--){
+ Temp = ((LVM_INT32)*dst) + (((LVM_INT32)*(src++) * CurrentShort)>>15); /* Q15 + Q15*Q15>>15 into Q15 */
+ if (Temp > 0x00007FFF)
+ *dst++ = 0x7FFF;
+ else if (Temp < -0x00008000)
+ *dst++ = - 0x8000;
+ else
+ *dst++ = (LVM_INT16)Temp;
+ }
+ }
+ }
+ pInstance->Current=Current;
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
new file mode 100755
index 0000000..2847d47
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_2i_D16C31_WRA.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "ScalarArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION LVC_Core_MixSoft_1St_2i_D16C31_WRA
+***********************************************************************************/
+
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st *ptrInstance1,
+ LVMixer3_st *ptrInstance2,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT16 CurrentShortL;
+ LVM_INT16 CurrentShortR;
+ LVM_INT32 ii;
+ Mix_Private_st *pInstanceL=(Mix_Private_st *)(ptrInstance1->PrivateParams);
+ Mix_Private_st *pInstanceR=(Mix_Private_st *)(ptrInstance2->PrivateParams);
+
+ LVM_INT32 DeltaL=pInstanceL->Delta;
+ LVM_INT32 CurrentL=pInstanceL->Current;
+ LVM_INT32 TargetL=pInstanceL->Target;
+
+ LVM_INT32 DeltaR=pInstanceR->Delta;
+ LVM_INT32 CurrentR=pInstanceR->Current;
+ LVM_INT32 TargetR=pInstanceR->Target;
+
+ LVM_INT32 Temp;
+
+ InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+ OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+ if (OutLoop)
+ {
+ if(CurrentL<TargetL)
+ {
+ ADD2_SAT_32x32(CurrentL,DeltaL,Temp); /* Q31 + Q31 into Q31*/
+ CurrentL=Temp;
+ if (CurrentL > TargetL)
+ CurrentL = TargetL;
+ }
+ else
+ {
+ CurrentL -= DeltaL; /* Q31 + Q31 into Q31*/
+ if (CurrentL < TargetL)
+ CurrentL = TargetL;
+ }
+
+ if(CurrentR<TargetR)
+ {
+ ADD2_SAT_32x32(CurrentR,DeltaR,Temp); /* Q31 + Q31 into Q31*/
+ CurrentR=Temp;
+ if (CurrentR > TargetR)
+ CurrentR = TargetR;
+ }
+ else
+ {
+ CurrentR -= DeltaR; /* Q31 + Q31 into Q31*/
+ if (CurrentR < TargetR)
+ CurrentR = TargetR;
+ }
+
+ CurrentShortL = (LVM_INT16)(CurrentL>>16); /* From Q31 to Q15*/
+ CurrentShortR = (LVM_INT16)(CurrentR>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop*2; ii != 0; ii-=2)
+ {
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15); /* Q15*Q15>>15 into Q15 */
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15); /* Q15*Q15>>15 into Q15 */
+ }
+ }
+
+ for (ii = InLoop*2; ii != 0; ii-=2)
+ {
+ if(CurrentL<TargetL)
+ {
+ ADD2_SAT_32x32(CurrentL,DeltaL,Temp); /* Q31 + Q31 into Q31*/
+ CurrentL=Temp;
+ if (CurrentL > TargetL)
+ CurrentL = TargetL;
+ }
+ else
+ {
+ CurrentL -= DeltaL; /* Q31 + Q31 into Q31*/
+ if (CurrentL < TargetL)
+ CurrentL = TargetL;
+ }
+
+ if(CurrentR<TargetR)
+ {
+ ADD2_SAT_32x32(CurrentR,DeltaR,Temp); /* Q31 + Q31 into Q31*/
+ CurrentR=Temp;
+ if (CurrentR > TargetR)
+ CurrentR = TargetR;
+ }
+ else
+ {
+ CurrentR -= DeltaR; /* Q31 + Q31 into Q31*/
+ if (CurrentR < TargetR)
+ CurrentR = TargetR;
+ }
+
+ CurrentShortL = (LVM_INT16)(CurrentL>>16); /* From Q31 to Q15*/
+ CurrentShortR = (LVM_INT16)(CurrentR>>16); /* From Q31 to Q15*/
+
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15); /* Q15*Q15>>15 into Q15 */
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15); /* Q15*Q15>>15 into Q15 */
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortL)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShortR)>>15);
+ }
+ pInstanceL->Current=CurrentL;
+ pInstanceR->Current=CurrentR;
+
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
new file mode 100755
index 0000000..78f0122
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
+***********************************************************************************/
+
+void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *ptrInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT16 CurrentShort;
+ LVM_INT32 ii;
+ Mix_Private_st *pInstance=(Mix_Private_st *)(ptrInstance->PrivateParams);
+ LVM_INT32 Delta=pInstance->Delta;
+ LVM_INT32 Current=pInstance->Current;
+ LVM_INT32 Target=pInstance->Target;
+ LVM_INT32 Temp;
+
+ InLoop = (LVM_INT16)(n >> 2); /* Process per 4 samples */
+ OutLoop = (LVM_INT16)(n - (InLoop << 2));
+
+ if(Current<Target){
+ if (OutLoop){
+ ADD2_SAT_32x32(Current,Delta,Temp); /* Q31 + Q31 into Q31*/
+ Current=Temp;
+ if (Current > Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop; ii != 0; ii--){
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15); /* Q15*Q15>>15 into Q15 */
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--){
+ ADD2_SAT_32x32(Current,Delta,Temp); /* Q31 + Q31 into Q31*/
+ Current=Temp;
+ if (Current > Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15); /* Q15*Q15>>15 into Q15 */
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+ }
+ }
+ else{
+ if (OutLoop){
+ Current -= Delta; /* Q31 + Q31 into Q31*/
+ if (Current < Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ for (ii = OutLoop; ii != 0; ii--){
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15); /* Q15*Q15>>15 into Q15 */
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--){
+ Current -= Delta; /* Q31 + Q31 into Q31*/
+ if (Current < Target)
+ Current = Target;
+
+ CurrentShort = (LVM_INT16)(Current>>16); /* From Q31 to Q15*/
+
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15); /* Q15*Q15>>15 into Q15 */
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+ *(dst++) = (LVM_INT16)(((LVM_INT32)*(src++) * (LVM_INT32)CurrentShort)>>15);
+ }
+ }
+ pInstance->Current=Current;
+}
+
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
new file mode 100755
index 0000000..52be129
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+/**********************************************************************************
+ FUNCTION MIXINSOFT_D16C31_SAT
+***********************************************************************************/
+
+void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
+ LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ char HardMixing = TRUE;
+ LVM_INT32 TargetGain;
+ Mix_Private_st *pInstance=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if (pInstance->Current != pInstance->Target)
+ {
+ if(pInstance->Delta == 0x7FFFFFFF){
+ pInstance->Current = pInstance->Target;
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+ }else if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+ }else{
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ if(pInstance->Shift!=0){
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
+ LVC_Core_MixInSoft_D16C31_SAT( &(ptrInstance->MixerStream[0]), src, dst, n);
+ }
+ else
+ LVC_Core_MixInSoft_D16C31_SAT( &(ptrInstance->MixerStream[0]), src, dst, n);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing){
+ if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+ if ((pInstance->Target>>16) == 0x7FFF){
+ if(pInstance->Shift!=0)
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
+ Add2_Sat_16x16( src, dst, n );
+ }
+ else{
+ if(pInstance->Shift!=0)
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,src,n);
+ Mac3s_Sat_16x16(src,(LVM_INT16)(pInstance->Target>>16),dst,n);
+ pInstance->Current = pInstance->Target; /* In case the LVCore function would have changed the Current value */
+ }
+ }
+ }
+
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (ptrInstance->MixerStream[0].CallbackSet){
+ if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(ptrInstance->MixerStream,TargetGain);
+ ptrInstance->MixerStream[0].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[0].pCallBack != 0){
+ (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
+ }
+ }
+ }
+
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
new file mode 100755
index 0000000..d832e06
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_2i_D16C31_SAT.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+/**********************************************************************************
+ FUNCTION LVC_MixSoft_1St_2i_D16C31_SAT
+***********************************************************************************/
+
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ char HardMixing = TRUE;
+ LVM_INT32 TargetGain;
+ Mix_Private_st *pInstance1=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+ Mix_Private_st *pInstance2=(Mix_Private_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if ((pInstance1->Current != pInstance1->Target)||(pInstance2->Current != pInstance2->Target))
+ {
+ if(pInstance1->Delta == 0x7FFFFFFF)
+ {
+ pInstance1->Current = pInstance1->Target;
+ TargetGain=pInstance1->Target>>16; // TargetGain in Q16.15 format, no integer part
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+ }
+ else if (Abs_32(pInstance1->Current-pInstance1->Target) < pInstance1->Delta)
+ {
+ pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance1->Target>>16; // TargetGain in Q16.15 format, no integer part
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+ }
+ else
+ {
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ }
+
+ if(HardMixing == TRUE)
+ {
+ if(pInstance2->Delta == 0x7FFFFFFF)
+ {
+ pInstance2->Current = pInstance2->Target;
+ TargetGain=pInstance2->Target>>16; // TargetGain in Q16.15 format, no integer part
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]),TargetGain);
+ }
+ else if (Abs_32(pInstance2->Current-pInstance2->Target) < pInstance2->Delta)
+ {
+ pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance2->Target>>16; // TargetGain in Q16.15 format, no integer part
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[1]),TargetGain);
+ }
+ else
+ {
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ }
+ }
+
+ if(HardMixing == FALSE)
+ {
+ LVC_Core_MixSoft_1St_2i_D16C31_WRA( &(ptrInstance->MixerStream[0]),&(ptrInstance->MixerStream[1]), src, dst, n);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing)
+ {
+ if (((pInstance1->Target>>16) == 0x7FFF)&&((pInstance2->Target>>16) == 0x7FFF))
+ {
+ if(src!=dst)
+ {
+ Copy_16(src, dst, n);
+ }
+ }
+ else
+ {
+ LVC_Core_MixHard_1St_2i_D16C31_SAT(&(ptrInstance->MixerStream[0]),&(ptrInstance->MixerStream[1]), src, dst, n);
+ }
+ }
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (ptrInstance->MixerStream[0].CallbackSet)
+ {
+ if (Abs_32(pInstance1->Current-pInstance1->Target) < pInstance1->Delta)
+ {
+ pInstance1->Current = pInstance1->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance1->Target>>(16-pInstance1->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(&ptrInstance->MixerStream[0],TargetGain);
+ ptrInstance->MixerStream[0].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[0].pCallBack != 0)
+ {
+ (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
+ }
+ }
+ }
+ if (ptrInstance->MixerStream[1].CallbackSet)
+ {
+ if (Abs_32(pInstance2->Current-pInstance2->Target) < pInstance2->Delta)
+ {
+ pInstance2->Current = pInstance2->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance2->Target>>(16-pInstance2->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(&ptrInstance->MixerStream[1],TargetGain);
+ ptrInstance->MixerStream[1].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[1].pCallBack != 0)
+ {
+ (*ptrInstance->MixerStream[1].pCallBack) ( ptrInstance->MixerStream[1].pCallbackHandle, ptrInstance->MixerStream[1].pGeneralPurpose,ptrInstance->MixerStream[1].CallbackParam );
+ }
+ }
+ }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
new file mode 100755
index 0000000..cfb1239
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+#include "ScalarArithmetic.h"
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+/**********************************************************************************
+ FUNCTION LVMixer3_MIXSOFT_1ST_D16C31_SAT
+***********************************************************************************/
+
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ char HardMixing = TRUE;
+ LVM_INT32 TargetGain;
+ Mix_Private_st *pInstance=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if (pInstance->Current != pInstance->Target)
+ {
+ if(pInstance->Delta == 0x7FFFFFFF){
+ pInstance->Current = pInstance->Target;
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+ }else if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]),TargetGain);
+ }else{
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ if(pInstance->Shift!=0){
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,dst,n);
+ LVC_Core_MixSoft_1St_D16C31_WRA( &(ptrInstance->MixerStream[0]), dst, dst, n);
+ }
+ else
+ LVC_Core_MixSoft_1St_D16C31_WRA( &(ptrInstance->MixerStream[0]), src, dst, n);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing){
+ if (pInstance->Target == 0)
+ LoadConst_16(0, dst, n);
+ else if(pInstance->Shift!=0){
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance->Shift,src,dst,n);
+ if ((pInstance->Target>>16) != 0x7FFF)
+ Mult3s_16x16( dst, (LVM_INT16)(pInstance->Target>>16), dst, n );
+ }
+ else {
+ if ((pInstance->Target>>16) != 0x7FFF)
+ Mult3s_16x16( src, (LVM_INT16)(pInstance->Target>>16), dst, n );
+ else if(src!=dst)
+ Copy_16(src, dst, n);
+ }
+
+ }
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (ptrInstance->MixerStream[0].CallbackSet){
+ if (Abs_32(pInstance->Current-pInstance->Target) < pInstance->Delta){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+ LVC_Mixer_SetTarget(ptrInstance->MixerStream,TargetGain);
+ ptrInstance->MixerStream[0].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[0].pCallBack != 0){
+ (*ptrInstance->MixerStream[0].pCallBack) ( ptrInstance->MixerStream[0].pCallbackHandle, ptrInstance->MixerStream[0].pGeneralPurpose,ptrInstance->MixerStream[0].CallbackParam );
+ }
+ }
+ }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
new file mode 100755
index 0000000..6184736
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer_Private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION LVC_MixSoft_2St_D16C31_SAT.c
+***********************************************************************************/
+
+void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
+ const LVM_INT16 *src1,
+ LVM_INT16 *src2,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ Mix_Private_st *pInstance1=(Mix_Private_st *)(ptrInstance->MixerStream[0].PrivateParams);
+ Mix_Private_st *pInstance2=(Mix_Private_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if ((pInstance1->Current == pInstance1->Target)&&(pInstance1->Current == 0)){
+ LVC_MixSoft_1St_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[1]), src2, dst, n);
+ }
+ else if ((pInstance2->Current == pInstance2->Target)&&(pInstance2->Current == 0)){
+ LVC_MixSoft_1St_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[0]), src1, dst, n);
+ }
+ else if ((pInstance1->Current != pInstance1->Target) || (pInstance2->Current != pInstance2->Target))
+ {
+ LVC_MixSoft_1St_D16C31_SAT((LVMixer3_1St_st *)(&ptrInstance->MixerStream[0]), src1, dst, n);
+ LVC_MixInSoft_D16C31_SAT( (LVMixer3_1St_st *)(&ptrInstance->MixerStream[1]), src2, dst, n);
+ }
+ else{
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+ if(pInstance2->Shift!=0)
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance2->Shift,src2,src2,n);
+ if(pInstance1->Shift!=0)
+ {
+ Shift_Sat_v16xv16 ((LVM_INT16)pInstance1->Shift,src1,dst,n);
+ LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], dst, src2, dst, n);
+ }
+ else
+ LVC_Core_MixHard_2St_D16C31_SAT( &ptrInstance->MixerStream[0], &ptrInstance->MixerStream[1], src1, src2, dst, n);
+ }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
new file mode 100755
index 0000000..3b32e21
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __LVC_MIXER_H__
+#define __LVC_MIXER_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "LVM_Types.h"
+
+/**********************************************************************************
+ INSTANCE MEMORY TYPE DEFINITION
+***********************************************************************************/
+
+/* LVMixer3_st structure stores Instance parameters for one audio stream */
+typedef struct
+{
+ LVM_INT32 PrivateParams[4]; /* Private Instance params for Audio Stream */
+ LVM_INT16 CallbackSet; /* Boolean. Should be set by calling application each time the target value is updated */
+ LVM_INT16 CallbackParam; /* Parameter that will be used in the calback function */
+ void *pCallbackHandle; /* Pointer to the instance of the callback function */
+ void *pGeneralPurpose; /* Pointer for general purpose usage */
+ LVM_Callback pCallBack; /* Pointer to the callback function */
+} LVMixer3_st;
+
+typedef struct
+{
+ LVMixer3_st MixerStream[1]; /* Instance Params for one Audio Stream */
+} LVMixer3_1St_st;
+
+typedef struct
+{
+ LVMixer3_st MixerStream[2]; /* Instance Params for two Audio Streams */
+} LVMixer3_2St_st;
+
+typedef struct
+{
+ LVMixer3_st MixerStream[3]; /* Instance Params for three Audio Streams */
+} LVMixer3_3St_st;
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES (HIGH LEVEL FUNCTIONS)
+***********************************************************************************/
+
+/* Function names should be unique within first 16 characters */
+#define LVMixer3_MixSoft_1St_D16C31_SAT LVMixer3_1St_D16C31_SAT_MixSoft
+#define LVMixer3_MixInSoft_D16C31_SAT LVMixer3_D16C31_SAT_MixInSoft
+#define LVMixer3_MixSoft_2St_D16C31_SAT LVMixer3_2St_D16C31_SAT_MixSoft
+#define LVMixer3_MixSoft_3St_D16C31_SAT LVMixer3_3St_D16C31_SAT_MixSoft
+
+
+/*** General functions ************************************************************/
+
+/**********************************************************************************/
+/* This time constant calculation function assumes the mixer will be called with */
+/* large block sizes. When the block size is small, especially if less than 4, */
+/* then the calculation will give an incorrect value for alpha, see the mixer */
+/* documentation for further details. */
+/* ********************************************************************************/
+void LVC_Mixer_SetTarget( LVMixer3_st *pStream,
+ LVM_INT32 TargetGain);
+
+LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream);
+
+LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream);
+
+void LVC_Mixer_Init( LVMixer3_st *pStream,
+ LVM_INT32 TargetGain,
+ LVM_INT32 CurrentGain);
+
+void LVC_Mixer_SetTimeConstant( LVMixer3_st *pStream,
+ LVM_INT32 Tc_millisec,
+ LVM_Fs_en Fs,
+ LVM_INT16 NumChannels);
+
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
+ LVM_INT32 Tc_millisec,
+ LVM_Fs_en Fs,
+ LVM_INT16 NumChannels);
+
+/*** 16 bit functions *************************************************************/
+
+void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *pInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *pInstance,
+ LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *pInstance,
+ const LVM_INT16 *src1,
+ LVM_INT16 *src2,
+ LVM_INT16 *dst, /* dst cannot be equal to src2 */
+ LVM_INT16 n);
+
+/**********************************************************************************/
+/* For applying different gains to Left and right chennals */
+/* MixerStream[0] applies to Left channel */
+/* MixerStream[1] applies to Right channel */
+/* Gain values should not be more that 1.0 */
+/**********************************************************************************/
+void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st *pInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst, /* dst can be equal to src */
+ LVM_INT16 n); /* Number of stereo samples */
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/**********************************************************************************/
+
+#endif //#ifndef __LVC_MIXER_H__
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
new file mode 100755
index 0000000..09658ba
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetCurrent.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 839 $*/
+/* $Date: 2010-06-16 14:15:52 +0200 (Wed, 16 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVMixer3_GetCurrent */
+/* */
+/* DESCRIPTION: */
+/* This function returns the CurrentGain in Q16.15 format */
+/* */
+/* RETURNS: */
+/* CurrentGain - CurrentGain value in Q 16.15 format */
+/* */
+/************************************************************************/
+
+LVM_INT32 LVC_Mixer_GetCurrent( LVMixer3_st *pStream)
+{
+ LVM_INT32 CurrentGain;
+ Mix_Private_st *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+ CurrentGain=pInstance->Current>>(16-pInstance->Shift); // CurrentGain in Q16.15 format
+ return CurrentGain;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
new file mode 100755
index 0000000..ed2cf94
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 839 $*/
+/* $Date: 2010-06-16 14:15:52 +0200 (Wed, 16 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVMixer3_GetTarget */
+/* */
+/* DESCRIPTION: */
+/* This function returns the TargetGain in Q16.15 format */
+/* */
+/* RETURNS: */
+/* TargetGain - TargetGain value in Q 16.15 format */
+/* */
+/************************************************************************/
+
+LVM_INT32 LVC_Mixer_GetTarget( LVMixer3_st *pStream)
+{
+ LVM_INT32 TargetGain;
+ Mix_Private_st *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+
+ TargetGain=pInstance->Target>>(16-pInstance->Shift); // TargetGain in Q16.15 format
+
+ return TargetGain;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
new file mode 100755
index 0000000..c61e468
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Init.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVMixer3_Init */
+/* */
+/* DESCRIPTION: */
+/* This intialization function intializes the private instance */
+/* paramters for a given Audio Stream based on TargetGain and */
+/* CurrentGain */
+/* This function caclulates the "Shift" required to provide the */
+/* integer part of TargetGain and fractional gain values "Target" and */
+/* "Current" based on maximum(TargetGain,CurrentGain) */
+/* E.g. CurrentGain=1.9 and TargetGain=2.5 then based on */
+/* MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625 */
+/* Therefore integer gain of 4 is provided by Left Shift of 2 and */
+/* fraction gain is provided through Current=0.475 and Target=0.625 */
+/* PARAMETERS: */
+/* pStream - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/* Audio Stream */
+/* TargetGain - TargetGain value in Q 16.15 format */
+/* CurrentGain - CurrentGain value in Q 16.15 format */
+/* */
+/* RETURNS: */
+/* void */
+/* */
+/************************************************************************/
+
+void LVC_Mixer_Init( LVMixer3_st *pStream,
+ LVM_INT32 TargetGain,
+ LVM_INT32 CurrentGain)
+{
+ LVM_INT16 Shift=0;
+ LVM_INT32 MaxGain=TargetGain; // MaxGain is in Q16.15 format
+ Mix_Private_st *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+ if(CurrentGain>MaxGain)
+ MaxGain=CurrentGain; // MaxGain=max(CurrentGain,TargetGain)
+
+ MaxGain=MaxGain>>15; // MaxGain in Q31.0 format i.e Integer part only
+ while(MaxGain>0){ // Update Shift required to provide integer gain
+ Shift++;
+ MaxGain=MaxGain>>1;
+ }
+ pInstance->Target=TargetGain<<(16-Shift); // Update fractional gain Target
+ pInstance->Current=CurrentGain<<(16-Shift); // Update fractional gain Current
+ pInstance->Shift=Shift; // Update Shift
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
new file mode 100755
index 0000000..d61d670
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __LVC_MIXER_PRIVATE_H__
+#define __LVC_MIXER_PRIVATE_H__
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "LVC_Mixer.h"
+#include "VectorArithmetic.h"
+
+/* Instance parameter structure */
+typedef struct
+{
+ /* General */
+ LVM_INT32 Target; /* 32 bit number specifying fractional value of Target Gain */
+ LVM_INT32 Current; /* 32 bit number specifying fractional valude of Current Gain */
+ LVM_INT32 Shift; /* Left Shift for Integer part of Gain */
+ LVM_INT32 Delta; /* 32 bit number specifying the fractional value of Delta Gain */
+} Mix_Private_st;
+
+
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+#define LVCore_MixInSoft_D32C31_SAT LVCore_InSoft_D32C31_SAT
+#define LVCore_MixSoft_1St_D32C31_WRA LVCore_Soft_1St_D32C31_WRA
+#define LVCore_MixHard_2St_D32C31_SAT LVCore_Hard_2St_D32C31_SAT
+
+/**********************************************************************************
+ FUNCTION PROTOTYPES (LOW LEVEL SUBFUNCTIONS)
+***********************************************************************************/
+
+/*** 16 bit functions *************************************************************/
+
+void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *pInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *pInstance,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+void LVC_Core_MixHard_2St_D16C31_SAT( LVMixer3_st *pInstance1,
+ LVMixer3_st *pInstance2,
+ const LVM_INT16 *src1,
+ const LVM_INT16 *src2,
+ LVM_INT16 *dst,
+ LVM_INT16 n);
+
+/**********************************************************************************/
+/* For applying different gains to Left and right chennals */
+/* ptrInstance1 applies to Left channel */
+/* ptrInstance2 applies to Right channel */
+/* Gain values should not be more that 1.0 */
+/**********************************************************************************/
+
+void LVC_Core_MixSoft_1St_2i_D16C31_WRA( LVMixer3_st *ptrInstance1,
+ LVMixer3_st *ptrInstance2,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst, /* dst can be equal to src */
+ LVM_INT16 n); /* Number of stereo samples */
+
+/**********************************************************************************/
+/* For applying different gains to Left and right chennals */
+/* ptrInstance1 applies to Left channel */
+/* ptrInstance2 applies to Right channel */
+/* Gain values should not be more that 1.0 */
+/**********************************************************************************/
+void LVC_Core_MixHard_1St_2i_D16C31_SAT( LVMixer3_st *ptrInstance1,
+ LVMixer3_st *ptrInstance2,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst, /* dst can be equal to src */
+ LVM_INT16 n); /* Number of stereo samples */
+
+
+
+/*** 32 bit functions *************************************************************/
+
+void LVC_Core_MixInSoft_D32C31_SAT( LVMixer3_st *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void LVC_Core_MixSoft_1St_D32C31_WRA( LVMixer3_st *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+void LVC_Core_MixHard_2St_D32C31_SAT( LVMixer3_st *pInstance1,
+ LVMixer3_st *pInstance2,
+ const LVM_INT32 *src1,
+ const LVM_INT32 *src2,
+ LVM_INT32 *dst,
+ LVM_INT16 n);
+
+/**********************************************************************************/
+
+#endif //#ifndef __LVC_MIXER_PRIVATE_H__
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
new file mode 100755
index 0000000..4d3fe0c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTarget.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVMixer3_SetTarget */
+/* */
+/* DESCRIPTION: */
+/* This function updates the private instance parameters: Shift,Target,*/
+/* Current for a given Audio Stream based on new value of TargetGain */
+/* */
+/* This function caclulates the "Shift" required to provide the */
+/* integer part of TargetGain and fractional gain values "Target" and */
+/* "Current" based on maximum(TargetGain,CurrentGain) */
+/* E.g. CurrentGain=1.9 and TargetGain=2.5 then based on */
+/* MaxGain of 2.5, Shift = 2, Current=1.9/4=0.475, Target=2.5/4=0.625 */
+/* Therefore integer gain of 4 is provided by Left Shift of 2 and */
+/* fraction gain is provided through Current=0.475 and Target=0.625 */
+/* PARAMETERS: */
+/* pStream - ptr to Instance Parameter Structure LVMixer3_st */
+/* for an Audio Stream */
+/* TargetGain - TargetGain value in Q 16.15 format */
+/* */
+/* RETURNS: */
+/* void */
+/* */
+/************************************************************************/
+
+void LVC_Mixer_SetTarget(LVMixer3_st *pStream,
+ LVM_INT32 TargetGain)
+{
+ LVM_INT32 Shift=0;
+ LVM_INT32 CurrentGain;
+ LVM_INT32 MaxGain=TargetGain; // MaxGain is in Q16.15 format
+ Mix_Private_st *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+ CurrentGain=pInstance->Current>>(16-pInstance->Shift); // CurrentGain in Q16.15 format
+ if(CurrentGain>MaxGain)
+ MaxGain=CurrentGain; // MaxGain=max(CurrentGain,TargetGain)
+
+ MaxGain=MaxGain>>15; // MaxGain in Q31.0 format i.e Integer part only
+ while(MaxGain>0){ // Update Shift required to provide integer gain
+ Shift++;
+ MaxGain=MaxGain>>1;
+ }
+ pInstance->Target=TargetGain<<(16-Shift); // Update fractional gain Target
+ pInstance->Current=CurrentGain<<(16-Shift); // Update fractional gain Current
+ pInstance->Shift=Shift; // Update Shift
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
new file mode 100755
index 0000000..df0fd37
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_SetTimeConstant.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVMixer3_SetTimeConstant */
+/* */
+/* DESCRIPTION: */
+/* This function calculates the step change for fractional gain for a */
+/* given time constant, sample rate and num channels */
+/* Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) */
+/* in Q 0.31 format */
+/* */
+/* PARAMETERS: */
+/* pStream - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/* Audio Stream */
+/* Tc_millisec - TimeConstant i.e time required in milli second to */
+/* go from linear fractional gain of 0 to 0.99999999 */
+/* Fs - LVM_Fs_en enumerator for Sampling Frequency */
+/* NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo */
+/* */
+/* UPDATES: */
+/* Delta - the step change for fractional gain per 4 samples */
+/* in Q0.31 format for a given Time Constant, */
+/* Sample Rate and NumChannels */
+/* RETURNS: */
+/* void */
+/************************************************************************/
+
+void LVC_Mixer_SetTimeConstant(LVMixer3_st *pStream,
+ LVM_INT32 Tc_millisec,
+ LVM_Fs_en Fs,
+ LVM_INT16 NumChannels)
+{
+ LVM_INT32 DeltaTable[9]={1073741824,
+ 779132389,
+ 715827882,
+ 536870912,
+ 389566194,
+ 357913941,
+ 268435456,
+ 194783097,
+ 178956971};
+ Mix_Private_st *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+ LVM_INT32 Delta=DeltaTable[Fs];
+ Delta=Delta>>(NumChannels-1);
+
+ if(Tc_millisec==0)
+ Delta=0x7FFFFFFF;
+ else
+ Delta=Delta/Tc_millisec;
+
+ if(Delta==0)
+ Delta=1; // If Time Constant is so large that Delta is 0, assign minimum value to Delta
+
+ pInstance->Delta=Delta; // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
new file mode 100755
index 0000000..420af9a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_VarSlope_SetTimeConstant.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "LVC_Mixer_Private.h"
+
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVMixer3_VarSlope_SetTimeConstant */
+/* */
+/* DESCRIPTION: */
+/* This function calculates the step change for fractional gain for a */
+/* given time constant, sample rate and num channels */
+/* Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) */
+/* in Q 0.31 format */
+/* */
+/* PARAMETERS: */
+/* pStream - ptr to Instance Parameter Structure LVMixer3_st for an*/
+/* Audio Stream */
+/* Tc_millisec - TimeConstant i.e time required in milli second to */
+/* go from linear fractional gain of 0 to 0.99999999 */
+/* Fs - LVM_Fs_en enumerator for Sampling Frequency */
+/* NumChannels - Number of channels in Audio Stream 1=Mono, 2=Stereo */
+/* */
+/* UPDATES: */
+/* Delta - the step change for fractional gain per 4 samples */
+/* in Q0.31 format for a given Time Constant, */
+/* Sample Rate and NumChannels */
+/* RETURNS: */
+/* void */
+/************************************************************************/
+
+void LVC_Mixer_VarSlope_SetTimeConstant( LVMixer3_st *pStream,
+ LVM_INT32 Tc_millisec,
+ LVM_Fs_en Fs,
+ LVM_INT16 NumChannels)
+{
+ LVM_INT32 DeltaTable[9]={1073741824,
+ 779132389,
+ 715827882,
+ 536870912,
+ 389566194,
+ 357913941,
+ 268435456,
+ 194783097,
+ 178956971};
+ Mix_Private_st *pInstance=(Mix_Private_st *)pStream->PrivateParams;
+ LVM_INT32 Delta=DeltaTable[Fs];
+
+ LVM_INT32 Current;
+ LVM_INT32 Target;
+
+ Delta=Delta>>(NumChannels-1);
+
+ /* Get gain values */
+ Current = LVC_Mixer_GetCurrent( pStream );
+ Target = LVC_Mixer_GetTarget( pStream );
+
+ if (Current != Target)
+ {
+ Tc_millisec = Tc_millisec * 32767 / (Current - Target);
+ if (Tc_millisec<0) Tc_millisec = -Tc_millisec;
+
+ if(Tc_millisec==0)
+ Delta=0x7FFFFFFF;
+ else
+ Delta=Delta/Tc_millisec;
+
+ if(Delta==0)
+ Delta=1; // If Time Constant is so large that Delta is 0, assign minimum value to Delta
+ }
+ else
+ {
+ Delta =1; // Minimum value for proper call-backs (setting it to zero has some problems, to be corrected)
+ }
+
+
+ pInstance->Delta=Delta; // Delta=(2147483647*4*1000)/(NumChannels*SampleRate*Tc_millisec) in Q 0.31 format
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
new file mode 100755
index 0000000..37c199e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_HPF.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp27078 $*/
+/* $Revision: 762 $*/
+/* $Date: 2010-06-11 14:50:33 +0200 (vr, 11 jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* void LVM_FO_LPF( LVM_INT32 w , */
+/* FO_C32_Coefs_t *pCoeffs); */
+/* */
+/* */
+/* DESCRIPTION: */
+/* This function calculates the coefficient of first order low pass */
+/* filter. It uses the equations: */
+/* */
+/* B1 = (tan(w/2) - 1 ) / (tan(w/2) + 1 ) */
+/* A0 = (1 - B1) / 2 */
+/* A1 = A0 */
+/* */
+/* The value of B1 is then calculated directly from the value w by a */
+/* polynomial expansion using a 9th order polynomial. It uses the */
+/* following table of 32-bit integer polynomial coefficients: */
+/* */
+/* Coefficient Value */
+/* A0 -8388571 */
+/* A1 33547744 */
+/* A2 -66816791 */
+/* A3 173375308 */
+/* A4 -388437573 */
+/* A5 752975383 */
+/* A6 -1103016663 */
+/* A7 1121848567 */
+/* A8 -688078159 */
+/* A9 194669577 */
+/* A10 8 */
+/* */
+/* Y = (A0 + A1*X + A2*X2 + A3*X3 + ….. + AN*xN) << AN+1 */
+/* */
+/* */
+/* PARAMETERS: */
+/* */
+/* w Sample rate in radians, where: */
+/* w = 2 * Pi * Fc / Fs */
+/* Fc is the corner frequency in Hz */
+/* Fs is the sample rate in Hz */
+/* w is in Q2.29 format and data range is [0 Pi] */
+/* pCoeffs Points to the filter coefficients calculated here */
+/* in Q1.30 format */
+/* RETURNS: */
+/* */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_FO_HPF( LVM_INT32 w,
+ FO_C32_Coefs_t *pCoeffs)
+{
+ LVM_INT32 Y,Coefficients[13]={ -8388571,
+ 33547744,
+ -66816791,
+ 173375308,
+ -388437573,
+ 752975383,
+ -1103016663,
+ 1121848567,
+ -688078159,
+ 194669577,
+ 8,
+ 0,
+ 0};
+ Y=LVM_Polynomial( (LVM_UINT16)9,
+ Coefficients,
+ w);
+ pCoeffs->B1=-Y; /* Store -B1 in filter structure instead of B1!*/
+ /* A0=(1-B1)/2= B1/2 - 0.5*/
+ Y=Y>>1; /* A0=Y=B1/2*/
+ Y=Y-0x40000000; /* A0=Y=(B1/2 - 0.5)*/
+ MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15) /* Apply loss to avoid overflow*/
+ pCoeffs->A1=-pCoeffs->A0; /* Store A1=-A0*/
+
+ return 1;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
new file mode 100755
index 0000000..6c73d59
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_FO_LPF.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp27078 $*/
+/* $Revision: 762 $*/
+/* $Date: 2010-06-11 14:50:33 +0200 (vr, 11 jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "BIQUAD.h"
+#include "Filter.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* void LVM_FO_LPF( LVM_INT32 w , */
+/* FO_C32_Coefs_t *pCoeffs); */
+/* */
+/* */
+/* DESCRIPTION: */
+/* This function calculates the coefficient of first order low pass */
+/* filter. It uses the equations: */
+/* */
+/* B1 = (tan(w/2) - 1 ) / (tan(w/2) + 1 ) */
+/* A0 = (1 + B1) / 2 */
+/* A1 = A0 */
+/* */
+/* The value of B1 is then calculated directly from the value w by a */
+/* polynomial expansion using a 9th order polynomial. It uses the */
+/* following table of 32-bit integer polynomial coefficients: */
+/* */
+/* Coefficient Value */
+/* A0 -8388571 */
+/* A1 33547744 */
+/* A2 -66816791 */
+/* A3 173375308 */
+/* A4 -388437573 */
+/* A5 752975383 */
+/* A6 -1103016663 */
+/* A7 1121848567 */
+/* A8 -688078159 */
+/* A9 194669577 */
+/* A10 8 */
+/* */
+/* Y = (A0 + A1*X + A2*X2 + A3*X3 + ….. + AN*xN) << AN+1 */
+/* */
+/* */
+/* PARAMETERS: */
+/* */
+/* w Sample rate in radians, where: */
+/* w = 2 * Pi * Fc / Fs */
+/* Fc is the corner frequency in Hz */
+/* Fs is the sample rate in Hz */
+/* w is in Q2.29 format and data range is [0 Pi] */
+/* pCoeffs Points to the filter coefficients calculated here */
+/* in Q1.30 format */
+/* RETURNS: */
+/* */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_FO_LPF( LVM_INT32 w,
+ FO_C32_Coefs_t *pCoeffs)
+{
+ LVM_INT32 Y,Coefficients[13]={ -8388571,
+ 33547744,
+ -66816791,
+ 173375308,
+ -388437573,
+ 752975383,
+ -1103016663,
+ 1121848567,
+ -688078159,
+ 194669577,
+ 8};
+ Y=LVM_Polynomial( (LVM_UINT16)9,
+ Coefficients,
+ w);
+ pCoeffs->B1=-Y; // Store -B1 in filter structure instead of B1!
+ // A0=(1+B1)/2= B1/2 + 0.5
+ Y=Y>>1; // A0=Y=B1/2
+ Y=Y+0x40000000; // A0=Y=(B1/2 + 0.5)
+ MUL32x16INTO32(Y, FILTER_LOSS ,pCoeffs->A0 ,15) // Apply loss to avoid overflow
+ pCoeffs->A1=pCoeffs->A0;
+ return 1;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
new file mode 100755
index 0000000..1cc10db
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_GetOmega.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp27078 $*/
+/* $Revision: 762 $*/
+/* $Date: 2010-06-11 14:50:33 +0200 (vr, 11 jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "Filter.h"
+#include "LVM_Macros.h"
+
+/************************************************************************************/
+/* */
+/* Defines and Tables for 2*Pi/Fs */
+/* */
+/************************************************************************************/
+
+#define LVVDL_2PiBy_8000 1727108826 /* In Q41 format */
+#define LVVDL_2PiBy_11025 1253230894 /* In Q41 format */
+#define LVVDL_2PiBy_12000 1151405884 /* In Q41 format */
+
+#define LVVDL_2PiByFs_SHIFT1 12 /* Qformat shift for 8kHz, 11.025kHz and 12kHz i.e. 12=41-29 */
+#define LVVDL_2PiByFs_SHIFT2 13 /* Qformat shift for 16kHz, 22.050kHz and 24kHz i.e. 13=42-29 */
+#define LVVDL_2PiByFs_SHIFT3 14 /* Qformat shift for 32kHz, 44.1kHz and 48kHz i.e. 14=43-29 */
+
+const LVM_INT32 LVVDL_2PiOnFsTable[] = {LVVDL_2PiBy_8000 , /* 8kHz in Q41, 16kHz in Q42, 32kHz in Q43 */
+ LVVDL_2PiBy_11025, /* 11025 Hz in Q41, 22050Hz in Q42, 44100 Hz in Q43*/
+ LVVDL_2PiBy_12000}; /* 12kHz in Q41, 24kHz in Q42, 48kHz in Q43 */
+
+
+const LVM_INT32 LVVDL_2PiOnFsShiftTable[]={LVVDL_2PiByFs_SHIFT1 , /* 8kHz, 11025Hz, 12kHz */
+ LVVDL_2PiByFs_SHIFT2, /* 16kHz, 22050Hz, 24kHz*/
+ LVVDL_2PiByFs_SHIFT3}; /* 32kHz, 44100Hz, 48kHz */
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* LVM_GetOmega */
+/* */
+/* LVM_INT32 LVM_GetOmega(LVM_UINT16 Fc, */
+/* LVM_Fs_en Fs) */
+/* */
+/* DESCRIPTION: */
+/* This function calculates the value of w using Fc and Fs */
+/* */
+/* PARAMETERS: */
+/* */
+/* LVM_UINT16 Fc The corner frequency in Hz Q16.0 format */
+/* LVM_Fs_en Fs The SampleRate */
+/* RETURNS: */
+/* w=2*pi*Fc/Fs in Q2.29 format */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_GetOmega(LVM_UINT16 Fc,
+ LVM_Fs_en Fs)
+{
+ LVM_INT32 w;
+ MUL32x32INTO32((LVM_INT32)Fc,LVVDL_2PiOnFsTable[Fs%3],w,LVVDL_2PiOnFsShiftTable[Fs/3])
+ return w;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
new file mode 100755
index 0000000..00235e0
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_FilterCoeffs.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Mixer library tables */
+/* */
+/* Coefficients and table values for the mixer library, generated by the Matlab */
+/* Script: Mixer_GenerateCoeffs.m */
+/* */
+/************************************************************************************/
+
+#ifndef __LVM_MIXER_FILTER_COEFFS_H__
+#define __LVM_MIXER_FILTER_COEFFS_H__
+
+
+/************************************************************************************/
+/* */
+/* Alpha Time Constant table */
+/* */
+/************************************************************************************/
+
+#define Alpha_TableSize 50 /* The number of table entires */
+#define ALPHA_0 2147480769 /* Floating point Alpha = 0.999999 */
+#define ALPHA_1 2147479577 /* Floating point Alpha = 0.999998 */
+#define ALPHA_2 2147477892 /* Floating point Alpha = 0.999997 */
+#define ALPHA_3 2147475510 /* Floating point Alpha = 0.999996 */
+#define ALPHA_4 2147472141 /* Floating point Alpha = 0.999995 */
+#define ALPHA_5 2147467377 /* Floating point Alpha = 0.999992 */
+#define ALPHA_6 2147460642 /* Floating point Alpha = 0.999989 */
+#define ALPHA_7 2147451118 /* Floating point Alpha = 0.999985 */
+#define ALPHA_8 2147437651 /* Floating point Alpha = 0.999979 */
+#define ALPHA_9 2147418608 /* Floating point Alpha = 0.999970 */
+#define ALPHA_10 2147391683 /* Floating point Alpha = 0.999957 */
+#define ALPHA_11 2147353611 /* Floating point Alpha = 0.999939 */
+#define ALPHA_12 2147299779 /* Floating point Alpha = 0.999914 */
+#define ALPHA_13 2147223662 /* Floating point Alpha = 0.999879 */
+#define ALPHA_14 2147116037 /* Floating point Alpha = 0.999829 */
+#define ALPHA_15 2146963865 /* Floating point Alpha = 0.999758 */
+#define ALPHA_16 2146748712 /* Floating point Alpha = 0.999658 */
+#define ALPHA_17 2146444522 /* Floating point Alpha = 0.999516 */
+#define ALPHA_18 2146014472 /* Floating point Alpha = 0.999316 */
+#define ALPHA_19 2145406527 /* Floating point Alpha = 0.999033 */
+#define ALPHA_20 2144547188 /* Floating point Alpha = 0.998633 */
+#define ALPHA_21 2143332669 /* Floating point Alpha = 0.998067 */
+#define ALPHA_22 2141616514 /* Floating point Alpha = 0.997268 */
+#define ALPHA_23 2139192215 /* Floating point Alpha = 0.996139 */
+#define ALPHA_24 2135768939 /* Floating point Alpha = 0.994545 */
+#define ALPHA_25 2130937774 /* Floating point Alpha = 0.992295 */
+#define ALPHA_26 2124125153 /* Floating point Alpha = 0.989123 */
+#define ALPHA_27 2114529263 /* Floating point Alpha = 0.984654 */
+#define ALPHA_28 2101034612 /* Floating point Alpha = 0.978370 */
+#define ALPHA_29 2082100030 /* Floating point Alpha = 0.969553 */
+#define ALPHA_30 2055617398 /* Floating point Alpha = 0.957221 */
+#define ALPHA_31 2018744824 /* Floating point Alpha = 0.940051 */
+#define ALPHA_32 1967733015 /* Floating point Alpha = 0.916297 */
+#define ALPHA_33 1897794587 /* Floating point Alpha = 0.883729 */
+#define ALPHA_34 1803123234 /* Floating point Alpha = 0.839645 */
+#define ALPHA_35 1677262220 /* Floating point Alpha = 0.781036 */
+#define ALPHA_36 1514142675 /* Floating point Alpha = 0.705078 */
+#define ALPHA_37 1310197875 /* Floating point Alpha = 0.610108 */
+#define ALPHA_38 1067813480 /* Floating point Alpha = 0.497239 */
+#define ALPHA_39 799601371 /* Floating point Alpha = 0.372343 */
+#define ALPHA_40 531183049 /* Floating point Alpha = 0.247351 */
+#define ALPHA_41 297904007 /* Floating point Alpha = 0.138722 */
+#define ALPHA_42 131499768 /* Floating point Alpha = 0.061234 */
+#define ALPHA_43 41375282 /* Floating point Alpha = 0.019267 */
+#define ALPHA_44 8065899 /* Floating point Alpha = 0.003756 */
+#define ALPHA_45 799076 /* Floating point Alpha = 0.000372 */
+#define ALPHA_46 30398 /* Floating point Alpha = 0.000014 */
+#define ALPHA_47 299 /* Floating point Alpha = 0.000000 */
+#define ALPHA_48 0 /* Floating point Alpha = 0.000000 */
+#define ALPHA_49 0 /* Floating point Alpha = 0.000000 */
+#define ALPHA_50 0 /* Floating point Alpha = 0.000000 */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
new file mode 100755
index 0000000..db6975a
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Mixer_TimeConstant.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "Mixer.h"
+#include "LVM_Mixer_FilterCoeffs.h"
+
+
+/************************************************************************/
+/* FUNCTION: */
+/* LVM_Mix_GetTimeConstant */
+/* */
+/* DESCRIPTION: */
+/* This function calculates the filter coefficient using the following */
+/* equation: */
+/* Alpha = exp(ln(0.1)/ (tc * Update + 1.0)) */
+/* */
+/* This is to be used with the follow first order filter, called at a */
+/* rate of Update times a second. tc is the required time constant in */
+/* units of 100us. */
+/* */
+/* Output(n) = Alpha * Output(n-1) + (1 - Alpha) * Target(n) */
+/* */
+/* The function assumes the block size is large, i.e. the update rate */
+/* is approximately a fixed, and correct factor of the value of Fs */
+/* given in the call. This is especially not true when the block size */
+/* is very small, see the mixer documentation for further details. */
+/* */
+/* The function does not support all possible combinations of input */
+/* values: */
+/* */
+/* 1. NumChannels is limited to the values 1 (Mono) and 2 (Stereo) */
+/* 2. The product tc * Fs is limited approximately to the range */
+/* 8 < (tc * Fs) < 2^35 */
+/* */
+/* PARAMETERS: */
+/* tc - the time constant in 100us steps, i.e. 10 = 1ms */
+/* Fs - the filter update rate in Hz */
+/* NumChannels - Number of channels 1=Mono, 2=Stereo */
+/* */
+/* RETURNS: */
+/* Alpha - the filter coefficient Q31 format */
+/* */
+/************************************************************************/
+
+LVM_UINT32 LVM_Mixer_TimeConstant(LVM_UINT32 tc,
+ LVM_UINT16 Fs,
+ LVM_UINT16 NumChannels)
+{
+
+ LVM_UINT32 Product;
+ LVM_INT16 Interpolate;
+ LVM_UINT16 Shift;
+ LVM_INT32 Diff;
+ LVM_UINT32 Table[] = {ALPHA_0, /* Log spaced look-up table */
+ ALPHA_1,
+ ALPHA_2,
+ ALPHA_3,
+ ALPHA_4,
+ ALPHA_5,
+ ALPHA_6,
+ ALPHA_7,
+ ALPHA_8,
+ ALPHA_9,
+ ALPHA_10,
+ ALPHA_11,
+ ALPHA_12,
+ ALPHA_13,
+ ALPHA_14,
+ ALPHA_15,
+ ALPHA_16,
+ ALPHA_17,
+ ALPHA_18,
+ ALPHA_19,
+ ALPHA_20,
+ ALPHA_21,
+ ALPHA_22,
+ ALPHA_23,
+ ALPHA_24,
+ ALPHA_25,
+ ALPHA_26,
+ ALPHA_27,
+ ALPHA_28,
+ ALPHA_29,
+ ALPHA_30,
+ ALPHA_31,
+ ALPHA_32,
+ ALPHA_33,
+ ALPHA_34,
+ ALPHA_35,
+ ALPHA_36,
+ ALPHA_37,
+ ALPHA_38,
+ ALPHA_39,
+ ALPHA_40,
+ ALPHA_41,
+ ALPHA_42,
+ ALPHA_43,
+ ALPHA_44,
+ ALPHA_45,
+ ALPHA_46,
+ ALPHA_47,
+ ALPHA_48,
+ ALPHA_49,
+ ALPHA_50};
+
+
+ /* Calculate the product of the time constant and the sample rate */
+ Product = ((tc >> 16) * (LVM_UINT32)Fs) << 13; /* Stereo value */
+ Product = Product + (((tc & 0x0000FFFF) * (LVM_UINT32)Fs) >> 3);
+
+ if (NumChannels == 1)
+ {
+ Product = Product >> 1; /* Mono value */
+ }
+
+ /* Normalize to get the table index and interpolation factor */
+ for (Shift=0; Shift<((Alpha_TableSize-1)/2); Shift++)
+ {
+ if ((Product & 0x80000000)!=0)
+ {
+ break;
+ }
+
+ Product = Product << 1;
+ }
+ Shift = (LVM_UINT16)((Shift << 1));
+
+ if ((Product & 0x40000000)==0)
+ {
+ Shift++;
+ }
+
+ Interpolate = (LVM_INT16)((Product >> 15) & 0x00007FFF);
+
+ Diff = (LVM_INT32)(Table[Shift] - Table[Shift+1]);
+ MUL32x16INTO32(Diff,Interpolate,Diff,15)
+ Product = Table[Shift+1] + (LVM_UINT32)Diff;
+
+ return Product;
+}
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
new file mode 100755
index 0000000..b8cf4b4
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Polynomial.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* LVM_Polynomial */
+/* */
+/* DESCRIPTION: */
+/* This function performs polynomial expansion */
+/* Y = (A0 + A1*X + A2*X2 + A3*X3 + ….. + AN*xN) << AN+1 */
+/* */
+/* LVM_INT32 LVM_Polynomial(LVM_UINT16 N, */
+/* LVM_INT32 *pCoefficients, */
+/* LVM_INT32 X) */
+/* */
+/* PARAMETERS: */
+/* */
+/* N is the polynomial order */
+/* pCoefficients is the ptr to polynomial coefficients A0,A1.. in Q.31 */
+/* X is the input variable */
+/* */
+/* RETURNS: */
+/* The result of the polynomial expansion in Q1.31 format */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_Polynomial(LVM_UINT16 N,
+ LVM_INT32 *pCoefficients,
+ LVM_INT32 X)
+{
+ LVM_INT32 i;
+ LVM_INT32 Y,A,XTemp,Temp,sign;
+
+ Y=*pCoefficients; /* Y=A0*/
+ pCoefficients++;
+
+ if((LVM_UINT32)X==0x80000000)
+ {
+ Temp=-1;
+ sign=Temp;
+ for(i=1;i<=N;i++)
+ {
+ Y+=((*pCoefficients)*sign);
+ pCoefficients++;
+ sign*=Temp;
+ }
+
+
+ }
+ else
+ {
+ XTemp=X;
+ for(i=N-1;i>=0;i--)
+ {
+ A=*pCoefficients;
+ pCoefficients++;
+
+ MUL32x32INTO32(A,XTemp,Temp,31)
+ Y+=Temp;
+
+ MUL32x32INTO32(XTemp,X,Temp,31)
+ XTemp=Temp;
+ }
+ }
+ A=*pCoefficients;
+ pCoefficients++;
+
+ if(A<0)
+ {
+ A=Abs_32(A);
+ Y=Y>>A;
+ }
+ else
+ {
+ Y = Y<<A;
+ }
+ return Y;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Power10.c b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
new file mode 100755
index 0000000..9a3f632
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Power10.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Macros.h"
+#include "ScalarArithmetic.h"
+#include "Filter.h"
+
+
+/*-------------------------------------------------------------------------*/
+/* FUNCTION: */
+/* LVM_Power10 */
+/* */
+/* DESCRIPTION: */
+/* This function calculates 10X using an 11th order polynomial. It uses */
+/* the following table of 32-bit integer polynomial coefficients: */
+/* */
+/* Coefficient Value */
+/* A0 67102543 */
+/* A1 309032995 */
+/* A2 712096127 */
+/* A3 1092797331 */
+/* A4 1251625137 */
+/* A5 1154649460 */
+/* A6 915654800 */
+/* A7 597883683 */
+/* A8 284378230 */
+/* A9 150262097 */
+/* A10 124894471 */
+/* A11 50477244 */
+/* A12 -2 */
+/* */
+/* Y = (A0 + A1*X + A2*X2 + A3*X3 + ….. + AN*xN) << AN+1 */
+/* */
+/* */
+/* PARAMETERS: */
+/* */
+/* X is the input variable in Q2.30 format */
+/* */
+/* RETURNS: */
+/* The result of the 10x expansion in Q8.24 format */
+/*-------------------------------------------------------------------------*/
+
+LVM_INT32 LVM_Power10(LVM_INT32 X)
+{
+ LVM_INT32 Y,Coefficients[13]={ 16775636,
+ 77258249,
+ 178024032,
+ 273199333,
+ 312906284,
+ 288662365,
+ 228913700,
+ 149470921,
+ 71094558,
+ 37565524,
+ 31223618,
+ 12619311,
+ 0};
+ Y=LVM_Polynomial((LVM_UINT16)11,
+ Coefficients,
+ X);
+ return Y;
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer.c b/media/libeffects/lvm/lib/Common/src/LVM_Timer.c
new file mode 100755
index 0000000..d49aadc
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: My Project */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/****************************************************************************************/
+/* INCLUDE FILES */
+/****************************************************************************************/
+
+#include "LVM_Timer.h"
+#include "LVM_Timer_Private.h"
+
+/****************************************************************************************/
+/* TIMER FUNCTION */
+/****************************************************************************************/
+
+void LVM_Timer ( LVM_Timer_Instance_t *pInstance,
+ LVM_INT16 BlockSize ){
+
+ LVM_Timer_Instance_Private_t *pInstancePr;
+ pInstancePr = (LVM_Timer_Instance_Private_t *)pInstance;
+
+ if (pInstancePr->TimerArmed){
+ pInstancePr->RemainingTimeInSamples -= BlockSize;
+ if (pInstancePr->RemainingTimeInSamples <= 0){
+ pInstancePr->TimerArmed = 0;
+ (*pInstancePr->pCallBack) ( pInstancePr->pCallbackInstance,
+ pInstancePr->pCallBackParams,
+ pInstancePr->CallBackParam );
+ }
+ }
+}
+
+/****************************************************************************************/
+/* END OF FILE */
+/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
new file mode 100755
index 0000000..e473038
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Init.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: My Project */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/****************************************************************************************/
+/* INCLUDE FILES */
+/****************************************************************************************/
+
+#include "LVM_Timer.h"
+#include "LVM_Timer_Private.h"
+#include "LVM_Macros.h"
+
+/****************************************************************************************/
+/* DEFINITIONS */
+/****************************************************************************************/
+
+#define OneOverThousandInQ24 16777
+
+/****************************************************************************************/
+/* INIT FUNCTION */
+/****************************************************************************************/
+
+void LVM_Timer_Init ( LVM_Timer_Instance_t *pInstance,
+ LVM_Timer_Params_t *pParams ){
+
+ LVM_Timer_Instance_Private_t *pInstancePr;
+ pInstancePr = (LVM_Timer_Instance_Private_t *)pInstance;
+
+ pInstancePr->CallBackParam = pParams->CallBackParam;
+ pInstancePr->pCallBackParams = pParams->pCallBackParams;
+ pInstancePr->pCallbackInstance = pParams->pCallbackInstance;
+ pInstancePr->pCallBack = pParams->pCallBack;
+ pInstancePr->TimerArmed = 1;
+
+ MUL32x16INTO32(pParams->SamplingRate,OneOverThousandInQ24,pInstancePr->RemainingTimeInSamples,16); /* (Q0 * Q24) >>16 into Q8*/
+ MUL32x16INTO32(pInstancePr->RemainingTimeInSamples,pParams->TimeInMs,pInstancePr->RemainingTimeInSamples,8); /* (Q8 * Q0) >>8 into Q0*/
+}
+
+/****************************************************************************************/
+/* END OF FILE */
+/****************************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
new file mode 100755
index 0000000..04d5af6
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LVM_Timer_Private.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: My Project */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#ifndef LVM_TIMER_PRIVATE_H
+#define LVM_TIMER_PRIVATE_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#include "LVM_Types.h"
+
+/****************************************************************************************/
+/* TYPE DEFINITIONS */
+/****************************************************************************************/
+
+typedef struct
+{
+ LVM_INT32 RemainingTimeInSamples;
+ LVM_INT32 CallBackParam;
+ LVM_INT32 *pCallBackParams;
+ void *pCallbackInstance;
+ void (*pCallBack)(void*,void*,LVM_INT32);
+ LVM_INT16 TimerArmed; /* Boolean, true between init and callback */
+
+} LVM_Timer_Instance_Private_t;
+
+/****************************************************************************************/
+/* END OF HEADER */
+/****************************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LVM_TIMER_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_16.c b/media/libeffects/lvm/lib/Common/src/LoadConst_16.c
new file mode 100755
index 0000000..bc2735f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_16.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION LoadConst_16
+***********************************************************************************/
+
+void LoadConst_16(const LVM_INT16 val,
+ LVM_INT16 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT16 ii;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = val;
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LoadConst_32.c b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
new file mode 100755
index 0000000..19d5d4e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/LoadConst_32.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION LoadConst_32
+***********************************************************************************/
+
+void LoadConst_32(const LVM_INT32 val,
+ LVM_INT32 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT16 ii;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = val;
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
new file mode 100755
index 0000000..1949f3c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MSTo2i_Sat_16x16.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION MSTO2I_SAT_16X16
+***********************************************************************************/
+
+void MSTo2i_Sat_16x16(const LVM_INT16 *srcM,
+ const LVM_INT16 *srcS,
+ LVM_INT16 *dst,
+ LVM_INT16 n )
+{
+ LVM_INT32 temp,mVal,sVal;
+ LVM_INT16 ii;
+
+
+ for (ii = n; ii != 0; ii--)
+ {
+ mVal=(LVM_INT32)*srcM;
+ srcM++;
+
+ sVal=(LVM_INT32)*srcS;
+ srcS++;
+
+ temp = mVal + sVal;
+
+ if (temp > 0x00007FFF)
+ {
+ *dst = 0x7FFF;
+ }
+ else if (temp < -0x00008000)
+ {
+ *dst = - 0x8000;
+ }
+ else
+ {
+ *dst = (LVM_INT16)temp;
+ }
+ dst++;
+
+ temp = mVal - sVal;
+
+ if (temp > 0x00007FFF)
+ {
+ *dst = 0x7FFF;
+ }
+ else if (temp < -0x00008000)
+ {
+ *dst = - 0x8000;
+ }
+ else
+ {
+ *dst = (LVM_INT16)temp;
+ }
+ dst++;
+ }
+
+ return;
+}
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c
new file mode 100755
index 0000000..ef04ae8
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_16x16.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ %created_by: sra % (CM/S)
+ %name: Mac3s_Sat_16x16.c % (CM/S)
+ %version: 1 % (CM/S)
+ %date_created: Fri Nov 13 12:07:13 2009 % (CM/S)
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION Mac3S_16X16
+***********************************************************************************/
+
+void Mac3s_Sat_16x16( const LVM_INT16 *src,
+ const LVM_INT16 val,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT16 srcval;
+ LVM_INT32 Temp,dInVal;
+
+
+ for (ii = n; ii != 0; ii--)
+ {
+ srcval=*src;
+ src++;
+
+ Temp = (srcval *val)>>15;
+
+ dInVal = (LVM_INT32)*dst;
+
+ Temp = Temp + dInVal;
+
+ if (Temp > 0x00007FFF)
+ {
+ *dst = 0x7FFF;
+ }
+ else if (Temp < -0x00008000)
+ {
+ *dst = - 0x8000;
+ }
+ else
+ {
+ *dst = (LVM_INT16)Temp;
+ }
+
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
new file mode 100755
index 0000000..746a273
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+ FUNCTION MAC3S_16X16
+***********************************************************************************/
+
+void Mac3s_Sat_32x16( const LVM_INT32 *src,
+ const LVM_INT16 val,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT32 srcval,temp, dInVal, dOutVal;
+
+
+ for (ii = n; ii != 0; ii--)
+ {
+ srcval=*src;
+ src++;
+
+ MUL32x16INTO32(srcval,val,temp,15)
+
+ dInVal = *dst;
+ dOutVal = temp + dInVal;
+
+
+ if ((((dOutVal ^ temp) & (dOutVal ^ dInVal)) >> 31)!=0) /* overflow / underflow */
+ {
+ if(temp<0)
+ {
+ dOutVal=0x80000000l;
+ }
+ else
+ {
+ dOutVal=0x7FFFFFFFl;
+ }
+ }
+
+ *dst = dOutVal;
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
+
+
+
diff --git a/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
new file mode 100755
index 0000000..36de6c1
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixInSoft_D32C31_SAT.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+/**********************************************************************************
+ FUNCTION MIXINSOFT_D32C31_SAT
+***********************************************************************************/
+
+void MixInSoft_D32C31_SAT( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ char HardMixing = TRUE;
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if (pInstance->Current != pInstance->Target)
+ {
+ if(pInstance->Alpha == 0){
+ pInstance->Current = pInstance->Target;
+ }else if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+ (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ }else{
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ Core_MixInSoft_D32C31_SAT( pInstance, src, dst, n);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing){
+ if (pInstance->Target != 0){ /* Nothing to do in case Target = 0 */
+ if ((pInstance->Target>>16) == 0x7FFF)
+ Add2_Sat_32x32( src, dst, n );
+ else{
+ Core_MixInSoft_D32C31_SAT( pInstance, src, dst, n);
+ pInstance->Current = pInstance->Target; /* In case the core function would have changed the Current value */
+ }
+ }
+ }
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+ /* Call back before the hard mixing, because in this case, hard mixing makes
+ use of the core soft mix function which can change the Current value! */
+
+ if (pInstance->CallbackSet){
+ if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+ (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ pInstance->CallbackSet = FALSE;
+ if (pInstance->pCallBack != 0){
+ (*pInstance->pCallBack) ( pInstance->pCallbackHandle, pInstance->pGeneralPurpose,pInstance->CallbackParam );
+ }
+ }
+ }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
new file mode 100755
index 0000000..5cf1a29
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_1St_D32C31_WRA.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+
+
+/**********************************************************************************
+ FUNCTION MIXSOFT_1ST_D32C31_WRA
+***********************************************************************************/
+
+void MixSoft_1St_D32C31_WRA( Mix_1St_Cll_t *pInstance,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ char HardMixing = TRUE;
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if (pInstance->Current != pInstance->Target)
+ {
+ if(pInstance->Alpha == 0){
+ pInstance->Current = pInstance->Target;
+ }else if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+ (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ }else{
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ Core_MixSoft_1St_D32C31_WRA( pInstance, src, dst, n);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing){
+ if (pInstance->Target == 0)
+ LoadConst_32(0, dst, n);
+ else if ((pInstance->Target>>16) == 0x7FFF){
+ if (src != dst)
+ Copy_16((LVM_INT16*)src, (LVM_INT16*)dst, (LVM_INT16)(n * 2));
+ }
+ else
+ Mult3s_32x16( src, (LVM_INT16)(pInstance->Current>>16), dst, n );
+ }
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (pInstance->CallbackSet){
+ if ((pInstance->Current-pInstance->Target <POINT_ZERO_ONE_DB)&&
+ (pInstance->Current-pInstance->Target > -POINT_ZERO_ONE_DB)){
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. Make them equal. */
+ pInstance->CallbackSet = FALSE;
+ if (pInstance->pCallBack != 0){
+ (*pInstance->pCallBack) ( pInstance->pCallbackHandle, pInstance->pGeneralPurpose,pInstance->CallbackParam );
+ }
+ }
+ }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
new file mode 100755
index 0000000..83f95ac
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MixSoft_2St_D32C31_SAT.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $*/
+/* $Revision: 1316 $*/
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer_private.h"
+#include "VectorArithmetic.h"
+
+
+/**********************************************************************************
+ FUNCTION MIXSOFT_2ST_D32C31_SAT
+***********************************************************************************/
+
+void MixSoft_2St_D32C31_SAT( Mix_2St_Cll_t *pInstance,
+ const LVM_INT32 *src1,
+ const LVM_INT32 *src2,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+
+ if(n<=0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if ((pInstance->Current1 != pInstance->Target1) || (pInstance->Current2 != pInstance->Target2))
+ {
+ MixSoft_1St_D32C31_WRA( (Mix_1St_Cll_t*) pInstance, src1, dst, n);
+ MixInSoft_D32C31_SAT( (void *) &pInstance->Alpha2, /* Cast to void: no dereferencing in function*/
+ src2, dst, n);
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ else
+ {
+ if (pInstance->Current1 == 0)
+ MixSoft_1St_D32C31_WRA( (void *) &pInstance->Alpha2, /* Cast to void: no dereferencing in function*/
+ src2, dst, n);
+ else if (pInstance->Current2 == 0)
+ MixSoft_1St_D32C31_WRA( (Mix_1St_Cll_t*) pInstance, src1, dst, n);
+ else
+ Core_MixHard_2St_D32C31_SAT( pInstance, src1, src2, dst, n);
+ }
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mixer_private.h b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
new file mode 100755
index 0000000..d012548
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mixer_private.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __MIXER_PRIVATE_H__
+#define __MIXER_PRIVATE_H__
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "Mixer.h"
+
+#define POINT_ZERO_ONE_DB 2473805 /* 0.01 dB on a full scale signal = (10^(0.01/20) -1) * 2^31 */
+
+/**********************************************************************************
+ DEFINITIONS
+***********************************************************************************/
+
+/**********************************************************************************/
+
+#endif //#ifndef __MIXER_PRIVATE_H__
+
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c
new file mode 100755
index 0000000..b053e55
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_16.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION MonoTo2I_16
+***********************************************************************************/
+
+void MonoTo2I_16( const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ src += (n-1);
+ dst += ((n*2)-1);
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = *src;
+ dst--;
+
+ *dst = *src;
+ dst--;
+ src--;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
new file mode 100755
index 0000000..e8164bb
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/MonoTo2I_32.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION MonoTo2I_32
+***********************************************************************************/
+
+void MonoTo2I_32( const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ src += (n-1);
+ dst += ((n*2)-1);
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = *src;
+ dst--;
+
+ *dst = *src;
+ dst--;
+ src--;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
new file mode 100755
index 0000000..ee83524
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Mult3s_32x16.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+#include "LVM_Macros.h"
+
+/**********************************************************************************
+FUNCTION MULT3S_16X16
+***********************************************************************************/
+
+void Mult3s_32x16( const LVM_INT32 *src,
+ const LVM_INT16 val,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT32 srcval,temp;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ srcval=*src;
+ src++;
+
+ MUL32x16INTO32(srcval,val,temp,15)
+
+ *dst = temp;
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
new file mode 100755
index 0000000..1428777
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/NonLinComp_D16.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "CompLim_private.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: NonLinComp_D16 */
+/* */
+/* DESCRIPTION: */
+/* Non-linear compression by companding. The function works on a sample by sample */
+/* basis by increasing the level near the zero crossing. This gives a ttrade-off */
+/* between THD and compression. It uses the equation: */
+/* */
+/* Output = Input + K * (Input - Input^2) if Input > 0 */
+/* = Input + K * (Input + Input^2) if Input <= 0 */
+/* */
+/* The value of K controls the amount of compression and as a side effect the amount */
+/* distortion introduced. The amount of compression is signal dependent and the values */
+/* given below are approximate. */
+/* */
+/* Gain (fractional) Gain (integer) Compression Pk-Pk THD */
+/* 1.0 32767 +6dB 16dB */
+/* 0.78 25559 +5dB 19dB */
+/* 0.6 19661 +4dB 21dB */
+/* 0.41 13435 +3dB 24dB */
+/* 0.26 8520 +2dB 28dB */
+/* 0.12 3932 +1dB 34dB */
+/* 0.0 0 +0dB 98dB */
+/* */
+/* PARAMETERS: */
+/* Gain - compression control parameter */
+/* pDataIn - pointer to the input data buffer */
+/* pDataOut - pointer to the output data buffer */
+/* BlockLength - number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void NonLinComp_D16(LVM_INT16 Gain,
+ LVM_INT16 *pDataIn,
+ LVM_INT16 *pDataOut,
+ LVM_INT32 BlockLength)
+{
+
+ LVM_INT16 Sample; /* Input samples */
+ LVM_INT32 SampleNo; /* Sample index */
+ LVM_INT16 Temp;
+
+
+ /*
+ * Process a block of samples
+ */
+ for(SampleNo = 0; SampleNo<BlockLength; SampleNo++)
+ {
+
+ /*
+ * Read the input
+ */
+ Sample = *pDataIn;
+ pDataIn++;
+
+
+ /*
+ * Apply the compander, this compresses the signal at the expense of
+ * harmonic distortion. The amount of compression is control by the
+ * gain factor
+ */
+ if ((LVM_INT32)Sample != -32768)
+ {
+ Temp = (LVM_INT16)((Sample * Sample) >> 15);
+ if(Sample >0)
+ {
+ Sample = (LVM_INT16)(Sample + ((Gain * (Sample - Temp)) >> 15));
+ }
+ else
+ {
+ Sample = (LVM_INT16)(Sample + ((Gain * (Sample + Temp)) >> 15));
+ }
+ }
+
+
+ /*
+ * Save the output
+ */
+ *pDataOut = Sample;
+ pDataOut++;
+
+
+ }
+
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
new file mode 100755
index 0000000..06cfe88
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q14 format
+ pBiquadState->coefs[3] is Gain, in Q11 format
+
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR,ynLO,ynRO,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ /* ynL= (A0 (Q14) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>14) in Q0*/
+ templ=(*pDataIn)-pBiquadState->pDelays[2];
+ MUL32x16INTO32(templ,pBiquadState->coefs[0],ynL,14)
+
+ /* ynL+= ((-B2 (Q14) * y(n-2)L (Q0) ) >>14) in Q0*/
+ MUL32x16INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[1],templ,14)
+ ynL+=templ;
+
+ /* ynL+= ((-B1 (Q14) * y(n-1)L (Q0) ) >>14) in Q0 */
+ MUL32x16INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[2],templ,14)
+ ynL+=templ;
+
+ /* ynLO= ((Gain (Q11) * ynL (Q0))>>11) in Q0*/
+ MUL32x16INTO32(ynL,pBiquadState->coefs[3],ynLO,11)
+
+ /* ynLO=( ynLO(Q0) + x(n)L (Q0) ) in Q0*/
+ ynLO+= (*pDataIn);
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ /* ynR= (A0 (Q14) * (x(n)R (Q0) - x(n-2)R (Q0) ) >>14) in Q0*/
+ templ=(*(pDataIn+1))-pBiquadState->pDelays[3];
+ MUL32x16INTO32(templ,pBiquadState->coefs[0],ynR,14)
+
+ /* ynR+= ((-B2 (Q14) * y(n-2)R (Q0) ) >>14) in Q0*/
+ MUL32x16INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[1],templ,14)
+ ynR+=templ;
+
+ /* ynR+= ((-B1 (Q14) * y(n-1)R (Q0) ) >>14) in Q0 */
+ MUL32x16INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[2],templ,14)
+ ynR+=templ;
+
+ /* ynRO= ((Gain (Q11) * ynR (Q0))>>11) in Q0*/
+ MUL32x16INTO32(ynR,pBiquadState->coefs[3],ynRO,11)
+
+ /* ynRO=( ynRO(Q0) + x(n)R (Q0) ) in Q0*/
+ ynRO+= (*(pDataIn+1));
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+ pBiquadState->pDelays[5]=ynR; /* Update y(n-1)R in Q0*/
+ pBiquadState->pDelays[4]=ynL; /* Update y(n-1)L in Q0*/
+ pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+ pDataIn++;
+ pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut=ynLO; /* Write Left output in Q0*/
+ pDataOut++;
+ *pDataOut=ynRO; /* Write Right ouput in Q0*/
+ pDataOut++;
+
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
new file mode 100755
index 0000000..5b78f62
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C30G11_TRC_WRA_01.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+#include "LVM_Macros.h"
+
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A0,
+ pBiquadState->coefs[1] is -B2,
+ pBiquadState->coefs[2] is -B1, these are in Q30 format
+ pBiquadState->coefs[3] is Gain, in Q11 format
+
+
+ DELAYS-
+ pBiquadState->pDelays[0] is x(n-1)L in Q0 format
+ pBiquadState->pDelays[1] is x(n-1)R in Q0 format
+ pBiquadState->pDelays[2] is x(n-2)L in Q0 format
+ pBiquadState->pDelays[3] is x(n-2)R in Q0 format
+ pBiquadState->pDelays[4] is y(n-1)L in Q0 format
+ pBiquadState->pDelays[5] is y(n-1)R in Q0 format
+ pBiquadState->pDelays[6] is y(n-2)L in Q0 format
+ pBiquadState->pDelays[7] is y(n-2)R in Q0 format
+***************************************************************************/
+void PK_2I_D32F32C30G11_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
+ LVM_INT32 *pDataIn,
+ LVM_INT32 *pDataOut,
+ LVM_INT16 NrSamples)
+ {
+ LVM_INT32 ynL,ynR,ynLO,ynRO,templ;
+ LVM_INT16 ii;
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+
+ for (ii = NrSamples; ii != 0; ii--)
+ {
+
+
+ /**************************************************************************
+ PROCESSING OF THE LEFT CHANNEL
+ ***************************************************************************/
+ /* ynL= (A0 (Q30) * (x(n)L (Q0) - x(n-2)L (Q0) ) >>30) in Q0*/
+ templ=(*pDataIn)-pBiquadState->pDelays[2];
+ MUL32x32INTO32(templ,pBiquadState->coefs[0],ynL,30)
+
+ /* ynL+= ((-B2 (Q30) * y(n-2)L (Q0) ) >>30) in Q0*/
+ MUL32x32INTO32(pBiquadState->pDelays[6],pBiquadState->coefs[1],templ,30)
+ ynL+=templ;
+
+ /* ynL+= ((-B1 (Q30) * y(n-1)L (Q0) ) >>30) in Q0 */
+ MUL32x32INTO32(pBiquadState->pDelays[4],pBiquadState->coefs[2],templ,30)
+ ynL+=templ;
+
+ /* ynLO= ((Gain (Q11) * ynL (Q0))>>11) in Q0*/
+ MUL32x16INTO32(ynL,pBiquadState->coefs[3],ynLO,11)
+ /* ynLO=( ynLO(Q0) + x(n)L (Q0) ) in Q0*/
+ ynLO+= (*pDataIn);
+
+ /**************************************************************************
+ PROCESSING OF THE RIGHT CHANNEL
+ ***************************************************************************/
+ /* ynR= (A0 (Q30) * (x(n)R (Q0) - x(n-2)R (Q0) ) >>30) in Q0*/
+ templ=(*(pDataIn+1))-pBiquadState->pDelays[3];
+ MUL32x32INTO32(templ,pBiquadState->coefs[0],ynR,30)
+
+ /* ynR+= ((-B2 (Q30) * y(n-2)R (Q0) ) >>30) in Q0*/
+ MUL32x32INTO32(pBiquadState->pDelays[7],pBiquadState->coefs[1],templ,30)
+ ynR+=templ;
+
+ /* ynR+= ((-B1 (Q30) * y(n-1)R (Q0) ) >>30) in Q0 */
+ MUL32x32INTO32(pBiquadState->pDelays[5],pBiquadState->coefs[2],templ,30)
+ ynR+=templ;
+
+ /* ynRO= ((Gain (Q11) * ynR (Q0))>>11) in Q0*/
+ MUL32x16INTO32(ynR,pBiquadState->coefs[3],ynRO,11)
+
+ /* ynRO=( ynRO(Q0) + x(n)R (Q0) ) in Q0*/
+ ynRO+= (*(pDataIn+1));
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[7]=pBiquadState->pDelays[5]; /* y(n-2)R=y(n-1)R*/
+ pBiquadState->pDelays[6]=pBiquadState->pDelays[4]; /* y(n-2)L=y(n-1)L*/
+ pBiquadState->pDelays[3]=pBiquadState->pDelays[1]; /* x(n-2)R=x(n-1)R*/
+ pBiquadState->pDelays[2]=pBiquadState->pDelays[0]; /* x(n-2)L=x(n-1)L*/
+ pBiquadState->pDelays[5]=ynR; /* Update y(n-1)R in Q0*/
+ pBiquadState->pDelays[4]=ynL; /* Update y(n-1)L in Q0*/
+ pBiquadState->pDelays[0]=(*pDataIn); /* Update x(n-1)L in Q0*/
+ pDataIn++;
+ pBiquadState->pDelays[1]=(*pDataIn); /* Update x(n-1)R in Q0*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut=ynLO; /* Write Left output in Q0*/
+ pDataOut++;
+ *pDataOut=ynRO; /* Write Right ouput in Q0*/
+ pDataOut++;
+ }
+
+ }
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..e7bcd0c
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Init.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CllGss_TRC_WRA_01_Private.h"
+
+
+void PK_2I_D32F32CllGss_TRC_WRA_01_Init(Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ PK_C32_Coefs_t *pCoef)
+{
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps;
+
+ pBiquadState->coefs[0]=pCoef->A0;
+
+ pBiquadState->coefs[1]=pCoef->B2;
+
+ pBiquadState->coefs[2]=pCoef->B1;
+
+ pBiquadState->coefs[3]=pCoef->G;
+
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..741f504
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CllGss_TRC_WRA_01_Private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
+#define _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _PK_2I_D32F32CLLGSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
new file mode 100755
index 0000000..f02305e
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Init.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+#include "BIQUAD.h"
+#include "PK_2I_D32F32CssGss_TRC_WRA_01_Private.h"
+
+void PK_2I_D32F32CssGss_TRC_WRA_01_Init(Biquad_Instance_t *pInstance,
+ Biquad_2I_Order2_Taps_t *pTaps,
+ PK_C16_Coefs_t *pCoef)
+{
+ PFilter_State pBiquadState = (PFilter_State) pInstance;
+ pBiquadState->pDelays =(LVM_INT32 *) pTaps;
+
+ pBiquadState->coefs[0]=pCoef->A0;
+
+ pBiquadState->coefs[1]=pCoef->B2;
+
+ pBiquadState->coefs[2]=pCoef->B1;
+
+ pBiquadState->coefs[3]=pCoef->G;
+
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
new file mode 100755
index 0000000..ca31669
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32CssGss_TRC_WRA_01_Private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
+#define _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+
+/* The internal state variables are implemented in a (for the user) hidden structure */
+/* In this (private) file, the internal structure is declared fro private use. */
+typedef struct _Filter_State_
+{
+ LVM_INT32 * pDelays; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 coefs[5]; /* pointer to the filter coefficients */
+}Filter_State;
+
+typedef Filter_State * PFilter_State ;
+
+#endif /* _PK_2I_D32F32CSSGSS_TRC_WRA_01_PRIVATE_H_ */
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
new file mode 100755
index 0000000..e449a7f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v16xv16.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION Shift_Sat_v16xv16
+***********************************************************************************/
+
+void Shift_Sat_v16xv16 (const LVM_INT16 val,
+ const LVM_INT16 *src,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 temp;
+ LVM_INT32 ii;
+ LVM_INT16 RShift;
+ if(val>0)
+ {
+ for (ii = n; ii != 0; ii--)
+ {
+ temp = (LVM_INT32)*src;
+ src++;
+
+ temp = temp << val;
+
+ if (temp > 0x00007FFF)
+ {
+ *dst = 0x7FFF;
+ }
+ else if (temp < -0x00008000)
+ {
+ *dst = - 0x8000;
+ }
+ else
+ {
+ *dst = (LVM_INT16)temp;
+ }
+ dst++;
+ }
+ }
+ else if(val<0)
+ {
+ RShift=(LVM_INT16)(-val);
+
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = (LVM_INT16)(*src >> RShift);
+ dst++;
+ src++;
+ }
+ }
+ else
+ {
+ if(src!=dst)
+ {
+ Copy_16(src,dst,n);
+ }
+ }
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
new file mode 100755
index 0000000..0ab98ea
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/Shift_Sat_v32xv32.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: */
+/* $Author: beq07716 $*/
+/* $Revision: 1000 $*/
+/* $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION Shift_Sat_v32xv32
+***********************************************************************************/
+
+void Shift_Sat_v32xv32 (const LVM_INT16 val,
+ const LVM_INT32 *src,
+ LVM_INT32 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT32 ii;
+ LVM_INT16 RShift;
+
+ if(val>0)
+ {
+ LVM_INT32 a,b;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ a=*src;
+ src++;
+
+ b=(a<<val);
+
+ if( (b>>val) != a ) /* if overflow occured, right shift will show difference*/
+ {
+ if(a<0)
+ {
+ b=0x80000000l;
+ }
+ else
+ {
+ b=0x7FFFFFFFl;
+ }
+ }
+
+ *dst = b;
+ dst++;
+ }
+ }
+ else if(val<0)
+ {
+ RShift=(LVM_INT16)(-val);
+ for (ii = n; ii != 0; ii--)
+ {
+ *dst = (*src >> RShift);
+ dst++;
+ src++;
+ }
+ }
+ else
+ {
+ if(src!=dst)
+ {
+ Copy_16((LVM_INT16 *)src,(LVM_INT16 *)dst,(LVM_INT16)(n<<1));
+ }
+ }
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
new file mode 100755
index 0000000..ac0343f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/dB_to_Lin32.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* %created_by: sra % (CM/S)*/
+/* %name: dB_to_Lin32.c % (CM/S)*/
+/* %version: 2 % (CM/S)*/
+/* %date_created: Wed Jun 18 11:27:46 2008 % (CM/S)*/
+/* */
+/************************************************************************/
+
+/*######################################################################################*/
+/* Include files */
+/*######################################################################################*/
+
+#include "ScalarArithmetic.h"
+
+
+/****************************************************************************************
+ * Name : dB_to_Lin32()
+ * Input : Signed 16-bit integer
+ * MSB (16) = sign bit
+ * (15->05) = integer part
+ * (04->01) = decimal part
+ * Output : Signed 32-bit integer
+ * MSB (32) = sign bit
+ * (31->16) = integer part
+ * (15->01) = decimal part
+ * Returns : Lin value format 1.16.15
+ * Description :
+ * Remarks : Makes an approximation to the conversion by counting the number
+ * of 6dB steps for use as shifts and then interpolates with a remainder
+ * with the equation:
+ *
+ * Correction = (Remainder / 1.5029) - (Remainder^2 / 6)
+ *
+ * The two coefficients are scaled from 0x40000000 in 96 steps and calculated
+ * as follows:
+ *
+ * FIRST_COEF = 0x80000000 / (96 * 1.5029)
+ * SECOND_COEF = 0x80000000 / (96^2 * 6)
+ *
+ ****************************************************************************************/
+
+#define FOUR_OVER_SIX 21846 /* (4 / 6) * 2^15 */
+#define SIX_DB 96 /* 6 * 16 or 6dB in Q11.4 format */
+#define FIRST_COEF_NEG 14884305
+#define FIRST_COEF_POS 7442152 /* FIRST_COEF_NEG / 2 */
+#define SECOND_COEF 38836
+#define MAX_VALUE 1536 /* 96 * 16 */
+
+LVM_INT32 dB_to_Lin32(LVM_INT16 db_fix)
+{
+ LVM_INT32 Lin_val_32;
+ LVM_INT16 Shift;
+ LVM_INT32 Remain;
+
+
+ /*
+ * Check sign of the input
+ */
+ if (db_fix<0)
+ {
+ if (db_fix > -MAX_VALUE)
+ {
+ Shift = (LVM_INT16)((((LVM_UINT32)(-db_fix) >> 4) * FOUR_OVER_SIX) >> 17); /* Number of 6dB steps in Q11.4 format */
+ Remain = -db_fix - (Shift * SIX_DB);
+ Remain = (0x7FFFFFFF - (Remain * FIRST_COEF_NEG)) + (Remain * Remain * SECOND_COEF);
+ Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (16 + Shift));
+ }
+ else
+ {
+ Lin_val_32 = 0;
+ }
+ }
+ else
+ {
+ if (db_fix < MAX_VALUE)
+ {
+ Shift = (LVM_INT16)((((LVM_UINT32)db_fix >> 4) * FOUR_OVER_SIX) >> 17); /* Number of 6dB steps in Q11.4 format */
+ Remain = db_fix - (Shift * SIX_DB);
+ Remain = 0x3FFFFFFF + (Remain * FIRST_COEF_POS) + (Remain * Remain * SECOND_COEF);
+ Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (15 - Shift));
+ }
+ else
+ {
+ Lin_val_32 = 0x7FFFFFFF;
+ }
+ }
+
+
+ return Lin_val_32; /* format 1.16.15 */
+}
+
diff --git a/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c
new file mode 100755
index 0000000..b500979
--- /dev/null
+++ b/media/libeffects/lvm/lib/Common/src/mult3s_16x16.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1000 $
+ $Date: 2010-06-28 13:08:20 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/**********************************************************************************
+ INCLUDE FILES
+***********************************************************************************/
+
+#include "VectorArithmetic.h"
+
+/**********************************************************************************
+ FUNCTION MULT3S_16X16
+***********************************************************************************/
+
+void Mult3s_16x16( const LVM_INT16 *src,
+ const LVM_INT16 val,
+ LVM_INT16 *dst,
+ LVM_INT16 n)
+{
+ LVM_INT16 ii;
+ LVM_INT32 temp;
+
+ for (ii = n; ii != 0; ii--)
+ {
+ temp = (LVM_INT32)(*src) * (LVM_INT32)val;
+ src++;
+
+ *dst = (LVM_INT16)(temp >> 15);
+ dst++;
+ }
+
+ return;
+}
+
+/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
new file mode 100755
index 0000000..7ba583f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -0,0 +1,484 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1005 $
+ $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the application layer interface of the N-Band equaliser. */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the calling layer. All other types, structures and */
+/* functions are private. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 1 */
+/* ======= */
+/* The algorithm can execute either with separate input and output buffers or with */
+/* a common buffer, i.e. the data is processed in-place. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 2 */
+/* ======= */
+/* Two data formats are support Stereo and Mono-In-Stereo. The data is interleaved as */
+/* follows: */
+/* Byte Offset Stereo Input Mono-In-Stereo Input */
+/* =========== ============ ==================== */
+/* 0 Left Sample #1 Mono Sample #1 */
+/* 2 Right Sample #1 Mono Sample #1 */
+/* 4 Left Sample #2 Mono Sample #2 */
+/* 6 Right Sample #2 Mono Sample #2 */
+/* . . . */
+/* . . . */
+/* */
+/* Mono format data is not supported, the calling routine must convert a Mono stream */
+/* in to Mono-In-Stereo format. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 3 */
+/* ======= */
+/* The format of the data in the filter band definition structure is as follows: */
+/* */
+/* Gain is in integer dB, range -15dB to +15dB inclusive */
+/* Frequency is the centre frequency in Hz, range DC to Nyquist */
+/* QFactor is the Q multiplied by 100, range 0.25 (25) to 12 (1200) */
+/* */
+/* Example: */
+/* Gain = 7 7dB gain */
+/* Frequency = 2467 Centre frequency = 2.467kHz */
+/* QFactor = 1089 Q = 10.89 */
+/* */
+/* The equaliser filters are passed as a pointer to and array of filter band */
+/* definitions structures. There must be one filter definition for each band. */
+/* */
+/****************************************************************************************/
+
+
+#ifndef __LVEQNB_H__
+#define __LVEQNB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Common.h"
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+
+/* Memory table */
+#define LVEQNB_MEMREGION_INSTANCE 0 /* Offset to the instance memory region */
+#define LVEQNB_MEMREGION_PERSISTENT_DATA 1 /* Offset to persistent data memory region */
+#define LVEQNB_MEMREGION_PERSISTENT_COEF 2 /* Offset to persistent coefficient region */
+#define LVEQNB_MEMREGION_SCRATCH 3 /* Offset to data scratch memory region */
+#define LVEQNB_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+/* Callback events */
+#define LVEQNB_EVENT_NONE 0x0000 /* Not a valid event */
+#define LVEQNB_EVENT_ALGOFF 0x0001 /* EQNB has completed switch off */
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVEQNB_Handle_t;
+
+
+/* Operating modes */
+typedef enum
+{
+ LVEQNB_BYPASS = 0,
+ LVEQNB_ON = 1,
+ LVEQNB_MODE_MAX = LVM_MAXINT_32
+} LVEQNB_Mode_en;
+
+
+/* Filter mode control */
+typedef enum
+{
+ LVEQNB_FILTER_OFF = 0,
+ LVEQNB_FILTER_ON = 1,
+ LVEQNB_FILTER_DUMMY = LVM_MAXINT_32
+} LVEQNB_FilterMode_en;
+
+
+/* Memory Types */
+typedef enum
+{
+ LVEQNB_PERSISTENT = 0,
+ LVEQNB_PERSISTENT_DATA = 1,
+ LVEQNB_PERSISTENT_COEF = 2,
+ LVEQNB_SCRATCH = 3,
+ LVEQNB_MEMORY_MAX = LVM_MAXINT_32
+} LVEQNB_MemoryTypes_en;
+
+
+/* Function return status */
+typedef enum
+{
+ LVEQNB_SUCCESS = 0, /* Successful return from a routine */
+ LVEQNB_ALIGNMENTERROR = 1, /* Memory alignment error */
+ LVEQNB_NULLADDRESS = 2, /* NULL allocation address */
+ LVEQNB_TOOMANYSAMPLES = 3, /* Maximum block size exceeded */
+ LVEQNB_STATUS_MAX = LVM_MAXINT_32
+} LVEQNB_ReturnStatus_en;
+
+
+/****************************************************************************************/
+/* */
+/* Linked enumerated type and capability definitions */
+/* */
+/* The capability definitions are used to define the required capabilities at */
+/* initialisation, these are added together to give the capability word. The */
+/* enumerated type is used to select the mode through a control function at run time. */
+/* */
+/* The capability definition is related to the enumerated type value by the equation: */
+/* */
+/* Capability_value = 2^Enumerated_value */
+/* */
+/* For example, a module could be configurd at initialisation to support two sample */
+/* rates only by calling the init function with the value: */
+/* Capabilities.SampleRate = LVEQNB_CAP_32000 + LVEQNB_CAP_44100; */
+/* */
+/* and at run time it would be passed the value LVEQNB_FS_32000 through the control */
+/* function to select operation at 32kHz */
+/* */
+/****************************************************************************************/
+
+/*
+ * Supported source data formats
+ */
+#define LVEQNB_CAP_STEREO 1
+#define LVEQNB_CAP_MONOINSTEREO 2
+
+typedef enum
+{
+ LVEQNB_STEREO = 0,
+ LVEQNB_MONOINSTEREO = 1,
+ LVEQNB_SOURCE_MAX = LVM_MAXINT_32
+} LVEQNB_SourceFormat_en;
+
+
+/*
+ * Supported sample rates in samples per second
+ */
+#define LVEQNB_CAP_FS_8000 1
+#define LVEQNB_CAP_FS_11025 2
+#define LVEQNB_CAP_FS_12000 4
+#define LVEQNB_CAP_FS_16000 8
+#define LVEQNB_CAP_FS_22050 16
+#define LVEQNB_CAP_FS_24000 32
+#define LVEQNB_CAP_FS_32000 64
+#define LVEQNB_CAP_FS_44100 128
+#define LVEQNB_CAP_FS_48000 256
+
+typedef enum
+{
+ LVEQNB_FS_8000 = 0,
+ LVEQNB_FS_11025 = 1,
+ LVEQNB_FS_12000 = 2,
+ LVEQNB_FS_16000 = 3,
+ LVEQNB_FS_22050 = 4,
+ LVEQNB_FS_24000 = 5,
+ LVEQNB_FS_32000 = 6,
+ LVEQNB_FS_44100 = 7,
+ LVEQNB_FS_48000 = 8,
+ LVEQNB_FS_MAX = LVM_MAXINT_32
+} LVEQNB_Fs_en;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+ LVM_UINT32 Size; /* Region size in bytes */
+ LVM_UINT16 Alignment; /* Region alignment in bytes */
+ LVEQNB_MemoryTypes_en Type; /* Region type */
+ void *pBaseAddress; /* Pointer to the region base address */
+} LVEQNB_MemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVEQNB_MemoryRegion_t Region[LVEQNB_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVEQNB_MemTab_t;
+
+
+/* Equaliser band definition */
+typedef struct
+{
+ LVM_INT16 Gain; /* Band gain in dB */
+ LVM_UINT16 Frequency; /* Band centre frequency in Hz */
+ LVM_UINT16 QFactor; /* Band quality factor */
+} LVEQNB_BandDef_t;
+
+
+/* Parameter structure */
+typedef struct
+{
+ /* General parameters */
+ LVEQNB_Mode_en OperatingMode;
+ LVEQNB_Fs_en SampleRate;
+ LVEQNB_SourceFormat_en SourceFormat;
+
+ /* Equaliser parameters */
+ LVM_UINT16 NBands; /* Number of bands */
+ LVEQNB_BandDef_t *pBandDefinition; /* Pointer to equaliser definitions */
+
+} LVEQNB_Params_t;
+
+
+/* Capability structure */
+typedef struct
+{
+ /* General parameters */
+ LVM_UINT16 SampleRate;
+ LVM_UINT16 SourceFormat;
+ LVM_UINT16 MaxBlockSize;
+ LVM_UINT16 MaxBands;
+
+ /* Callback parameters */
+ LVM_Callback CallBack; /* Bundle callback */
+ void *pBundleInstance; /* Bundle instance handle */
+
+} LVEQNB_Capabilities_t;
+
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the default capabilities */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeded */
+/* LVEQNB_NULLADDRESS When any of pMemoryTable and pCapabilities is NULL address */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t hInstance,
+ LVEQNB_MemTab_t *pMemoryTable,
+ LVEQNB_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Init */
+/* */
+/* DESCRIPTION: */
+/* Create and initialisation function for the N-Band equalliser module */
+/* */
+/* This function can be used to create an algorithm instance by calling with */
+/* hInstance set to NULL. In this case the algorithm returns the new instance */
+/* handle. */
+/* */
+/* This function can be used to force a full re-initialisation of the algorithm */
+/* by calling with hInstance = Instance Handle. In this case the memory table */
+/* should be correct for the instance, this can be ensured by calling the function */
+/* LVEQNB_Memory before calling this function. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pCapabilities Pointer to the initialisation capabilities */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Initialisation succeeded */
+/* LVEQNB_NULLADDRESS When pCapabilities or pMemoryTableis or phInstance are NULL */
+/* LVEQNB_NULLADDRESS One or more of the memory regions has a NULL base address */
+/* pointer for a memory region with a non-zero size. */
+/* */
+/* */
+/* NOTES: */
+/* 1. The instance handle is the pointer to the base address of the first memory */
+/* region. */
+/* 2. This function must not be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t *phInstance,
+ LVEQNB_MemTab_t *pMemoryTable,
+ LVEQNB_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_GetParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the equaliser module parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeds */
+/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t hInstance,
+ LVEQNB_Params_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_GetCapabilities */
+/* */
+/* DESCRIPTION: */
+/* Request the equaliser module capabilities. The capabilities set is returned */
+/* via the pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pCapabilities Pointer to an empty capability structure */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeds */
+/* LVEQNB_NULLADDRESS hInstance or pCapabilities is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance,
+ LVEQNB_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Control */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the equaliser module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeded */
+/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
+/* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */
+/* number of bands is non-zero */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance,
+ LVEQNB_Params_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LifeVibes module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeded */
+/* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */
+/* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */
+/* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples);
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVEQNB__ */
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
new file mode 100755
index 0000000..4881049
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_CalcCoef.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1005 $
+ $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVEQNB_Private.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+
+#define PI 3.14159265358979
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_DoublePrecCoefs */
+/* */
+/* DESCRIPTION: */
+/* Calculate double precision coefficients for a peaking filter */
+/* */
+/* PARAMETERS: */
+/* Fs Sampling frequency index */
+/* pFilterDefinition Pointer to the filter definition */
+/* pCoefficients Pointer to the coefficients */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The equations used are as follows: */
+/* */
+/* G = 10^(GaindB/20) - 1 */
+/* t0 = 2 * Pi * Fc / Fs */
+/* D = 1 if GaindB >= 0 */
+/* D = 1 / (1 + G) if GaindB < 0 */
+/* */
+/* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */
+/* b1 = (0.5 - b2) * (1 - coserr(t0)) */
+/* a0 = (0.5 + b2) / 2 */
+/* */
+/* Where: */
+/* GaindB is the gain in dBs, range -15dB to +15dB */
+/* Fc is the centre frequency, DC to Fs/50 */
+/* Fs is the sample frequency, 8000 to 48000 in descrete steps */
+/* Q is the Q factor, 0.25 to 12 (represented by 25 to 1200) */
+/* */
+/* 2. The double precision coefficients are only used when fc is less than fs/85, so */
+/* the cosine of t0 is always close to 1.0. Instead of calculating the cosine */
+/* itself the difference from the value 1.0 is calculated, this can be done with */
+/* lower precision maths. */
+/* */
+/* 3. The value of the B2 coefficient is only calculated as a single precision value, */
+/* small errors in this value have a combined effect on the Q and Gain but not the */
+/* the frequency of the filter. */
+/* */
+/****************************************************************************************/
+
+
+LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16 Fs,
+ LVEQNB_BandDef_t *pFilterDefinition,
+ PK_C32_Coefs_t *pCoefficients)
+{
+
+ extern LVM_INT16 LVEQNB_GainTable[];
+ extern LVM_INT16 LVEQNB_TwoPiOnFsTable[];
+ extern LVM_INT16 LVEQNB_DTable[];
+ extern LVM_INT16 LVEQNB_DPCosCoef[];
+
+ /*
+ * Get the filter definition
+ */
+ LVM_INT16 Gain = pFilterDefinition->Gain;
+ LVM_UINT16 Frequency = pFilterDefinition->Frequency;
+ LVM_UINT16 QFactor = pFilterDefinition->QFactor;
+
+ /*
+ * Intermediate variables and temporary values
+ */
+ LVM_INT32 T0;
+ LVM_INT16 D;
+ LVM_INT32 A0;
+ LVM_INT32 B1;
+ LVM_INT32 B2;
+ LVM_INT32 Dt0;
+ LVM_INT32 B2_Den;
+ LVM_INT32 B2_Num;
+ LVM_INT32 CosErr;
+ LVM_INT16 coef;
+ LVM_INT32 factor;
+ LVM_INT16 t0;
+ LVM_INT16 i;
+
+ /*
+ * Calculating the intermediate values
+ */
+ T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */
+ if (Gain >= 0)
+ {
+ D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */
+ }
+ else
+ {
+ D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */
+ }
+
+ /*
+ * Calculate the B2 coefficient
+ */
+ Dt0 = D * (T0 >> 10);
+ B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2);
+ B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18);
+ B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+ /*
+ * Calculate the cosine error by a polynomial expansion using the equation:
+ *
+ * CosErr += coef(n) * t0^n For n = 0 to 4
+ */
+ T0 = (T0 >> 6) * 0x7f53; /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+ t0 = (LVM_INT16)(T0 >> 16);
+ factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */
+ CosErr = 0; /* Initialise the error to zero */
+ for (i=1; i<5; i++)
+ {
+ coef = LVEQNB_DPCosCoef[i]; /* Get the nth coefficient */
+ CosErr += (factor * coef) >> 5; /* The nth partial sum */
+ factor = (factor * t0) >> 15; /* Calculate t0^n */
+ }
+ CosErr = CosErr << (LVEQNB_DPCosCoef[0]); /* Correct the scaling */
+
+ /*
+ * Calculate the B1 and A0 coefficients
+ */
+ B1 = (0x40000000 - B2); /* B1 = (0.5 - b2/2) */
+ A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6; /* Temporary storage for (0.5 - b2/2) * coserr(t0) */
+ B1 -= A0; /* B1 = (0.5 - b2/2) * (1 - coserr(t0)) */
+ A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) */
+
+ /*
+ * Write coeff into the data structure
+ */
+ pCoefficients->A0 = A0;
+ pCoefficients->B1 = B1;
+ pCoefficients->B2 = B2;
+ pCoefficients->G = LVEQNB_GainTable[Gain+15];
+
+ return(LVEQNB_SUCCESS);
+
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_SinglePrecCoefs */
+/* */
+/* DESCRIPTION: */
+/* Calculate single precision coefficients for a peaking filter */
+/* */
+/* PARAMETERS: */
+/* Fs Sampling frequency index */
+/* pFilterDefinition Pointer to the filter definition */
+/* pCoefficients Pointer to the coefficients */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The equations used are as follows: */
+/* */
+/* G = 10^(GaindB/20) - 1 */
+/* t0 = 2 * Pi * Fc / Fs */
+/* D = 1 if GaindB >= 0 */
+/* D = 1 / (1 + G) if GaindB < 0 */
+/* */
+/* b2 = -0.5 * (2Q - D * t0) / (2Q + D * t0) */
+/* b1 = (0.5 - b2) * cos(t0) */
+/* a0 = (0.5 + b2) / 2 */
+/* */
+/* Where: */
+/* GaindB is the gain in dBs, range -15dB to +15dB */
+/* Fc is the centre frequency, DC to Nyquist */
+/* Fs is the sample frequency, 8000 to 48000 in descrete steps */
+/* Q is the Q factor, 0.25 to 12 */
+/* */
+/****************************************************************************************/
+
+
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs,
+ LVEQNB_BandDef_t *pFilterDefinition,
+ PK_C16_Coefs_t *pCoefficients)
+{
+
+ extern LVM_INT16 LVEQNB_GainTable[];
+ extern LVM_INT16 LVEQNB_TwoPiOnFsTable[];
+ extern LVM_INT16 LVEQNB_DTable[];
+ extern LVM_INT16 LVEQNB_CosCoef[];
+
+
+ /*
+ * Get the filter definition
+ */
+ LVM_INT16 Gain = pFilterDefinition->Gain;
+ LVM_UINT16 Frequency = pFilterDefinition->Frequency;
+ LVM_UINT16 QFactor = pFilterDefinition->QFactor;
+
+
+ /*
+ * Intermediate variables and temporary values
+ */
+ LVM_INT32 T0;
+ LVM_INT16 D;
+ LVM_INT32 A0;
+ LVM_INT32 B1;
+ LVM_INT32 B2;
+ LVM_INT32 Dt0;
+ LVM_INT32 B2_Den;
+ LVM_INT32 B2_Num;
+ LVM_INT32 COS_T0;
+ LVM_INT16 coef;
+ LVM_INT32 factor;
+ LVM_INT16 t0;
+ LVM_INT16 i;
+
+ /*
+ * Calculating the intermediate values
+ */
+ T0 = (LVM_INT32)Frequency * LVEQNB_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */
+ if (Gain >= 0)
+ {
+ D = LVEQNB_DTable[15]; /* D = 1 if GaindB >= 0 */
+ }
+ else
+ {
+ D = LVEQNB_DTable[Gain+15]; /* D = 1 / (1 + G) if GaindB < 0 */
+ }
+
+ /*
+ * Calculate the B2 coefficient
+ */
+ Dt0 = D * (T0 >> 10);
+ B2_Den = ((LVM_INT32)QFactor << 19) + (Dt0 >> 2);
+ B2_Num = (Dt0 >> 3) - ((LVM_INT32)QFactor << 18);
+ B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+ /*
+ * Calculate the cosine by a polynomial expansion using the equation:
+ *
+ * Cos += coef(n) * t0^n For n = 0 to 6
+ */
+ T0 = (T0 >> 10) * 20859; /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+ t0 = (LVM_INT16)(T0 >> 16);
+ factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */
+ COS_T0 = 0; /* Initialise the error to zero */
+ for (i=1; i<7; i++)
+ {
+ coef = LVEQNB_CosCoef[i]; /* Get the nth coefficient */
+ COS_T0 += (factor * coef) >> 5; /* The nth partial sum */
+ factor = (factor * t0) >> 15; /* Calculate t0^n */
+ }
+ COS_T0 = COS_T0 << (LVEQNB_CosCoef[0]+6); /* Correct the scaling */
+
+
+ B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16); /* B1 = (0.5 - b2/2) * cos(t0) */
+ A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2/2) */
+
+ /*
+ * Write coeff into the data structure
+ */
+ pCoefficients->A0 = (LVM_INT16)(A0>>16);
+ pCoefficients->B1 = (LVM_INT16)(B1>>15);
+ pCoefficients->B2 = (LVM_INT16)(B2>>16);
+ pCoefficients->G = LVEQNB_GainTable[Gain+15];
+
+
+ return(LVEQNB_SUCCESS);
+
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
new file mode 100755
index 0000000..87d7145
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Coeffs.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __LVEQNB_COEFFS_H__
+#define __LVEQNB_COEFFS_H__
+
+
+/************************************************************************************/
+/* */
+/* Gain table for (10^(Gain/20) - 1) */
+/* */
+/************************************************************************************/
+
+#define LVEQNB_GAINSHIFT 11 /* As a power of 2 */
+#define LVEQNB_Gain_Neg15_dB -1684 /* Floating point value -0.822172 */
+#define LVEQNB_Gain_Neg14_dB -1639 /* Floating point value -0.800474 */
+#define LVEQNB_Gain_Neg13_dB -1590 /* Floating point value -0.776128 */
+#define LVEQNB_Gain_Neg12_dB -1534 /* Floating point value -0.748811 */
+#define LVEQNB_Gain_Neg11_dB -1471 /* Floating point value -0.718162 */
+#define LVEQNB_Gain_Neg10_dB -1400 /* Floating point value -0.683772 */
+#define LVEQNB_Gain_Neg9_dB -1321 /* Floating point value -0.645187 */
+#define LVEQNB_Gain_Neg8_dB -1233 /* Floating point value -0.601893 */
+#define LVEQNB_Gain_Neg7_dB -1133 /* Floating point value -0.553316 */
+#define LVEQNB_Gain_Neg6_dB -1022 /* Floating point value -0.498813 */
+#define LVEQNB_Gain_Neg5_dB -896 /* Floating point value -0.437659 */
+#define LVEQNB_Gain_Neg4_dB -756 /* Floating point value -0.369043 */
+#define LVEQNB_Gain_Neg3_dB -598 /* Floating point value -0.292054 */
+#define LVEQNB_Gain_Neg2_dB -421 /* Floating point value -0.205672 */
+#define LVEQNB_Gain_Neg1_dB -223 /* Floating point value -0.108749 */
+#define LVEQNB_Gain_0_dB 0 /* Floating point value 0.000000 */
+#define LVEQNB_Gain_1_dB 250 /* Floating point value 0.122018 */
+#define LVEQNB_Gain_2_dB 530 /* Floating point value 0.258925 */
+#define LVEQNB_Gain_3_dB 845 /* Floating point value 0.412538 */
+#define LVEQNB_Gain_4_dB 1198 /* Floating point value 0.584893 */
+#define LVEQNB_Gain_5_dB 1594 /* Floating point value 0.778279 */
+#define LVEQNB_Gain_6_dB 2038 /* Floating point value 0.995262 */
+#define LVEQNB_Gain_7_dB 2537 /* Floating point value 1.238721 */
+#define LVEQNB_Gain_8_dB 3096 /* Floating point value 1.511886 */
+#define LVEQNB_Gain_9_dB 3724 /* Floating point value 1.818383 */
+#define LVEQNB_Gain_10_dB 4428 /* Floating point value 2.162278 */
+#define LVEQNB_Gain_11_dB 5219 /* Floating point value 2.548134 */
+#define LVEQNB_Gain_12_dB 6105 /* Floating point value 2.981072 */
+#define LVEQNB_Gain_13_dB 7100 /* Floating point value 3.466836 */
+#define LVEQNB_Gain_14_dB 8216 /* Floating point value 4.011872 */
+#define LVEQNB_Gain_15_dB 9469 /* Floating point value 4.623413 */
+
+
+/************************************************************************************/
+/* */
+/* Frequency table for 2*Pi/Fs */
+/* */
+/************************************************************************************/
+
+#define LVEQNB_FREQSHIFT 25 /* As a power of 2 */
+#define LVEQNB_2PiOn_8000 26354 /* Floating point value 0.000785 */
+#define LVEQNB_2PiOn_11025 19123 /* Floating point value 0.000570 */
+#define LVEQNB_2PiOn_12000 17569 /* Floating point value 0.000524 */
+#define LVEQNB_2PiOn_16000 13177 /* Floating point value 0.000393 */
+#define LVEQNB_2PiOn_22050 9561 /* Floating point value 0.000285 */
+#define LVEQNB_2PiOn_24000 8785 /* Floating point value 0.000262 */
+#define LVEQNB_2PiOn_32000 6588 /* Floating point value 0.000196 */
+#define LVEQNB_2PiOn_44100 4781 /* Floating point value 0.000142 */
+#define LVEQNB_2PiOn_48000 4392 /* Floating point value 0.000131 */
+
+
+/************************************************************************************/
+/* */
+/* 50D table for 50 / ( 1 + Gain ) */
+/* */
+/************************************************************************************/
+
+#define LVEQNB_100DSHIFT 5 /* As a power of 2 */
+#define LVEQNB_100D_Neg15_dB 17995 /* Floating point value 5.623413 */
+#define LVEQNB_100D_Neg14_dB 16038 /* Floating point value 5.011872 */
+#define LVEQNB_100D_Neg13_dB 14294 /* Floating point value 4.466836 */
+#define LVEQNB_100D_Neg12_dB 12739 /* Floating point value 3.981072 */
+#define LVEQNB_100D_Neg11_dB 11354 /* Floating point value 3.548134 */
+#define LVEQNB_100D_Neg10_dB 10119 /* Floating point value 3.162278 */
+#define LVEQNB_100D_Neg9_dB 9019 /* Floating point value 2.818383 */
+#define LVEQNB_100D_Neg8_dB 8038 /* Floating point value 2.511886 */
+#define LVEQNB_100D_Neg7_dB 7164 /* Floating point value 2.238721 */
+#define LVEQNB_100D_Neg6_dB 6385 /* Floating point value 1.995262 */
+#define LVEQNB_100D_Neg5_dB 5690 /* Floating point value 1.778279 */
+#define LVEQNB_100D_Neg4_dB 5072 /* Floating point value 1.584893 */
+#define LVEQNB_100D_Neg3_dB 4520 /* Floating point value 1.412538 */
+#define LVEQNB_100D_Neg2_dB 4029 /* Floating point value 1.258925 */
+#define LVEQNB_100D_Neg1_dB 3590 /* Floating point value 1.122018 */
+#define LVEQNB_100D_0_dB 3200 /* Floating point value 1.000000 */
+
+
+#endif
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
new file mode 100755
index 0000000..dac2449
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1316 $
+ $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+
+#define LOW_FREQ 298 /* 32768/110 for low test frequency */
+#define HIGH_FREQ 386 /* 32768/85 for high test frequency */
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_GetParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the N-Band equaliser parameters. The current parameter set is returned via */
+/* the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeds */
+/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t hInstance,
+ LVEQNB_Params_t *pParams)
+{
+
+ LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
+
+ /*
+ * Check for error conditions
+ */
+ if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+ *pParams = pInstance->Params;
+
+ return(LVEQNB_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_GetCapabilities */
+/* */
+/* DESCRIPTION: */
+/* Get the N-Band equaliser capabilities. The current capabilities are returned */
+/* via the pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pCapabilities Pointer to an empty capability structure */
+/* */
+/* RETURNS: */
+/* LVEQNB_Success Succeeds */
+/* LVEQNB_NULLADDRESS hInstance or pCapabilities is NULL */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance,
+ LVEQNB_Capabilities_t *pCapabilities)
+{
+
+ LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
+
+ if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+ *pCapabilities = pInstance->Capabilities;
+
+ return(LVEQNB_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_SetFilters */
+/* */
+/* DESCRIPTION: */
+/* Sets the filter type based on the definition. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/* RETURNS: */
+/* void Nothing */
+/* */
+/* NOTES: */
+/* 1. To select the biquad type the follow rules are applied: */
+/* Double precision if (fc <= fs/110) */
+/* Double precision if (fs/110 < fc < fs/85) & (Q>3) */
+/* Single precision otherwise */
+/* */
+/************************************************************************************/
+
+void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance,
+ LVEQNB_Params_t *pParams)
+{
+
+ extern const LVM_UINT16 LVEQNB_SampleRateTab[]; /* Sample rate table */
+ LVM_UINT16 i; /* Filter band index */
+ LVM_UINT32 fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate]; /* Sample rate */
+ LVM_UINT32 fc; /* Filter centre frequency */
+ LVM_INT16 QFactor; /* Filter Q factor */
+
+
+ pInstance->NBands = pParams->NBands;
+
+ for (i=0; i<pParams->NBands; i++)
+ {
+ /*
+ * Get the filter settings
+ */
+ fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency; /* Get the band centre frequency */
+ QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor; /* Get the band Q factor */
+
+
+ /*
+ * For each filter set the type of biquad required
+ */
+ pInstance->pBiquadType[i] = LVEQNB_SinglePrecision; /* Default to single precision */
+ if ((fc << 15) <= (LOW_FREQ * fs))
+ {
+ /*
+ * fc <= fs/110
+ */
+ pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
+ }
+ else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300))
+ {
+ /*
+ * (fs/110 < fc < fs/85) & (Q>3)
+ */
+ pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
+ }
+
+
+ /*
+ * Check for out of range frequencies
+ */
+ if (fc > (fs >> 1))
+ {
+ pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
+ }
+
+
+ /*
+ * Copy the filter definition to persistant memory
+ */
+ pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
+
+ }
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_SetCoefficients */
+/* */
+/* DESCRIPTION: */
+/* Sets the filter coefficients. This uses the type to select single or double */
+/* precision coefficients. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pParams Initialisation parameters */
+/* */
+/************************************************************************************/
+
+void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance)
+{
+
+ LVM_UINT16 i; /* Filter band index */
+ LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
+
+
+ /*
+ * Set the coefficients for each band by the init function
+ */
+ for (i=0; i<pInstance->Params.NBands; i++)
+ {
+
+ /*
+ * Check band type for correct initialisation method and recalculate the coefficients
+ */
+ BiquadType = pInstance->pBiquadType[i];
+ switch (BiquadType)
+ {
+ case LVEQNB_DoublePrecision:
+ {
+ PK_C32_Coefs_t Coefficients;
+
+ /*
+ * Calculate the double precision coefficients
+ */
+ LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
+ &pInstance->pBandDefinitions[i],
+ &Coefficients);
+
+ /*
+ * Set the coefficients
+ */
+ PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
+ &pInstance->pEQNB_Taps[i],
+ &Coefficients);
+ break;
+ }
+
+ case LVEQNB_SinglePrecision:
+ {
+ PK_C16_Coefs_t Coefficients;
+
+ /*
+ * Calculate the single precision coefficients
+ */
+ LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
+ &pInstance->pBandDefinitions[i],
+ &Coefficients);
+
+ /*
+ * Set the coefficients
+ */
+ PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
+ &pInstance->pEQNB_Taps[i],
+ &Coefficients);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_ClearFilterHistory */
+/* */
+/* DESCRIPTION: */
+/* Clears the filter data history */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* */
+/************************************************************************************/
+
+void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance)
+{
+ LVM_INT16 *pTapAddress;
+ LVM_INT16 NumTaps;
+
+
+ pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps;
+ NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16));
+
+ if (NumTaps != 0)
+ {
+ LoadConst_16(0, /* Clear the history, value 0 */
+ pTapAddress, /* Destination */
+ NumTaps); /* Number of words */
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Control */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the LifeVibes module parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVEQNB_Success Always succeeds */
+/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
+/* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */
+/* number of bands is non-zero */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance,
+ LVEQNB_Params_t *pParams)
+{
+
+ LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
+ LVM_INT16 bChange = LVM_FALSE;
+ LVM_INT16 i = 0;
+ LVEQNB_Mode_en OperatingModeSave ;
+
+ /*
+ * Check for error conditions
+ */
+ if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+ if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+ OperatingModeSave = pInstance->Params.OperatingMode;
+
+ /* Set the alpha factor of the mixer */
+ if (pParams->SampleRate != pInstance->Params.SampleRate)
+ {
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+ }
+
+
+ if( (pInstance->Params.NBands != pParams->NBands ) ||
+ (pInstance->Params.OperatingMode != pParams->OperatingMode ) ||
+ (pInstance->Params.pBandDefinition != pParams->pBandDefinition ) ||
+ (pInstance->Params.SampleRate != pParams->SampleRate ) ||
+ (pInstance->Params.SourceFormat != pParams->SourceFormat ))
+ {
+
+ bChange = LVM_TRUE;
+ }
+ else
+ {
+ for(i = 0; i < pParams->NBands; i++)
+ {
+
+ if((pInstance->pBandDefinitions[i].Frequency != pParams->pBandDefinition[i].Frequency )||
+ (pInstance->pBandDefinitions[i].Gain != pParams->pBandDefinition[i].Gain )||
+ (pInstance->pBandDefinitions[i].QFactor != pParams->pBandDefinition[i].QFactor ))
+ {
+
+ bChange = LVM_TRUE;
+ }
+ }
+ }
+
+
+ if(bChange){
+
+ /*
+ * If the sample rate has changed clear the history
+ */
+ if (pInstance->Params.SampleRate != pParams->SampleRate)
+ {
+ LVEQNB_ClearFilterHistory(pInstance); /* Clear the history */
+ }
+
+ /*
+ * Update the instance parameters
+ */
+ pInstance->Params = *pParams;
+
+
+ /*
+ * Reset the filters except if the algo is switched off
+ */
+ if(pParams->OperatingMode != LVEQNB_BYPASS){
+ /*
+ * Reset the filters as all parameters could have changed
+ */
+ LVEQNB_SetFilters(pInstance, /* Instance pointer */
+ pParams); /* New parameters */
+
+ /*
+ * Update the filters
+ */
+ LVEQNB_SetCoefficients(pInstance); /* Instance pointer */
+ }
+
+ if(pParams->OperatingMode != OperatingModeSave)
+ {
+ if(pParams->OperatingMode == LVEQNB_ON)
+ {
+ LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
+ LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
+
+ pInstance->BypassMixer.MixerStream[0].CallbackSet = 1;
+ pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
+ }
+ else
+ {
+ /* Stay on the ON operating mode until the transition is done */
+ pInstance->Params.OperatingMode = LVEQNB_ON;
+
+ LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
+ LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
+ pInstance->BypassMixer.MixerStream[0].CallbackSet = 1;
+ pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
+ }
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
+
+ pInstance->bInOperatingModeTransition = LVM_TRUE;
+ }
+
+ }
+ return(LVEQNB_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_BypassMixerCallBack */
+/* */
+/* DESCRIPTION: */
+/* CallBack function of the mixer */
+/* transition */
+/* */
+/****************************************************************************************/
+LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
+ void *pGeneralPurpose,
+ LVM_INT16 CallbackParam)
+{
+ LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
+ LVM_Callback CallBack = pInstance->Capabilities.CallBack;
+
+ (void) pGeneralPurpose;
+
+ /*
+ * Send an ALGOFF event if the ON->OFF switch transition is finished
+ */
+ if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
+ (CallbackParam == 0)){
+ pInstance->Params.OperatingMode = LVEQNB_BYPASS;
+ if (CallBack != LVM_NULL){
+ CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
+ }
+ }
+
+ /*
+ * Exit transition state
+ */
+ pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+ return 1;
+}
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
new file mode 100755
index 0000000..a29fe05
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Init.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1005 $
+ $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the instance capabilities */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeded */
+/* LVEQNB_NULLADDRESS When any of pMemoryTable and pCapabilities is NULL address */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t hInstance,
+ LVEQNB_MemTab_t *pMemoryTable,
+ LVEQNB_Capabilities_t *pCapabilities)
+{
+
+ INST_ALLOC AllocMem;
+ LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
+
+
+ if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+ /*
+ * Instance memory
+ */
+ InstAlloc_Init(&AllocMem,
+ LVM_NULL);
+ InstAlloc_AddMember(&AllocMem, /* Low pass filter */
+ sizeof(LVEQNB_Instance_t));
+ pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size = InstAlloc_GetTotal(&AllocMem);
+ pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment = LVEQNB_INSTANCE_ALIGN;
+ pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type = LVEQNB_PERSISTENT;
+ pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+
+ /*
+ * Persistant data memory
+ */
+ InstAlloc_Init(&AllocMem,
+ LVM_NULL);
+ InstAlloc_AddMember(&AllocMem, /* Low pass filter */
+ sizeof(Biquad_2I_Order2_Taps_t));
+ InstAlloc_AddMember(&AllocMem, /* High pass filter */
+ sizeof(Biquad_2I_Order2_Taps_t));
+ InstAlloc_AddMember(&AllocMem,
+ (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */
+ InstAlloc_AddMember(&AllocMem,
+ (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t))); /* Filter definitions */
+ InstAlloc_AddMember(&AllocMem,
+ (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en))); /* Biquad types */
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size = InstAlloc_GetTotal(&AllocMem);
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment = LVEQNB_DATA_ALIGN;
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type = LVEQNB_PERSISTENT_DATA;
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+ /*
+ * Persistant coefficient memory
+ */
+ InstAlloc_Init(&AllocMem,
+ LVM_NULL);
+ InstAlloc_AddMember(&AllocMem, /* Low pass filter */
+ sizeof(Biquad_Instance_t));
+ InstAlloc_AddMember(&AllocMem, /* High pass filter */
+ sizeof(Biquad_Instance_t));
+ InstAlloc_AddMember(&AllocMem,
+ pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size = InstAlloc_GetTotal(&AllocMem);
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment = LVEQNB_COEF_ALIGN;
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type = LVEQNB_PERSISTENT_COEF;
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+ /*
+ * Scratch memory
+ */
+ InstAlloc_Init(&AllocMem,
+ LVM_NULL);
+ InstAlloc_AddMember(&AllocMem, /* Low pass filter */
+ LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
+ pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size = InstAlloc_GetTotal(&AllocMem);
+ pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment = LVEQNB_SCRATCH_ALIGN;
+ pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type = LVEQNB_SCRATCH;
+ pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+ }
+ else
+ {
+ /* Read back memory allocation table */
+ *pMemoryTable = pInstance->MemoryTable;
+ }
+
+ return(LVEQNB_SUCCESS);
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Init */
+/* */
+/* DESCRIPTION: */
+/* Create and initialisation function for the N-Band equaliser module */
+/* */
+/* This function can be used to create an algorithm instance by calling with */
+/* hInstance set to NULL. In this case the algorithm returns the new instance */
+/* handle. */
+/* */
+/* This function can be used to force a full re-initialisation of the algorithm */
+/* by calling with hInstance = Instance Handle. In this case the memory table */
+/* should be correct for the instance, this can be ensured by calling the function */
+/* DBE_Memory before calling this function. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pCapabilities Pointer to the instance capabilities */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Initialisation succeeded */
+/* LVEQNB_NULLADDRESS When pCapabilities or pMemoryTableis or phInstance are NULL */
+/* LVEQNB_NULLADDRESS One or more of the memory regions has a NULL base address */
+/* pointer for a memory region with a non-zero size. */
+/* */
+/* NOTES: */
+/* 1. The instance handle is the pointer to the base address of the first memory */
+/* region. */
+/* 2. This function must not be interrupted by the LVEQNB_Process function */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t *phInstance,
+ LVEQNB_MemTab_t *pMemoryTable,
+ LVEQNB_Capabilities_t *pCapabilities)
+{
+
+ LVEQNB_Instance_t *pInstance;
+ LVM_UINT32 MemSize;
+ INST_ALLOC AllocMem;
+ LVM_INT32 i;
+
+ /*
+ * Check for NULL pointers
+ */
+ if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+ /*
+ * Check the memory table for NULL pointers
+ */
+ for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++)
+ {
+ if (pMemoryTable->Region[i].Size!=0)
+ {
+ if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
+ {
+ return(LVEQNB_NULLADDRESS);
+ }
+ }
+ }
+
+ /*
+ * Set the instance handle if not already initialised
+ */
+
+ InstAlloc_Init(&AllocMem, pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress);
+
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t));
+ }
+ pInstance =(LVEQNB_Instance_t *)*phInstance;
+
+
+
+ /*
+ * Save the memory table in the instance structure
+ */
+ pInstance->Capabilities = *pCapabilities;
+
+
+ /*
+ * Save the memory table in the instance structure and
+ * set the structure pointers
+ */
+ pInstance->MemoryTable = *pMemoryTable;
+
+ /*
+ * Allocate coefficient memory
+ */
+ InstAlloc_Init(&AllocMem,
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+ pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
+ pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
+
+
+
+ /*
+ * Allocate data memory
+ */
+ InstAlloc_Init(&AllocMem,
+ pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+
+ MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
+ pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
+ MemSize);
+ MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
+ pInstance->pBandDefinitions = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
+ MemSize);
+ MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en));
+ pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem,
+ MemSize);
+
+
+ /*
+ * Internally map, structure and allign scratch memory
+ */
+ InstAlloc_Init(&AllocMem,
+ pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
+
+ pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
+ sizeof(LVM_INT16));
+
+ /*
+ * Update the instance parameters
+ */
+ pInstance->Params.NBands = 0;
+ pInstance->Params.OperatingMode = LVEQNB_BYPASS;
+ pInstance->Params.pBandDefinition = LVM_NULL;
+ pInstance->Params.SampleRate = LVEQNB_FS_8000;
+ pInstance->Params.SourceFormat = LVEQNB_STEREO;
+
+ /*
+ * Initialise the filters
+ */
+ LVEQNB_SetFilters(pInstance, /* Set the filter types */
+ &pInstance->Params);
+
+ LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */
+
+ LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */
+
+ /*
+ * Initialise the bypass variables
+ */
+ pInstance->BypassMixer.MixerStream[0].CallbackSet = 0;
+ pInstance->BypassMixer.MixerStream[0].CallbackParam = 0;
+ pInstance->BypassMixer.MixerStream[0].pCallbackHandle = (void*)pInstance;
+ pInstance->BypassMixer.MixerStream[0].pCallBack = LVEQNB_BypassMixerCallBack;
+ LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
+ LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
+
+ pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
+ pInstance->BypassMixer.MixerStream[1].CallbackParam = 0;
+ pInstance->BypassMixer.MixerStream[1].pCallbackHandle = LVM_NULL;
+ pInstance->BypassMixer.MixerStream[1].pCallBack = LVM_NULL;
+ LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
+ LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
+
+ pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+ return(LVEQNB_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
new file mode 100755
index 0000000..0ae84af
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1005 $
+ $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+#ifndef __LVEQNB_PRIVATE_H__
+#define __LVEQNB_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVEQNB.h" /* Calling or Application layer definitions */
+#include "BIQUAD.h"
+#include "LVC_Mixer.h"
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+
+/* General */
+#define LVEQNB_INVALID 0xFFFF /* Invalid init parameter */
+
+/* Memory */
+#define LVEQNB_INSTANCE_ALIGN 4 /* 32-bit alignment for instance structures */
+#define LVEQNB_DATA_ALIGN 4 /* 32-bit alignment for structures */
+#define LVEQNB_COEF_ALIGN 4 /* 32-bit alignment for long words */
+#define LVEQNB_SCRATCHBUFFERS 4 /* Number of buffers required for inplace processing */
+#define LVEQNB_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
+
+#define LVEQNB_BYPASS_MIXER_TC 100 /* Bypass Mixer TC */
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+
+/* Filter biquad types */
+typedef enum
+{
+ LVEQNB_SinglePrecision = 0,
+ LVEQNB_DoublePrecision = 1,
+ LVEQNB_OutOfRange = 2,
+ LVEQNB_BIQUADTYPE_MAX = LVM_MAXINT_32
+} LVEQNB_BiquadType_en;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+
+
+/* Instance structure */
+typedef struct
+{
+ /* Public parameters */
+ LVEQNB_MemTab_t MemoryTable; /* Instance memory allocation table */
+ LVEQNB_Params_t Params; /* Instance parameters */
+ LVEQNB_Capabilities_t Capabilities; /* Instance capabilities */
+
+ /* Aligned memory pointers */
+ LVM_INT16 *pFastTemporary; /* Fast temporary data base address */
+
+ /* Process variables */
+ Biquad_2I_Order2_Taps_t *pEQNB_Taps; /* Equaliser Taps */
+ Biquad_Instance_t *pEQNB_FilterState; /* State for each filter band */
+
+ /* Filter definitions and call back */
+ LVM_UINT16 NBands; /* Number of bands */
+ LVEQNB_BandDef_t *pBandDefinitions; /* Filter band definitions */
+ LVEQNB_BiquadType_en *pBiquadType; /* Filter biquad types */
+
+ /* Bypass variable */
+ LVMixer3_2St_st BypassMixer; /* Bypass mixer used in transitions */
+ LVM_INT16 bInOperatingModeTransition; /* Operating mode transition flag */
+
+} LVEQNB_Instance_t;
+
+
+/****************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/****************************************************************************************/
+
+void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance,
+ LVEQNB_Params_t *pParams);
+
+void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance);
+
+void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance);
+
+LVEQNB_ReturnStatus_en LVEQNB_SinglePrecCoefs(LVM_UINT16 Fs,
+ LVEQNB_BandDef_t *pFilterDefinition,
+ PK_C16_Coefs_t *pCoefficients);
+
+LVEQNB_ReturnStatus_en LVEQNB_DoublePrecCoefs(LVM_UINT16 Fs,
+ LVEQNB_BandDef_t *pFilterDefinition,
+ PK_C32_Coefs_t *pCoefficients);
+
+LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, void *pGeneralPurpose, LVM_INT16 CallbackParam);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVEQNB_PRIVATE_H__ */
+
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
new file mode 100755
index 0000000..e29e881
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**********************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1005 $
+ $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+***********************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Private.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+
+
+/****************************************************************************************/
+/* */
+/* Defines */
+/* */
+/****************************************************************************************/
+
+#define SHIFT 13
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the N-Band Equaliser module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVEQNB_SUCCESS Succeeded */
+/* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */
+/* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */
+/* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+
+ LVM_UINT16 i;
+ Biquad_Instance_t *pBiquad;
+ LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
+ LVM_INT32 *pScratch;
+
+
+ /* Check for NULL pointers */
+ if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+ {
+ return LVEQNB_NULLADDRESS;
+ }
+
+ /* Check if the input and output data buffers are 32-bit aligned */
+ if ((((LVM_INT32)pInData % 4) != 0) || (((LVM_INT32)pOutData % 4) != 0))
+ {
+ return LVEQNB_ALIGNMENTERROR;
+ }
+
+ pScratch = (LVM_INT32 *)pInstance->pFastTemporary;
+
+ /*
+ * Check the number of samples is not too large
+ */
+ if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+ {
+ return(LVEQNB_TOOMANYSAMPLES);
+ }
+
+ if (pInstance->Params.OperatingMode == LVEQNB_ON)
+ {
+ /*
+ * Convert from 16-bit to 32-bit
+ */
+ Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */
+ pScratch, /* Destination */
+ (LVM_INT16)(2*NumSamples), /* Left and Right */
+ SHIFT); /* Scaling shift */
+
+ /*
+ * For each section execte the filter unless the gain is 0dB
+ */
+ if (pInstance->NBands != 0)
+ {
+ for (i=0; i<pInstance->NBands; i++)
+ {
+ /*
+ * Check if band is non-zero dB gain
+ */
+ if (pInstance->pBandDefinitions[i].Gain != 0)
+ {
+ /*
+ * Get the address of the biquad instance
+ */
+ pBiquad = &pInstance->pEQNB_FilterState[i];
+
+
+ /*
+ * Select single or double precision as required
+ */
+ switch (pInstance->pBiquadType[i])
+ {
+ case LVEQNB_SinglePrecision:
+ {
+ PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
+ (LVM_INT32 *)pScratch,
+ (LVM_INT32 *)pScratch,
+ (LVM_INT16)NumSamples);
+ break;
+ }
+
+ case LVEQNB_DoublePrecision:
+ {
+ PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
+ (LVM_INT32 *)pScratch,
+ (LVM_INT32 *)pScratch,
+ (LVM_INT16)NumSamples);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+
+ if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+ /*
+ * Convert from 32-bit to 16- bit and saturate
+ */
+ Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
+ (LVM_INT16 *)pScratch, /* Destination */
+ (LVM_INT16)(2*NumSamples), /* Left and Right */
+ SHIFT); /* Scaling shift */
+
+ LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16 *)pInData,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16)(2*NumSamples));
+
+ Copy_16((LVM_INT16*)pScratch, /* Source */
+ pOutData, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
+ }
+ else{
+
+ /*
+ * Convert from 32-bit to 16- bit and saturate
+ */
+ Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
+ pOutData, /* Destination */
+ (LVM_INT16 )(2*NumSamples), /* Left and Right */
+ SHIFT); /* Scaling shift */
+ }
+ }
+ else
+ {
+ /*
+ * Mode is OFF so copy the data if necessary
+ */
+ if (pInData != pOutData)
+ {
+ Copy_16(pInData, /* Source */
+ pOutData, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
+ }
+ }
+
+
+
+ return(LVEQNB_SUCCESS);
+
+}
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
new file mode 100755
index 0000000..33c07da
--- /dev/null
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Tables.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1005 $
+ $Date: 2010-06-28 13:58:28 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVEQNB.h"
+#include "LVEQNB_Coeffs.h"
+
+
+/************************************************************************************/
+/* */
+/* Sample rate table */
+/* */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT16 LVEQNB_SampleRateTab[] = {8000, /* 8kS/s */
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000}; /* 48kS/s */
+
+
+/************************************************************************************/
+/* */
+/* Coefficient calculation tables */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_INT16 LVEQNB_TwoPiOnFsTable[] = {LVEQNB_2PiOn_8000, /* 8kS/s */
+ LVEQNB_2PiOn_11025,
+ LVEQNB_2PiOn_12000,
+ LVEQNB_2PiOn_16000,
+ LVEQNB_2PiOn_22050,
+ LVEQNB_2PiOn_24000,
+ LVEQNB_2PiOn_32000,
+ LVEQNB_2PiOn_44100,
+ LVEQNB_2PiOn_48000}; /* 48kS/s */
+
+/*
+ * Gain table
+ */
+const LVM_INT16 LVEQNB_GainTable[] = {LVEQNB_Gain_Neg15_dB, /* -15dB gain */
+ LVEQNB_Gain_Neg14_dB,
+ LVEQNB_Gain_Neg13_dB,
+ LVEQNB_Gain_Neg12_dB,
+ LVEQNB_Gain_Neg11_dB,
+ LVEQNB_Gain_Neg10_dB,
+ LVEQNB_Gain_Neg9_dB,
+ LVEQNB_Gain_Neg8_dB,
+ LVEQNB_Gain_Neg7_dB,
+ LVEQNB_Gain_Neg6_dB,
+ LVEQNB_Gain_Neg5_dB,
+ LVEQNB_Gain_Neg4_dB,
+ LVEQNB_Gain_Neg3_dB,
+ LVEQNB_Gain_Neg2_dB,
+ LVEQNB_Gain_Neg1_dB,
+ LVEQNB_Gain_0_dB, /* 0dB gain */
+ LVEQNB_Gain_1_dB,
+ LVEQNB_Gain_2_dB,
+ LVEQNB_Gain_3_dB,
+ LVEQNB_Gain_4_dB,
+ LVEQNB_Gain_5_dB,
+ LVEQNB_Gain_6_dB,
+ LVEQNB_Gain_7_dB,
+ LVEQNB_Gain_8_dB,
+ LVEQNB_Gain_9_dB,
+ LVEQNB_Gain_10_dB,
+ LVEQNB_Gain_11_dB,
+ LVEQNB_Gain_12_dB,
+ LVEQNB_Gain_13_dB,
+ LVEQNB_Gain_14_dB,
+ LVEQNB_Gain_15_dB}; /* +15dB gain */
+
+
+/*
+ * D table for 100 / (Gain + 1)
+ */
+const LVM_INT16 LVEQNB_DTable[] = {LVEQNB_100D_Neg15_dB, /* -15dB gain */
+ LVEQNB_100D_Neg14_dB,
+ LVEQNB_100D_Neg13_dB,
+ LVEQNB_100D_Neg12_dB,
+ LVEQNB_100D_Neg11_dB,
+ LVEQNB_100D_Neg10_dB,
+ LVEQNB_100D_Neg9_dB,
+ LVEQNB_100D_Neg8_dB,
+ LVEQNB_100D_Neg7_dB,
+ LVEQNB_100D_Neg6_dB,
+ LVEQNB_100D_Neg5_dB,
+ LVEQNB_100D_Neg4_dB,
+ LVEQNB_100D_Neg3_dB,
+ LVEQNB_100D_Neg2_dB,
+ LVEQNB_100D_Neg1_dB,
+ LVEQNB_100D_0_dB}; /* 0dB gain */
+
+
+/************************************************************************************/
+/* */
+/* Filter polynomial coefficients */
+/* */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ * Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16 LVEQNB_CosCoef[] = {3, /* Shifts */
+ 4096, /* a0 */
+ -36, /* a1 */
+ -19725, /* a2 */
+ -2671, /* a3 */
+ 23730, /* a4 */
+ -9490}; /* a5 */
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ * CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16 LVEQNB_DPCosCoef[] = {1, /* Shifts */
+ 0, /* a0 */
+ -6, /* a1 */
+ 16586, /* a2 */
+ -44}; /* a3 */
+
+/************************************************************************************/
+/* */
+/* Bypass mixer time constants (100ms) */
+/* */
+/************************************************************************************/
+
+#define LVEQNB_MIX_TC_Fs8000 32580 /* Floating point value 0.994262695 */
+#define LVEQNB_MIX_TC_Fs11025 32632 /* Floating point value 0.995849609 */
+#define LVEQNB_MIX_TC_Fs12000 32643 /* Floating point value 0.996185303 */
+#define LVEQNB_MIX_TC_Fs16000 32674 /* Floating point value 0.997131348 */
+#define LVEQNB_MIX_TC_Fs22050 32700 /* Floating point value 0.997924805 */
+#define LVEQNB_MIX_TC_Fs24000 32705 /* Floating point value 0.998077393 */
+#define LVEQNB_MIX_TC_Fs32000 32721 /* Floating point value 0.998565674 */
+#define LVEQNB_MIX_TC_Fs44100 32734 /* Floating point value 0.998962402 */
+#define LVEQNB_MIX_TC_Fs48000 32737 /* Floating point value 0.999053955 */
+
+
+const LVM_INT16 LVEQNB_MixerTCTable[] = {
+ LVEQNB_MIX_TC_Fs8000,
+ LVEQNB_MIX_TC_Fs11025,
+ LVEQNB_MIX_TC_Fs12000,
+ LVEQNB_MIX_TC_Fs16000,
+ LVEQNB_MIX_TC_Fs22050,
+ LVEQNB_MIX_TC_Fs24000,
+ LVEQNB_MIX_TC_Fs32000,
+ LVEQNB_MIX_TC_Fs44100,
+ LVEQNB_MIX_TC_Fs48000};
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
new file mode 100755
index 0000000..b9903b2
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/lib/LVPSA.h
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#ifndef _LVPSA_H_
+#define _LVPSA_H_
+
+
+#include "LVM_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/****************************************************************************************/
+/* */
+/* CONSTANTS DEFINITIONS */
+/* */
+/****************************************************************************************/
+
+/* Memory table*/
+#define LVPSA_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+/****************************************************************************************/
+/* */
+/* TYPES DEFINITIONS */
+/* */
+/****************************************************************************************/
+/* Memory Types */
+typedef enum
+{
+ LVPSA_PERSISTENT = LVM_PERSISTENT,
+ LVPSA_PERSISTENT_DATA = LVM_PERSISTENT_DATA,
+ LVPSA_PERSISTENT_COEF = LVM_PERSISTENT_COEF,
+ LVPSA_SCRATCH = LVM_SCRATCH,
+ LVPSA_MEMORY_DUMMY = LVM_MAXINT_32 /* Force 32 bits enum, don't use it! */
+} LVPSA_MemoryTypes_en;
+
+/* Level detection speed control parameters */
+typedef enum
+{
+ LVPSA_SPEED_LOW, /* Low speed level detection */
+ LVPSA_SPEED_MEDIUM, /* Medium speed level detection */
+ LVPSA_SPEED_HIGH, /* High speed level detection */
+ LVPSA_SPEED_DUMMY = LVM_MAXINT_32 /* Force 32 bits enum, don't use it! */
+} LVPSA_LevelDetectSpeed_en;
+
+/* Filter control parameters */
+typedef struct
+{
+ LVM_UINT16 CenterFrequency; /* Center frequency of the band-pass filter (in Hz) */
+ LVM_UINT16 QFactor; /* Quality factor of the filter (in 1/100) */
+ LVM_INT16 PostGain; /* Postgain to apply after the filtering (in dB Q16.0) */
+
+} LVPSA_FilterParam_t;
+
+/* LVPSA initialization parameters */
+typedef struct
+{
+ LVM_UINT16 SpectralDataBufferDuration; /* Spectral data buffer duration in time (ms in Q16.0) */
+ LVM_UINT16 MaxInputBlockSize; /* Maximum expected input block size (in samples) */
+ LVM_UINT16 nBands; /* Number of bands of the SA */
+ LVPSA_FilterParam_t *pFiltersParams; /* Points to nBands filter param structures for filters settings */
+
+} LVPSA_InitParams_t, *pLVPSA_InitParams_t;
+
+/* LVPSA control parameters */
+typedef struct
+{
+ LVM_Fs_en Fs; /* Input sampling rate */
+ LVPSA_LevelDetectSpeed_en LevelDetectionSpeed; /* Level detection speed */
+
+} LVPSA_ControlParams_t, *pLVPSA_ControlParams_t;
+
+/* Memory region definition */
+typedef struct
+{
+ LVM_UINT32 Size; /* Region size in bytes */
+ LVPSA_MemoryTypes_en Type; /* Region type */
+ void *pBaseAddress; /* Pointer to the region base address */
+} LVPSA_MemoryRegion_t;
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVPSA_MemoryRegion_t Region[LVPSA_NR_MEMORY_REGIONS];/* One definition for each region */
+} LVPSA_MemTab_t;
+
+/* Audio time type */
+typedef LVM_INT32 LVPSA_Time;
+
+/* Module instance Handle */
+typedef void *pLVPSA_Handle_t;
+
+/* LVPSA return codes */
+typedef enum
+{
+ LVPSA_OK, /* The function ran without any problem */
+ LVPSA_ERROR_INVALIDPARAM, /* A parameter is incorrect */
+ LVPSA_ERROR_WRONGTIME, /* An incorrect AudioTime is used */
+ LVPSA_ERROR_NULLADDRESS, /* A pointer has a NULL value */
+ LVPSA_RETURN_DUMMY = LVM_MAXINT_32 /* Force 32 bits enum, don't use it! */
+} LVPSA_RETURN;
+
+
+
+/*********************************************************************************************************************************
+ FUNCTIONS PROTOTYPE
+**********************************************************************************************************************************/
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pInitParams Pointer to the instance init parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Memory ( pLVPSA_Handle_t hInstance,
+ LVPSA_MemTab_t *pMemoryTable,
+ LVPSA_InitParams_t *pInitParams );
+
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Init */
+/* */
+/* DESCRIPTION: */
+/* Initializes the LVPSA module. */
+/* */
+/* */
+/* PARAMETERS: */
+/* phInstance Pointer to the instance Handle */
+/* pInitParams Pointer to the instance init parameters */
+/* pControlParams Pointer to the instance control parameters */
+/* pMemoryTable Pointer to the memory definition table */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Init ( pLVPSA_Handle_t *phInstance,
+ LVPSA_InitParams_t *pInitParams,
+ LVPSA_ControlParams_t *pControlParams,
+ LVPSA_MemTab_t *pMemoryTable );
+
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Control */
+/* */
+/* DESCRIPTION: */
+/* Controls the LVPSA module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pNewParams Pointer to the instance new control parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Control ( pLVPSA_Handle_t hInstance,
+ LVPSA_ControlParams_t *pNewParams );
+
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Process */
+/* */
+/* DESCRIPTION: */
+/* The process calculates the levels of the frequency bands. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pLVPSA_InputSamples Pointer to the input samples buffer */
+/* InputBlockSize Number of mono samples to process */
+/* AudioTime Playback time of the first input sample */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_Process ( pLVPSA_Handle_t hInstance,
+ LVM_INT16 *pLVPSA_InputSamples,
+ LVM_UINT16 InputBlockSize,
+ LVPSA_Time AudioTime );
+
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetSpectrum */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* GetSpectrumAudioTime Time to retrieve the values at */
+/* pCurrentValues Pointer to an empty buffer : Current level values output */
+/* pPeakValues Pointer to an empty buffer : Peak level values output */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_GetSpectrum ( pLVPSA_Handle_t hInstance,
+ LVPSA_Time GetSpectrumAudioTime,
+ LVM_UINT8 *pCurrentValues,
+ LVM_UINT8 *pPeakValues );
+
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetControlParams */
+/* */
+/* DESCRIPTION: */
+/* Get the current control parameters of the LVPSA module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Pointer to an empty control parameters structure */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_GetControlParams ( pLVPSA_Handle_t hInstance,
+ LVPSA_ControlParams_t *pParams );
+
+/*********************************************************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetInitParams */
+/* */
+/* DESCRIPTION: */
+/* Get the initialization parameters of the LVPSA module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Pointer to an empty init parameters structure */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/*********************************************************************************************************************************/
+LVPSA_RETURN LVPSA_GetInitParams ( pLVPSA_Handle_t hInstance,
+ LVPSA_InitParams_t *pParams );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVPSA_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
new file mode 100755
index 0000000..1be8ff0
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
@@ -0,0 +1,715 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "VectorArithmetic.h"
+
+#define LOW_FREQ 298 /* 32768/110 for low test frequency */
+#define HIGH_FREQ 386 /* 32768/85 for high test frequency */
+
+LVPSA_RETURN LVPSA_SetBPFiltersType ( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams );
+
+LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams );
+
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C16_Coefs_t *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C32_Coefs_t *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C32_Coefs_t *pCoefficients);
+
+LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams );
+
+LVPSA_RETURN LVPSA_ClearFilterHistory( LVPSA_InstancePr_t *pInst);
+
+
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Control */
+/* */
+/* DESCRIPTION: */
+/* Give some new control parameters to the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* NewParams Structure that contains the new parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Control ( pLVPSA_Handle_t hInstance,
+ LVPSA_ControlParams_t *pNewParams )
+{
+
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+ if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ if(pNewParams->Fs >= LVPSA_NR_SUPPORTED_RATE)
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ if(pNewParams->LevelDetectionSpeed >= LVPSA_NR_SUPPORTED_SPEED)
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+
+ pLVPSA_Inst->NewParams = *pNewParams;
+ pLVPSA_Inst->bControlPending = LVM_TRUE;
+
+ return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetControlParams */
+/* */
+/* DESCRIPTION: */
+/* Get the current control parameters of the module */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* pParams Pointer to an empty control structure */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetControlParams ( pLVPSA_Handle_t hInstance,
+ LVPSA_ControlParams_t *pParams )
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+ if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+ pParams->Fs = pLVPSA_Inst->CurrentParams.Fs;
+ pParams->LevelDetectionSpeed = pLVPSA_Inst->CurrentParams.LevelDetectionSpeed;
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetInitParams */
+/* */
+/* DESCRIPTION: */
+/* Get the initialization parameters of the module */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* pParams Pointer to an empty control structure */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetInitParams ( pLVPSA_Handle_t hInstance,
+ LVPSA_InitParams_t *pParams )
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+ if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+ pParams->SpectralDataBufferDuration = pLVPSA_Inst->SpectralDataBufferDuration;
+ pParams->MaxInputBlockSize = pLVPSA_Inst->MaxInputBlockSize;
+ pParams->nBands = pLVPSA_Inst->nBands;
+ pParams->pFiltersParams = pLVPSA_Inst->pFiltersParams;
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Reinitialize some parameters and changes filters' coefficients if */
+/* some control parameters have changed. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t *pInst)
+{
+ LVM_UINT16 ii;
+ LVM_UINT16 Freq;
+ LVPSA_ControlParams_t Params;
+ extern LVM_INT16 LVPSA_nSamplesBufferUpdate[];
+ extern LVM_UINT16 LVPSA_SampleRateTab[];
+ extern LVM_UINT16 LVPSA_DownSamplingFactor[];
+
+
+ if(pInst == 0)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+ Params = pInst->NewParams;
+
+ /* Modifies filters types and coefficients, clear the taps and
+ re-initializes parameters if sample frequency has changed */
+ if(Params.Fs != pInst->CurrentParams.Fs)
+ {
+ pInst->CurrentParams.Fs = Params.Fs;
+
+ /* Initialize the center freqeuncies as a function of the sample rate */
+ Freq = (LVM_UINT16) ((LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1) / (pInst->nBands + 1));
+ for(ii = pInst->nBands; ii > 0; ii--)
+ {
+ pInst->pFiltersParams[ii-1].CenterFrequency = (LVM_UINT16) (Freq * ii);
+ }
+
+ /* Count the number of relevant filters. If the center frequency of the filter is
+ bigger than the nyquist frequency, then the filter is not relevant and doesn't
+ need to be used */
+ for(ii = pInst->nBands; ii > 0; ii--)
+ {
+ if(pInst->pFiltersParams[ii-1].CenterFrequency < (LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1))
+ {
+ pInst->nRelevantFilters = ii;
+ break;
+ }
+ }
+ LVPSA_SetBPFiltersType(pInst, &Params);
+ LVPSA_SetBPFCoefficients(pInst, &Params);
+ LVPSA_SetQPFCoefficients(pInst, &Params);
+ LVPSA_ClearFilterHistory(pInst);
+ pInst->nSamplesBufferUpdate = (LVM_UINT16)LVPSA_nSamplesBufferUpdate[Params.Fs];
+ pInst->BufferUpdateSamplesCount = 0;
+ pInst->DownSamplingFactor = LVPSA_DownSamplingFactor[Params.Fs];
+ pInst->DownSamplingCount = 0;
+ for(ii = 0; ii < (pInst->nBands * pInst->SpectralDataBufferLength); ii++)
+ {
+ pInst->pSpectralDataBufferStart[ii] = 0;
+ }
+ for(ii = 0; ii < pInst->nBands; ii++)
+ {
+ pInst->pPreviousPeaks[ii] = 0;
+ }
+ }
+ else
+ {
+ if(Params.LevelDetectionSpeed != pInst->CurrentParams.LevelDetectionSpeed)
+ {
+ LVPSA_SetQPFCoefficients(pInst, &Params);
+ }
+ }
+
+ pInst->CurrentParams = pInst->NewParams;
+
+ return (LVPSA_OK);
+}
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_SetBPFiltersType */
+/* */
+/* DESCRIPTION: */
+/* Sets the filter type based on the BPFilterType. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* pParams Poniter to conrol parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* 1. To select the biquad type the follow rules are applied: */
+/* Double precision if (fc <= fs/110) */
+/* Double precision if (fs/110 < fc < fs/85) & (Q>3) */
+/* Single precision otherwise */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFiltersType ( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams )
+{
+
+ extern LVM_UINT16 LVPSA_SampleRateTab[]; /* Sample rate table */
+ LVM_UINT16 ii; /* Filter band index */
+ LVM_UINT32 fs = (LVM_UINT32)LVPSA_SampleRateTab[(LVM_UINT16)pParams->Fs]; /* Sample rate */
+ LVM_UINT32 fc; /* Filter centre frequency */
+ LVM_INT16 QFactor; /* Filter Q factor */
+
+ for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+ {
+ /*
+ * Get the filter settings
+ */
+ fc = (LVM_UINT32)pInst->pFiltersParams[ii].CenterFrequency; /* Get the band centre frequency */
+ QFactor =(LVM_INT16) pInst->pFiltersParams[ii].QFactor; /* Get the band Q factor */
+
+
+ /*
+ * For each filter set the type of biquad required
+ */
+ pInst->pBPFiltersPrecision[ii] = LVPSA_SimplePrecisionFilter; /* Default to single precision */
+ if ((LOW_FREQ * fs) >= (fc << 15))
+ {
+ /*
+ * fc <= fs/110
+ */
+ pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+ }
+ else
+ {
+ if (((LOW_FREQ * fs) < (fc << 15)) && ((fc << 15) < (HIGH_FREQ * fs)) && (QFactor > 300))
+ {
+ /*
+ * (fs/110 < fc < fs/85) & (Q>3)
+ */
+ pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+ }
+ }
+ }
+
+ return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_SetBPFCoefficients */
+/* */
+/* DESCRIPTION: */
+/* Sets the band pass filter coefficients. This uses the type to select */
+/* single or double precision coefficients. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* Params Initialisation parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams)
+{
+
+ LVM_UINT16 ii;
+
+ /*
+ * Set the coefficients for each band by the init function
+ */
+ for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+ {
+ switch (pInst->pBPFiltersPrecision[ii])
+ {
+ case LVPSA_DoublePrecisionFilter:
+ {
+ BP_C32_Coefs_t Coefficients;
+
+ /*
+ * Calculate the double precision coefficients
+ */
+ LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
+ &pInst->pFiltersParams[ii],
+ &Coefficients);
+
+ /*
+ * Set the coefficients
+ */
+ BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+ &pInst->pBP_Taps[ii],
+ &Coefficients);
+ break;
+ }
+
+ case LVPSA_SimplePrecisionFilter:
+ {
+ BP_C16_Coefs_t Coefficients;
+
+ /*
+ * Calculate the single precision coefficients
+ */
+ LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
+ &pInst->pFiltersParams[ii],
+ &Coefficients);
+
+ /*
+ * Set the coefficients
+ */
+ BP_1I_D16F16Css_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+ &pInst->pBP_Taps[ii],
+ &Coefficients);
+ break;
+ }
+ }
+ }
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_SetQPFCoefficients */
+/* */
+/* DESCRIPTION: */
+/* Sets the quasi peak filters coefficients. This uses the chosen */
+/* LevelDetectionSpeed from the control parameters. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* Params Control parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams )
+{
+ LVM_UINT16 ii;
+ LVM_Fs_en Fs = pParams->Fs;
+ QPD_C32_Coefs *pCoefficients;
+ extern QPD_C32_Coefs LVPSA_QPD_Coefs[];
+
+
+ pCoefficients = &LVPSA_QPD_Coefs[(pParams->LevelDetectionSpeed * LVPSA_NR_SUPPORTED_RATE) + Fs];
+
+
+ for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+ {
+ LVPSA_QPD_Init (&pInst->pQPD_States[ii],
+ &pInst->pQPD_Taps[ii],
+ pCoefficients );
+ }
+
+ return(LVPSA_OK);
+
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_BPSinglePrecCoefs */
+/* */
+/* DESCRIPTION: */
+/* Calculate single precision coefficients for a band pass filter */
+/* */
+/* PARAMETERS: */
+/* Fs Sampling frequency index */
+/* pFilterParams Pointer to the filter definition */
+/* pCoefficients Pointer to the coefficients */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The equations used are as follows: */
+/* */
+/* t0 = 2 * Pi * Fc / Fs */
+/* */
+/* b2 = -0.5 * (2Q - t0) / (2Q + t0) */
+/* b1 = (0.5 - b2) * cos(t0) */
+/* a0 = (0.5 + b2) / 2 */
+/* */
+/* Where: */
+/* Fc is the centre frequency, DC to Nyquist */
+/* Fs is the sample frequency, 8000 to 48000 in descrete steps */
+/* Q is the Q factor, 0.25 to 12 */
+/* */
+/* 2. This function is entirely based on the LVEQNB_SinglePrecCoefs function */
+/* of the n bands equalizer (LVEQNB */
+/* */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C16_Coefs_t *pCoefficients)
+{
+
+ extern LVM_INT16 LVPSA_TwoPiOnFsTable[];
+ extern LVM_INT16 LVPSA_CosCoef[];
+
+
+ /*
+ * Intermediate variables and temporary values
+ */
+ LVM_INT32 T0;
+ LVM_INT16 D;
+ LVM_INT32 A0;
+ LVM_INT32 B1;
+ LVM_INT32 B2;
+ LVM_INT32 Dt0;
+ LVM_INT32 B2_Den;
+ LVM_INT32 B2_Num;
+ LVM_INT32 COS_T0;
+ LVM_INT16 coef;
+ LVM_INT32 factor;
+ LVM_INT16 t0;
+ LVM_INT16 i;
+
+
+ /*
+ * Get the filter definition
+ */
+ LVM_UINT16 Frequency = pFilterParams->CenterFrequency;
+ LVM_UINT16 QFactor = pFilterParams->QFactor;
+
+
+ /*
+ * Calculating the intermediate values
+ */
+ T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */
+ D = 3200; /* Floating point value 1.000000 (1*100*2^5) */
+ /* Force D = 1 : the function was originally used for a peaking filter.
+ The D parameter do not exist for a BandPass filter coefficients */
+
+ /*
+ * Calculate the B2 coefficient
+ */
+ Dt0 = D * (T0 >> 10);
+ B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
+ B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
+ B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+ /*
+ * Calculate the cosine by a polynomial expansion using the equation:
+ *
+ * Cos += coef(n) * t0^n For n = 0 to 6
+ */
+ T0 = (T0 >> 10) * 20859; /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+ t0 = (LVM_INT16)(T0 >> 16);
+ factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */
+ COS_T0 = 0; /* Initialise the error to zero */
+ for (i=1; i<7; i++)
+ {
+ coef = LVPSA_CosCoef[i]; /* Get the nth coefficient */
+ COS_T0 += (factor * coef) >> 5; /* The nth partial sum */
+ factor = (factor * t0) >> 15; /* Calculate t0^n */
+ }
+ COS_T0 = COS_T0 << (LVPSA_CosCoef[0]+6); /* Correct the scaling */
+
+
+ B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16); /* B1 = (0.5 - b2) * cos(t0) */
+ A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) / 2 */
+
+ /*
+ * Write coeff into the data structure
+ */
+ pCoefficients->A0 = (LVM_INT16)(A0>>16);
+ pCoefficients->B1 = (LVM_INT16)(B1>>15);
+ pCoefficients->B2 = (LVM_INT16)(B2>>16);
+
+
+ return(LVPSA_OK);
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_BPDoublePrecCoefs */
+/* */
+/* DESCRIPTION: */
+/* Calculate double precision coefficients for a band pass filter */
+/* */
+/* PARAMETERS: */
+/* Fs Sampling frequency index */
+/* pFilterParams Pointer to the filter definition */
+/* pCoefficients Pointer to the coefficients */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The equations used are as follows: */
+/* */
+/* t0 = 2 * Pi * Fc / Fs */
+/* */
+/* b2 = -0.5 * (2Q - t0) / (2Q + t0) */
+/* b1 = (0.5 - b2) * (1 - coserr(t0)) */
+/* a0 = (0.5 + b2) / 2 */
+/* */
+/* Where: */
+/* Fc is the centre frequency, DC to Fs/50 */
+/* Fs is the sample frequency, 8000 to 48000 in descrete steps */
+/* Q is the Q factor, 0.25 to 12 (represented by 25 to 1200) */
+/* */
+/* 2. The double precision coefficients are only used when fc is less than fs/85, so */
+/* the cosine of t0 is always close to 1.0. Instead of calculating the cosine */
+/* itself the difference from the value 1.0 is calculated, this can be done with */
+/* lower precision maths. */
+/* */
+/* 3. The value of the B2 coefficient is only calculated as a single precision value, */
+/* small errors in this value have a combined effect on the Q and Gain but not the */
+/* the frequency of the filter. */
+/* */
+/* 4. This function is entirely based on the LVEQNB_DoublePrecCoefs function */
+/* of the n bands equalizer (LVEQNB */
+/* */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C32_Coefs_t *pCoefficients)
+{
+
+ extern LVM_INT16 LVPSA_TwoPiOnFsTable[];
+ extern LVM_INT16 LVPSA_DPCosCoef[];
+
+ /*
+ * Intermediate variables and temporary values
+ */
+ LVM_INT32 T0;
+ LVM_INT16 D;
+ LVM_INT32 A0;
+ LVM_INT32 B1;
+ LVM_INT32 B2;
+ LVM_INT32 Dt0;
+ LVM_INT32 B2_Den;
+ LVM_INT32 B2_Num;
+ LVM_INT32 CosErr;
+ LVM_INT16 coef;
+ LVM_INT32 factor;
+ LVM_INT16 t0;
+ LVM_INT16 i;
+
+ /*
+ * Get the filter definition
+ */
+ LVM_UINT16 Frequency = pFilterParams->CenterFrequency;
+ LVM_UINT16 QFactor = pFilterParams->QFactor;
+
+
+ /*
+ * Calculating the intermediate values
+ */
+ T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */
+ D = 3200; /* Floating point value 1.000000 (1*100*2^5) */
+ /* Force D = 1 : the function was originally used for a peaking filter.
+ The D parameter do not exist for a BandPass filter coefficients */
+
+ /*
+ * Calculate the B2 coefficient
+ */
+ Dt0 = D * (T0 >> 10);
+ B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
+ B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
+ B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+ /*
+ * Calculate the cosine error by a polynomial expansion using the equation:
+ *
+ * CosErr += coef(n) * t0^n For n = 0 to 4
+ */
+ T0 = (T0 >> 6) * 0x7f53; /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+ t0 = (LVM_INT16)(T0 >> 16);
+ factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */
+ CosErr = 0; /* Initialise the error to zero */
+ for (i=1; i<5; i++)
+ {
+ coef = LVPSA_DPCosCoef[i]; /* Get the nth coefficient */
+ CosErr += (factor * coef) >> 5; /* The nth partial sum */
+ factor = (factor * t0) >> 15; /* Calculate t0^n */
+ }
+ CosErr = CosErr << (LVPSA_DPCosCoef[0]); /* Correct the scaling */
+
+ /*
+ * Calculate the B1 and A0 coefficients
+ */
+ B1 = (0x40000000 - B2); /* B1 = (0.5 - b2) */
+ A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6; /* Temporary storage for (0.5 - b2) * coserr(t0) */
+ B1 -= A0; /* B1 = (0.5 - b2) * (1 - coserr(t0)) */
+ A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) / 2 */
+
+ /*
+ * Write coeff into the data structure
+ */
+ pCoefficients->A0 = A0;
+ pCoefficients->B1 = B1;
+ pCoefficients->B2 = B2;
+
+ return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_ClearFilterHistory */
+/* */
+/* DESCRIPTION: */
+/* Clears the filters' data history */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t *pInst)
+{
+ LVM_INT8 *pTapAddress;
+ LVM_UINT32 i;
+
+ /* Band Pass filters taps */
+ pTapAddress = (LVM_INT8 *)pInst->pBP_Taps;
+ for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_Taps_t); i++)
+ {
+ pTapAddress[i] = 0;
+ }
+
+ /* Quasi-peak filters taps */
+ pTapAddress = (LVM_INT8 *)pInst->pQPD_Taps;
+ for(i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++)
+ {
+ pTapAddress[i] = 0;
+ }
+
+ return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
new file mode 100755
index 0000000..ab45678
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "InstAlloc.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Init */
+/* */
+/* DESCRIPTION: */
+/* Initialize the LVPSA module */
+/* */
+/* */
+/* PARAMETERS: */
+/* phInstance Pointer to pointer to the instance */
+/* InitParams Init parameters structure */
+/* ControlParams Control parameters structure */
+/* pMemoryTable Memory table that contains memory areas definition */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Init ( pLVPSA_Handle_t *phInstance,
+ LVPSA_InitParams_t *pInitParams,
+ LVPSA_ControlParams_t *pControlParams,
+ LVPSA_MemTab_t *pMemoryTable )
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst;
+ LVPSA_RETURN errorCode = LVPSA_OK;
+ LVM_UINT32 ii;
+ extern LVM_INT16 LVPSA_GainTable[];
+ LVM_UINT32 BufferLength = 0;
+
+ /* Ints_Alloc instances, needed for memory alignment management */
+ INST_ALLOC Instance;
+ INST_ALLOC Scratch;
+ INST_ALLOC Data;
+ INST_ALLOC Coef;
+
+ /* Check parameters */
+ if((phInstance == LVM_NULL) || (pInitParams == LVM_NULL) || (pControlParams == LVM_NULL) || (pMemoryTable == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION) ||
+ (pInitParams->SpectralDataBufferDuration == 0) ||
+ (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE) ||
+ (pInitParams->MaxInputBlockSize == 0) ||
+ (pInitParams->nBands < LVPSA_NBANDSMIN) ||
+ (pInitParams->nBands > LVPSA_NBANDSMAX) ||
+ (pInitParams->pFiltersParams == 0))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ for(ii = 0; ii < pInitParams->nBands; ii++)
+ {
+ if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+ (pInitParams->pFiltersParams[ii].PostGain > LVPSA_MAXPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].PostGain < LVPSA_MINPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR) ||
+ (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ }
+
+
+ /*Inst_Alloc instances initialization */
+ InstAlloc_Init( &Instance , pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress);
+ InstAlloc_Init( &Scratch , pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress);
+ InstAlloc_Init( &Data , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+ InstAlloc_Init( &Coef , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+
+ /* Set the instance handle if not already initialised */
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+ }
+ pLVPSA_Inst =(LVPSA_InstancePr_t*)*phInstance;
+
+
+ /* Check the memory table for NULL pointers */
+ for (ii = 0; ii < LVPSA_NR_MEMORY_REGIONS; ii++)
+ {
+ if (pMemoryTable->Region[ii].Size!=0)
+ {
+ if (pMemoryTable->Region[ii].pBaseAddress==LVM_NULL)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ pLVPSA_Inst->MemoryTable.Region[ii] = pMemoryTable->Region[ii];
+ }
+ }
+
+ /* Initialize module's internal parameters */
+ pLVPSA_Inst->bControlPending = LVM_FALSE;
+ pLVPSA_Inst->nBands = pInitParams->nBands;
+ pLVPSA_Inst->MaxInputBlockSize = pInitParams->MaxInputBlockSize;
+ pLVPSA_Inst->SpectralDataBufferDuration = pInitParams->SpectralDataBufferDuration;
+ pLVPSA_Inst->CurrentParams.Fs = LVM_FS_DUMMY;
+ pLVPSA_Inst->CurrentParams.LevelDetectionSpeed = LVPSA_SPEED_DUMMY;
+
+ { /* for avoiding QAC warnings */
+ LVM_INT32 SDBD=(LVM_INT32)pLVPSA_Inst->SpectralDataBufferDuration;
+ LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+ LVM_INT32 BL;
+
+ MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+
+ BufferLength=(LVM_UINT32)BL;
+ }
+
+ if((BufferLength * LVPSA_InternalRefreshTime) != pLVPSA_Inst->SpectralDataBufferDuration)
+ {
+ pLVPSA_Inst->SpectralDataBufferLength = BufferLength + 1;
+ }
+ else
+ {
+ pLVPSA_Inst->SpectralDataBufferLength = BufferLength;
+ }
+
+
+ /* Assign the pointers */
+
+ pLVPSA_Inst->pPostGains = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+ pLVPSA_Inst->pFiltersParams = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+ pLVPSA_Inst->pSpectralDataBufferStart = InstAlloc_AddMember( &Instance, pInitParams->nBands * pLVPSA_Inst->SpectralDataBufferLength * sizeof(LVM_UINT8) );
+ pLVPSA_Inst->pPreviousPeaks = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+ pLVPSA_Inst->pBPFiltersPrecision = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+
+ pLVPSA_Inst->pBP_Instances = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
+ pLVPSA_Inst->pQPD_States = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+
+ pLVPSA_Inst->pBP_Taps = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
+ pLVPSA_Inst->pQPD_Taps = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+
+
+ /* Copy filters parameters in the private instance */
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pLVPSA_Inst->pFiltersParams[ii] = pInitParams->pFiltersParams[ii];
+ }
+
+ /* Set Post filters gains*/
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pLVPSA_Inst->pPostGains[ii] =(LVM_UINT16) LVPSA_GainTable[pInitParams->pFiltersParams[ii].PostGain + 15];
+ }
+ pLVPSA_Inst->pSpectralDataBufferWritePointer = pLVPSA_Inst->pSpectralDataBufferStart;
+
+
+ /* Initialize control dependant internal parameters */
+ errorCode = LVPSA_Control (*phInstance, pControlParams);
+
+ if(errorCode!=0)
+ {
+ return errorCode;
+ }
+
+ errorCode = LVPSA_ApplyNewSettings (pLVPSA_Inst);
+
+ if(errorCode!=0)
+ {
+ return errorCode;
+ }
+
+ return(errorCode);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
new file mode 100755
index 0000000..059cb4e
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVEQNB_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) the memory */
+/* base address pointers are NULL on return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the memory */
+/* table returns the allocated memory and base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* InitParams Pointer to the instance init parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_Memory ( pLVPSA_Handle_t hInstance,
+ LVPSA_MemTab_t *pMemoryTable,
+ LVPSA_InitParams_t *pInitParams )
+{
+ LVM_UINT32 ii;
+ LVM_UINT32 BufferLength;
+ INST_ALLOC Instance;
+ INST_ALLOC Scratch;
+ INST_ALLOC Data;
+ INST_ALLOC Coef;
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+
+ InstAlloc_Init( &Instance , LVM_NULL);
+ InstAlloc_Init( &Scratch , LVM_NULL);
+ InstAlloc_Init( &Data , LVM_NULL);
+ InstAlloc_Init( &Coef , LVM_NULL);
+
+
+ if((pMemoryTable == LVM_NULL) || (pInitParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+
+ /* Check init parameter */
+ if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION) ||
+ (pInitParams->SpectralDataBufferDuration == 0) ||
+ (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE) ||
+ (pInitParams->MaxInputBlockSize == 0) ||
+ (pInitParams->nBands < LVPSA_NBANDSMIN) ||
+ (pInitParams->nBands > LVPSA_NBANDSMAX) ||
+ (pInitParams->pFiltersParams == 0))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ for(ii = 0; ii < pInitParams->nBands; ii++)
+ {
+ if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+ (pInitParams->pFiltersParams[ii].PostGain > LVPSA_MAXPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].PostGain < LVPSA_MINPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR) ||
+ (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ }
+
+ /*
+ * Instance memory
+ */
+
+ InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+
+ {
+ /* for avoiding QAC warnings as MUL32x32INTO32 works on LVM_INT32 only*/
+ LVM_INT32 SDBD=(LVM_INT32)pInitParams->SpectralDataBufferDuration;
+ LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+ LVM_INT32 BL;
+
+ MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+ BufferLength=(LVM_UINT32)BL;
+ }
+
+
+ if((BufferLength * LVPSA_InternalRefreshTime) != pInitParams->SpectralDataBufferDuration)
+ {
+ BufferLength++;
+ }
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * BufferLength * sizeof(LVM_UINT8) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+ pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Size = InstAlloc_GetTotal(&Instance);
+ pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Type = LVPSA_PERSISTENT;
+ pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+ /*
+ * Scratch memory
+ */
+ InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_INT16) );
+ pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Size = InstAlloc_GetTotal(&Scratch);
+ pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Type = LVPSA_SCRATCH;
+ pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+
+ /*
+ * Persistent coefficients memory
+ */
+ InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
+ InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Size = InstAlloc_GetTotal(&Coef);
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Type = LVPSA_PERSISTENT_COEF;
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+ /*
+ * Persistent data memory
+ */
+ InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
+ InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Size = InstAlloc_GetTotal(&Data);
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Type = LVPSA_PERSISTENT_DATA;
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+ }
+ else
+ {
+ /* Read back memory allocation table */
+ *pMemoryTable = pLVPSA_Inst->MemoryTable;
+ }
+
+ return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
new file mode 100755
index 0000000..eb9fa8f
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#ifndef _LVPSA_PRIVATE_H_
+#define _LVPSA_PRIVATE_H_
+
+#include "LVPSA.h"
+#include "BIQUAD.h"
+#include "LVPSA_QPD.h"
+#include "LVM_Macros.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+ CONSTANT DEFINITIONS
+***********************************************************************************/
+
+/* Memory */
+#define LVPSA_INSTANCE_ALIGN 4 /* 32-bit alignment for structures */
+#define LVPSA_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
+#define LVPSA_COEF_ALIGN 4 /* 32-bit alignment for long words */
+#define LVPSA_DATA_ALIGN 4 /* 32-bit alignment for long data */
+
+#define LVPSA_MEMREGION_INSTANCE 0 /* Offset to instance memory region in memory table */
+#define LVPSA_MEMREGION_PERSISTENT_COEF 1 /* Offset to persistent coefficients memory region in memory table */
+#define LVPSA_MEMREGION_PERSISTENT_DATA 2 /* Offset to persistent taps memory region in memory table */
+#define LVPSA_MEMREGION_SCRATCH 3 /* Offset to scratch memory region in memory table */
+
+#define LVPSA_NR_SUPPORTED_RATE 9 /* From 8000Hz to 48000Hz */
+#define LVPSA_NR_SUPPORTED_SPEED 3 /* LOW, MEDIUM, HIGH */
+
+#define LVPSA_MAXBUFFERDURATION 4000 /* Maximum length in ms of the levels buffer */
+#define LVPSA_MAXINPUTBLOCKSIZE 5000 /* Maximum length in mono samples of the block to process */
+#define LVPSA_NBANDSMIN 1 /* Minimum number of frequency band */
+#define LVPSA_NBANDSMAX 30 /* Maximum number of frequency band */
+#define LVPSA_MAXCENTERFREQ 20000 /* Maximum possible center frequency */
+#define LVPSA_MINPOSTGAIN -15 /* Minimum possible post gain */
+#define LVPSA_MAXPOSTGAIN 15 /* Maximum possible post gain */
+#define LVPSA_MINQFACTOR 25 /* Minimum possible Q factor */
+#define LVPSA_MAXQFACTOR 1200 /* Maximum possible Q factor */
+
+#define LVPSA_MAXLEVELDECAYFACTOR 0x4111 /* Decay factor for the maximum values calculation */
+#define LVPSA_MAXLEVELDECAYSHIFT 14 /* Decay shift for the maximum values calculation */
+
+#define LVPSA_MAXUNSIGNEDCHAR 0xFF
+
+#define LVPSA_FsInvertShift 31
+#define LVPSA_GAINSHIFT 11
+#define LVPSA_FREQSHIFT 25
+
+/**********************************************************************************
+ TYPES DEFINITIONS
+***********************************************************************************/
+
+#define LVPSA_InternalRefreshTime 0x0014 /* 20 ms (50Hz) in Q16.0 */
+#define LVPSA_InternalRefreshTimeInv 0x0666 /* 1/20ms left shifted by 15 */
+#define LVPSA_InternalRefreshTimeShift 15
+
+
+/* Precision of the filter */
+typedef enum
+{
+ LVPSA_SimplePrecisionFilter, /* Simple precision */
+ LVPSA_DoublePrecisionFilter /* Double precision */
+} LVPSA_BPFilterPrecision_en;
+
+typedef struct
+{
+ LVM_CHAR bControlPending; /* Flag incating a change of the control parameters */
+ LVM_UINT16 nBands; /* Number of bands of the spectrum analyzer */
+ LVM_UINT16 MaxInputBlockSize; /* Maximum input data buffer size */
+
+ LVPSA_ControlParams_t CurrentParams; /* Current control parameters of the module */
+ LVPSA_ControlParams_t NewParams; /* New control parameters given by the user */
+ LVPSA_MemTab_t MemoryTable;
+
+ LVPSA_BPFilterPrecision_en *pBPFiltersPrecision; /* Points a nBands elements array that contains the filter precision for each band */
+ Biquad_Instance_t *pBP_Instances; /* Points a nBands elements array that contains the band pass filter instance for each band */
+ Biquad_1I_Order2_Taps_t *pBP_Taps; /* Points a nBands elements array that contains the band pass filter taps for each band */
+ QPD_State_t *pQPD_States; /* Points a nBands elements array that contains the QPD filter instance for each band */
+ QPD_Taps_t *pQPD_Taps; /* Points a nBands elements array that contains the QPD filter taps for each band */
+ LVM_UINT16 *pPostGains; /* Points a nBands elements array that contains the post-filter gains for each band */
+
+ LVPSA_FilterParam_t *pFiltersParams; /* Copy of the filters parameters from the input parameters */
+
+
+ LVM_UINT16 nSamplesBufferUpdate; /* Number of samples to make 20ms */
+ LVM_INT32 BufferUpdateSamplesCount; /* Counter used to know when to put a new value in the buffer */
+ LVM_UINT16 nRelevantFilters; /* Number of relevent filters depending on sampling frequency and bands center frequency */
+ LVM_UINT16 LocalSamplesCount; /* Counter used to update the SpectralDataBufferAudioTime */
+
+ LVM_UINT16 DownSamplingFactor; /* Down sampling factor depending on the sampling frequency */
+ LVM_UINT16 DownSamplingCount; /* Counter used for the downsampling handling */
+
+ LVM_UINT16 SpectralDataBufferDuration; /* Length of the buffer in time (ms) defined by the application */
+ LVM_UINT8 *pSpectralDataBufferStart; /* Starting address of the buffer */
+ LVM_UINT8 *pSpectralDataBufferWritePointer; /* Current position of the writting pointer of the buffer */
+ LVPSA_Time SpectralDataBufferAudioTime; /* AudioTime at which the last value save occured in the buffer */
+ LVM_UINT32 SpectralDataBufferLength; /* Number of spectrum data value that the buffer can contain (per band)
+ = SpectralDataBufferDuration/20ms */
+
+ LVM_UINT8 *pPreviousPeaks; /* Points to a nBands elements array that contains the previous peak value of the level
+ detection. Those values are decremented after each call to the GetSpectrum function */
+
+}LVPSA_InstancePr_t, *pLVPSA_InstancePr_t;
+
+
+
+/**********************************************************************************
+ FUNCTIONS PROTOTYPE
+***********************************************************************************/
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Reinitialize some parameters and changes filters' coefficients if */
+/* some control parameters have changed. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t *pInst);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVPSA_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
new file mode 100755
index 0000000..d88a751
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "LVM_Macros.h"
+#include "VectorArithmetic.h"
+
+#define LVM_MININT_32 0x80000000
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Process */
+/* */
+/* DESCRIPTION: */
+/* The process applies band pass filters to the signal. Each output */
+/* feeds a quasi peak filter for level detection. */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* pLVPSA_InputSamples Pointer to the input samples buffer */
+/* InputBlockSize Number of mono samples to process */
+/* AudioTime Playback time of the input samples */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Process ( pLVPSA_Handle_t hInstance,
+ LVM_INT16 *pLVPSA_InputSamples,
+ LVM_UINT16 InputBlockSize,
+ LVPSA_Time AudioTime )
+
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+ LVM_INT16 *pScratch;
+ LVM_INT16 ii;
+ LVM_INT32 AudioTimeInc;
+ extern LVM_UINT32 LVPSA_SampleRateInvTab[];
+ LVM_UINT8 *pWrite_Save; /* Position of the write pointer at the beginning of the process */
+
+ /******************************************************************************
+ CHECK PARAMETERS
+ *******************************************************************************/
+ if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+
+ pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
+ pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+
+ /******************************************************************************
+ APPLY NEW SETTINGS IF NEEDED
+ *******************************************************************************/
+ if (pLVPSA_Inst->bControlPending == LVM_TRUE)
+ {
+ pLVPSA_Inst->bControlPending = 0;
+ LVPSA_ApplyNewSettings( pLVPSA_Inst);
+ }
+
+ /******************************************************************************
+ PROCESS SAMPLES
+ *******************************************************************************/
+ /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
+ Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize);
+ Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize);
+
+ for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
+ {
+ switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
+ {
+ case LVPSA_SimplePrecisionFilter:
+ BP_1I_D16F16C14_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
+ pScratch,
+ pScratch + InputBlockSize,
+ (LVM_INT16)InputBlockSize);
+ break;
+
+ case LVPSA_DoublePrecisionFilter:
+ BP_1I_D16F32C30_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
+ pScratch,
+ pScratch + InputBlockSize,
+ (LVM_INT16)InputBlockSize);
+ break;
+ default:
+ break;
+ }
+
+
+ LVPSA_QPD_Process ( pLVPSA_Inst,
+ pScratch + InputBlockSize,
+ (LVM_INT16)InputBlockSize,
+ ii);
+ }
+
+ /******************************************************************************
+ UPDATE SpectralDataBufferAudioTime
+ *******************************************************************************/
+
+ if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
+ {
+ MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
+ (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
+ AudioTimeInc,
+ LVPSA_FsInvertShift)
+ pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
+ }
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetSpectrum */
+/* */
+/* DESCRIPTION: */
+/* Gets the levels values at a certain point in time */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* GetSpectrumAudioTime Retrieve the values at this time */
+/* pCurrentValues Pointer to a buffer that will contain levels' values */
+/* pMaxValues Pointer to a buffer that will contain max levels' values */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetSpectrum ( pLVPSA_Handle_t hInstance,
+ LVPSA_Time GetSpectrumAudioTime,
+ LVM_UINT8 *pCurrentValues,
+ LVM_UINT8 *pPeakValues )
+
+{
+
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+ LVM_INT32 StatusDelta, ii;
+ LVM_UINT8 *pRead;
+
+ if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+
+ /* First find the place where to look in the status buffer */
+ if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
+ {
+ MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
+ if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
+ {
+ StatusDelta += 1;
+ }
+ }
+ else
+ {
+ /* This part handles the wrap around */
+ MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
+ if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
+ {
+ StatusDelta += 1;
+ }
+ }
+ /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
+ if(
+ ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+ ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
+ (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
+
+ ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+ (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
+ ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
+ (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
+ (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
+
+ (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
+ (!StatusDelta))
+ {
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pCurrentValues[ii] = 0;
+ pPeakValues[ii] = 0;
+ }
+ return(LVPSA_OK);
+ }
+ /* Set the reading pointer */
+ if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
+ {
+ pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
+ }
+ else
+ {
+ pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer - StatusDelta * pLVPSA_Inst->nBands;
+ }
+
+
+ /* Read the status buffer and fill the output buffers */
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pCurrentValues[ii] = pRead[ii];
+ if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
+ {
+ pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
+ }
+ else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
+ {
+ LVM_INT32 temp;
+ /*Re-compute max values for decay */
+ temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
+ temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
+ /* If the gain has no effect, "help" the value to increase */
+ if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
+ {
+ temp += 1;
+ }
+ /* Saturate */
+ temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
+ /* Store new max level */
+ pLVPSA_Inst->pPreviousPeaks[ii] = (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
+ }
+
+ pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
+ }
+
+ return(LVPSA_OK);
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
new file mode 100755
index 0000000..641357e
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#ifndef _LVPSA_QPD_H_
+#define _LVPSA_QPD_H_
+
+#include "LVM_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct
+{
+ LVM_INT32 *pDelay; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 Coefs[2]; /* pointer to the filter coefficients */
+}QPD_State_t, *pQPD_State_t;
+
+typedef struct
+{
+ LVM_INT32 KP; /*should store a0*/
+ LVM_INT32 KM; /*should store b2*/
+
+} QPD_C32_Coefs, *PQPD_C32_Coefs;
+
+typedef struct
+{
+ LVM_INT32 Storage[1];
+
+} QPD_Taps_t, *pQPD_Taps_t;
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Process */
+/* */
+/* DESCRIPTION: */
+/* Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/* in the buffer every 20 ms. */
+/* */
+/* PARAMETERS: */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Process ( void *hInstance,
+ LVM_INT16 *pInSamps,
+ LVM_INT16 numSamples,
+ LVM_INT16 BandIndex);
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Init */
+/* */
+/* DESCRIPTION: */
+/* Initialize a quasi peak filter instance. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pTaps Pointer to the filter's taps */
+/* pCoef Pointer to the filter's coefficients */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Init ( QPD_State_t *pInstance,
+ QPD_Taps_t *pTaps,
+ QPD_C32_Coefs *pCoef );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
new file mode 100755
index 0000000..37abe40
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA_QPD.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Init */
+/* */
+/* DESCRIPTION: */
+/* Initialize a quasi peak filter instance. */
+/* */
+/* PARAMETERS: */
+/* pQPD_State Pointer to the filter state */
+/* pTaps Pointer to the filter's taps */
+/* pCoef Pointer to the filter's coefficients */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Init ( pQPD_State_t pQPD_State,
+ QPD_Taps_t *pTaps,
+ QPD_C32_Coefs *pCoef )
+{
+ pQPD_State->pDelay = pTaps->Storage;
+ pQPD_State->Coefs[0] = pCoef->KP;
+ pQPD_State->Coefs[1] = pCoef->KM;
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
new file mode 100755
index 0000000..7087475
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA_QPD.h"
+#include "LVPSA_Private.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_WritePeak */
+/* */
+/* DESCRIPTION: */
+/* Write a level value in the buffer in the corresponding band. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the LVPSA instance */
+/* ppWrite Pointer to pointer to the buffer */
+/* CallNumber Number of the band the value should be written in */
+/* Value Value to write in the buffer */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak( pLVPSA_InstancePr_t pLVPSA_Inst,
+ LVM_UINT8 **ppWrite,
+ LVM_INT16 BandIndex,
+ LVM_INT16 Value );
+
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Process */
+/* */
+/* DESCRIPTION: */
+/* Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/* in the buffer every 20 ms. */
+/* */
+/* PARAMETERS: */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Process ( void *hInstance,
+ LVM_INT16 *pInSamps,
+ LVM_INT16 numSamples,
+ LVM_INT16 BandIndex)
+{
+
+ /******************************************************************************
+ PARAMETERS
+ *******************************************************************************/
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+ QPD_State_t *pQPDState = (QPD_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
+
+ /* Pointer to taps */
+ LVM_INT32* pDelay = pQPDState->pDelay;
+
+ /* Parameters needed during quasi peak calculations */
+ LVM_INT32 X0;
+ LVM_INT32 temp,temp2;
+ LVM_INT32 accu;
+ LVM_INT16 Xg0;
+ LVM_INT16 D0;
+ LVM_INT16 V0 = (LVM_INT16)(*pDelay);
+
+ /* Filter's coef */
+ LVM_INT32 Kp = pQPDState->Coefs[0];
+ LVM_INT32 Km = pQPDState->Coefs[1];
+
+ LVM_INT16 ii = numSamples;
+
+ LVM_UINT8 *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+ LVM_INT32 BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
+ LVM_UINT16 DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
+
+ /******************************************************************************
+ INITIALIZATION
+ *******************************************************************************/
+ /* Correct the pointer to take the first down sampled signal sample */
+ pInSamps += pLVPSA_Inst->DownSamplingCount;
+ /* Correct also the number of samples */
+ ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
+
+ while (ii > 0)
+ {
+ /* Apply post gain */
+ X0 = ((*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex]) >> (LVPSA_GAINSHIFT-1); /* - 1 to compensate scaling in process function*/
+ pInSamps = pInSamps + DownSamplingFactor;
+
+ /* Saturate and take absolute value */
+ if(X0 < 0)
+ X0 = -X0;
+ if (X0 > 0x7FFF)
+ Xg0 = 0x7FFF;
+ else
+ Xg0 = (LVM_INT16)(X0);
+
+
+ /* Quasi peak filter calculation */
+ D0 = (LVM_INT16)(Xg0 - V0);
+
+ temp2 = (LVM_INT32)D0;
+ MUL32x32INTO32(temp2,Kp,accu,31);
+
+ D0 = (LVM_INT16)(D0>>1);
+ if (D0 < 0){
+ D0 = (LVM_INT16)(-D0);
+ }
+
+ temp2 = (LVM_INT32)D0;
+ MUL32x32INTO32((LVM_INT32)D0,Km,temp,31);
+ accu +=temp + Xg0;
+
+ if (accu > 0x7FFF)
+ accu = 0x7FFF;
+ else if(accu < 0)
+ accu = 0x0000;
+
+ V0 = (LVM_INT16)accu;
+
+ if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
+ {
+ LVPSA_QPD_WritePeak( pLVPSA_Inst,
+ &pWrite,
+ BandIndex,
+ V0);
+ BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
+ pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
+ }
+ BufferUpdateSamplesCount+=DownSamplingFactor;
+
+ ii = (LVM_INT16)(ii-DownSamplingFactor);
+
+ }
+
+ /* Store last taps in memory */
+ *pDelay = (LVM_INT32)(V0);
+
+ /* If this is the last call to the function after last band processing,
+ update the parameters. */
+ if(BandIndex == (pLVPSA_Inst->nRelevantFilters-1))
+ {
+ pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+ /* Adjustment for 11025Hz input, 220,5 is normally
+ the exact number of samples for 20ms.*/
+ if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&(pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
+ {
+ if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
+ {
+ pLVPSA_Inst->nSamplesBufferUpdate = 221;
+ }
+ else
+ {
+ pLVPSA_Inst->nSamplesBufferUpdate = 220;
+ }
+ }
+ pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+ pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
+ pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
+ }
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_WritePeak */
+/* */
+/* DESCRIPTION: */
+/* Write a level value in the spectrum data buffer in the corresponding band. */
+/* */
+/* PARAMETERS: */
+/* pLVPSA_Inst Pointer to the LVPSA instance */
+/* ppWrite Pointer to pointer to the buffer */
+/* CallNumber Number of the band the value should be written in */
+/* Value Value to write in the spectrum data buffer */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak( pLVPSA_InstancePr_t pLVPSA_Inst,
+ LVM_UINT8 **ppWrite,
+ LVM_INT16 BandIndex,
+ LVM_INT16 Value )
+{
+ LVM_UINT8 *pWrite = *ppWrite;
+
+
+ /* Write the value and update the write pointer */
+ *(pWrite + BandIndex) = (LVM_UINT8)(Value>>7);
+ pWrite += pLVPSA_Inst->nBands;
+ if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * pLVPSA_Inst->SpectralDataBufferLength))
+ {
+ pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
+ }
+
+ *ppWrite = pWrite;
+
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
new file mode 100755
index 0000000..f4a35c5
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVPSA.h"
+#include "LVPSA_QPD.h"
+/************************************************************************************/
+/* */
+/* Sample rate table */
+/* */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT16 LVPSA_SampleRateTab[] = { 8000, /* 8kS/s */
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000}; /* 48kS/s */
+
+/************************************************************************************/
+/* */
+/* Sample rate inverse table */
+/* */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT32 LVPSA_SampleRateInvTab[] = { 268435, /* 8kS/s */
+ 194783,
+ 178957,
+ 134218,
+ 97391,
+ 89478,
+ 67109,
+ 48696,
+ 44739}; /* 48kS/s */
+
+
+
+/************************************************************************************/
+/* */
+/* Number of samples in 20ms */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the number of samples
+ * during 20ms
+ */
+const LVM_UINT16 LVPSA_nSamplesBufferUpdate[] = { 160, /* 8kS/s */
+ 220,
+ 240,
+ 320,
+ 441,
+ 480,
+ 640,
+ 882,
+ 960}; /* 48kS/s */
+/************************************************************************************/
+/* */
+/* Down sampling factors */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the down sampling factor
+ */
+const LVM_UINT16 LVPSA_DownSamplingFactor[] = { 5, /* 8000 S/s */
+ 7, /* 11025 S/s */
+ 8, /* 12000 S/s */
+ 10, /* 16000 S/s */
+ 15, /* 22050 S/s */
+ 16, /* 24000 S/s */
+ 21, /* 32000 S/s */
+ 30, /* 44100 S/s */
+ 32}; /* 48000 S/s */
+
+
+/************************************************************************************/
+/* */
+/* Coefficient calculation tables */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_INT16 LVPSA_TwoPiOnFsTable[] = { 26354, /* 8kS/s */
+ 19123,
+ 17569,
+ 13177,
+ 9561,
+ 8785,
+ 6588,
+ 4781,
+ 4392}; /* 48kS/s */
+
+/*
+ * Gain table
+ */
+const LVM_INT16 LVPSA_GainTable[] = { 364, /* -15dB gain */
+ 408,
+ 458,
+ 514,
+ 577,
+ 647,
+ 726,
+ 815,
+ 914,
+ 1026,
+ 1151,
+ 1292,
+ 1449,
+ 1626,
+ 1825,
+ 2048, /* 0dB gain */
+ 2297,
+ 2578,
+ 2892,
+ 3245,
+ 3641,
+ 4096,
+ 4584,
+ 5144,
+ 5772,
+ 6476,
+ 7266,
+ 8153,
+ 9148,
+ 10264,
+ 11576}; /* +15dB gain */
+
+/************************************************************************************/
+/* */
+/* Cosone polynomial coefficients */
+/* */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ * Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16 LVPSA_CosCoef[] = { 3, /* Shifts */
+ 4096, /* a0 */
+ -36, /* a1 */
+ -19725, /* a2 */
+ -2671, /* a3 */
+ 23730, /* a4 */
+ -9490}; /* a5 */
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ * CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16 LVPSA_DPCosCoef[] = { 1, /* Shifts */
+ 0, /* a0 */
+ -6, /* a1 */
+ 16586, /* a2 */
+ -44}; /* a3 */
+
+/************************************************************************************/
+/* */
+/* Quasi peak filter coefficients table */
+/* */
+/************************************************************************************/
+const QPD_C32_Coefs LVPSA_QPD_Coefs[] = {
+
+ {0x80CEFD2B,0x00CB9B17}, /* 8kS/s */ /* LVPSA_SPEED_LOW */
+ {0x80D242E7,0x00CED11D},
+ {0x80DCBAF5,0x00D91679},
+ {0x80CEFD2B,0x00CB9B17},
+ {0x80E13739,0x00DD7CD3},
+ {0x80DCBAF5,0x00D91679},
+ {0x80D94BAF,0x00D5B7E7},
+ {0x80E13739,0x00DD7CD3},
+ {0x80DCBAF5,0x00D91679}, /* 48kS/s */
+
+ {0x8587513D,0x055C22CF}, /* 8kS/s */ /* LVPSA_SPEED_MEDIUM */
+ {0x859D2967,0x0570F007},
+ {0x85E2EFAC,0x05B34D79},
+ {0x8587513D,0x055C22CF},
+ {0x8600C7B9,0x05CFA6CF},
+ {0x85E2EFAC,0x05B34D79},
+ {0x85CC1018,0x059D8F69},
+ {0x8600C7B9,0x05CFA6CF},//{0x8600C7B9,0x05CFA6CF},
+ {0x85E2EFAC,0x05B34D79}, /* 48kS/s */
+
+ {0xA115EA7A,0x1CDB3F5C}, /* 8kS/s */ /* LVPSA_SPEED_HIGH */
+ {0xA18475F0,0x1D2C83A2},
+ {0xA2E1E950,0x1E2A532E},
+ {0xA115EA7A,0x1CDB3F5C},
+ {0xA375B2C6,0x1E943BBC},
+ {0xA2E1E950,0x1E2A532E},
+ {0xA26FF6BD,0x1DD81530},
+ {0xA375B2C6,0x1E943BBC},
+ {0xA2E1E950,0x1E2A532E}}; /* 48kS/s */
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
new file mode 100755
index 0000000..1ab45cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Header file for the application layer interface of Concert Sound and Concert */
+/* Sound EX. */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the calling layer. All other types, structures and */
+/* functions are private. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 1 */
+/* ======= */
+/* The algorithm can execute either with separate input and output buffers or with */
+/* a common buffer, i.e. the data is processed in-place. If the buffers are the */
+/* same then the MIPs will be slightly higher and an extra stereo scratch buffer is */
+/* required. */
+/* */
+/****************************************************************************************/
+/* */
+/* Note: 2 */
+/* ======= */
+/* Two data formats are support Stereo and Mono-In-Stereo. The data is interleaved as */
+/* follows: */
+/* Byte Offset Stereo Input Mono-In-Stereo Input */
+/* =========== ============ ==================== */
+/* 0 Left Sample #1 Mono Sample #1 */
+/* 2 Right Sample #1 Mono Sample #1 */
+/* 4 Left Sample #2 Mono Sample #2 */
+/* 6 Right Sample #2 Mono Sample #2 */
+/* . . . */
+/* . . . */
+/* */
+/* Mono format data is not supported, the calling routine must convert a Mono stream */
+/* in to Mono-In-Stereo format. */
+/* */
+/****************************************************************************************/
+
+#ifndef LVCS_H
+#define LVCS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Types.h"
+#include "LVM_Common.h"
+
+
+/****************************************************************************************/
+/* */
+/* Definitions */
+/* */
+/****************************************************************************************/
+
+/* Memory table */
+#define LVCS_MEMREGION_PERSISTENT_SLOW_DATA 0 /* Offset to the instance memory region */
+#define LVCS_MEMREGION_PERSISTENT_FAST_DATA 1 /* Offset to the persistent data memory region */
+#define LVCS_MEMREGION_PERSISTENT_FAST_COEF 2 /* Offset to the persistent coefficient memory region */
+#define LVCS_MEMREGION_TEMPORARY_FAST 3 /* Offset to temporary memory region */
+#define LVCS_NR_MEMORY_REGIONS 4 /* Number of memory regions */
+
+/* Effect Level */
+#define LVCS_EFFECT_LOW 16384 /* Effect scaling 50% */
+#define LVCS_EFFECT_MEDIUM 24576 /* Effect scaling 75% */
+#define LVCS_EFFECT_HIGH 32767 /* Effect Scaling 100% */
+
+/* Callback events */
+#define LVCS_EVENT_NONE 0x0000 /* Not a valid event */
+#define LVCS_EVENT_ALGOFF 0x0001 /* CS has completed switch off */
+
+
+/****************************************************************************************/
+/* */
+/* Types */
+/* */
+/****************************************************************************************/
+
+/* Instance handle */
+typedef void *LVCS_Handle_t;
+
+
+/* Operating modes */
+typedef enum
+{
+ LVCS_OFF = 0,
+ LVCS_ON = 15,
+ LVCS_MAX = LVM_MAXENUM
+} LVCS_Modes_en;
+
+
+/* Memory Types */
+typedef enum
+{
+ LVCS_SCRATCH = 0,
+ LVCS_DATA = 1,
+ LVCS_COEFFICIENT = 2,
+ LVCS_PERSISTENT = 3,
+ LVCS_MEMORYTYPE_MAX = LVM_MAXENUM
+} LVCS_MemoryTypes_en;
+
+
+/* Function return status */
+typedef enum
+{
+ LVCS_SUCCESS = 0, /* Successful return from a routine */
+ LVCS_ALIGNMENTERROR = 1, /* Memory alignment error */
+ LVCS_NULLADDRESS = 2, /* NULL allocation address */
+ LVCS_TOOMANYSAMPLES = 3, /* Maximum block size exceeded */
+ LVCS_INVALIDBUFFER = 4, /* Invalid buffer processing request */
+ LVCS_STATUSMAX = LVM_MAXENUM
+} LVCS_ReturnStatus_en;
+
+
+/*
+ * Source data formats
+ */
+typedef enum
+{
+ LVCS_STEREO = 0,
+ LVCS_MONOINSTEREO = 1,
+ LVCS_SOURCEMAX = LVM_MAXENUM
+} LVCS_SourceFormat_en;
+
+
+/*
+ * Supported output devices
+ */
+typedef enum
+{
+ LVCS_HEADPHONES = 0,
+ LVCS_EX_HEADPHONES = 1,
+ LVCS_SPEAKERTYPE_MAX = LVM_MAXENUM
+} LVCS_SpeakerType_en;
+
+/*
+ * Speaker Coefficients Table
+ */
+typedef struct
+{
+ void *pTable1;
+ void *pTable2;
+ void *pTable3;
+ void *pTable4;
+ void *pTable5;
+ void *pTable6;
+ void *pTable7;
+ void *pTable8;
+} LVCS_CSMS_Coef_Tables_t;
+
+
+/****************************************************************************************/
+/* */
+/* Structures */
+/* */
+/****************************************************************************************/
+
+/* Memory region definition */
+typedef struct
+{
+ LVM_UINT32 Size; /* Region size in bytes */
+ LVCS_MemoryTypes_en Type; /* Region type */
+ void *pBaseAddress; /* Pointer to the region base address */
+} LVCS_MemoryRegion_t;
+
+
+/* Memory table containing the region definitions */
+typedef struct
+{
+ LVCS_MemoryRegion_t Region[LVCS_NR_MEMORY_REGIONS]; /* One definition for each region */
+} LVCS_MemTab_t;
+
+
+/* Concert Sound parameter structure */
+typedef struct
+{
+ LVCS_Modes_en OperatingMode; /* Algorithm mode */
+ LVCS_SpeakerType_en SpeakerType; /* Output device type */
+ LVCS_SourceFormat_en SourceFormat; /* Source data format */
+ LVM_Mode_en CompressorMode; /* Non-Linear Compressor Mode */
+ LVM_Fs_en SampleRate; /* Sampling rate */
+ LVM_INT16 EffectLevel; /* Effect level */
+ LVM_UINT16 ReverbLevel; /* Reverb level in % */
+} LVCS_Params_t;
+
+
+/* Concert Sound Capability structure */
+typedef struct
+{
+ /* General parameters */
+ LVM_UINT16 MaxBlockSize; /* Maximum block size in sample pairs */
+
+ /* Callback parameters */
+ LVM_Callback CallBack; /* Bundle callback */
+ void *pBundleInstance; /* Bundle instance handle */
+
+} LVCS_Capabilities_t;
+
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) it is */
+/* passed the default capabilities, of these only the buffer processing setting is */
+/* used. */
+/* */
+/* When called for memory allocation the memory base address pointers are NULL on */
+/* return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the */
+/* capabilities are ignored and the memory table returns the allocated memory and */
+/* base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the default capabilites */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVCS_Process function */
+/* */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Memory(LVCS_Handle_t hInstance,
+ LVCS_MemTab_t *pMemoryTable,
+ LVCS_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Init */
+/* */
+/* DESCRIPTION: */
+/* Create and initialisation function for the Concert Sound module */
+/* */
+/* This function can be used to create an algorithm instance by calling with */
+/* hInstance set to NULL. In this case the algorithm returns the new instance */
+/* handle. */
+/* */
+/* This function can be used to force a full re-initialisation of the algorithm */
+/* by calling with hInstance = Instance Handle. In this case the memory table */
+/* should be correct for the instance, this can be ensured by calling the function */
+/* LVCS_Memory before calling this function. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pCapabilities Pointer to the initialisation capabilities */
+/* */
+/* RETURNS: */
+/* LVCS_Success Initialisation succeeded */
+/* LVCS_AlignmentError Instance or scratch memory on incorrect alignment */
+/* LVCS_NullAddress Instance or scratch memory has a NULL pointer */
+/* */
+/* NOTES: */
+/* 1. The instance handle is the pointer to the base address of the first memory */
+/* region. */
+/* 2. This function must not be interrupted by the LVCS_Process function */
+/* */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Init(LVCS_Handle_t *phInstance,
+ LVCS_MemTab_t *pMemoryTable,
+ LVCS_Capabilities_t *pCapabilities);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_GetParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the Concert Sound parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVCS_Process function */
+/* */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Control */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the Concert Sound parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVCS_Process function */
+/* */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams);
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the Concert Sound module. The implementation supports two */
+/* variants of the algorithm, one for headphones and one for mobile speakers. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* LVCS_TooManySamples NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LVCS_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
new file mode 100755
index 0000000..b1d9408
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq06068 $
+ $Revision: 1307 $
+ $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_BypassMix.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/****************************************************************************************/
+/* */
+/* Function Prototypes */
+/* */
+/****************************************************************************************/
+LVM_INT32 LVCS_MixerCallback( LVCS_Handle_t hInstance,
+ void *pGeneralPurpose,
+ LVM_INT16 CallbackParam);
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_BypassMixInit */
+/* */
+/* DESCRIPTION: */
+/* Initialises the bypass mixer module */
+/* */
+/* The overall gain of the processed path is set by the gains in the individual */
+/* processing blocks and by the effect level gain. */
+/* */
+/* The unprocessed path must have matching gain for the processed path to ensure */
+/* as they are mixed together the correct effect is achieved, this is the value */
+/* UnprocLoss. */
+/* */
+/* The overall gain is corrected by a combination of a shift with saturation and a */
+/* linear scaler, loss. The loss ensures the sum in the mixer does not saturate */
+/* and also corrects for any excess gain in the shift. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Initialisation parameters */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams)
+{
+
+ LVM_UINT16 Offset;
+ LVM_UINT32 Gain;
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_BypassMix_t *pConfig = (LVCS_BypassMix_t *)&pInstance->BypassMix;
+ const Gain_t *pOutputGainTable;
+ LVM_INT32 Current;
+
+
+ /*
+ * Set the transition gain
+ */
+ if ((pParams->OperatingMode == LVCS_ON) &&
+ (pInstance->bTimerDone == LVM_TRUE)
+ && (pInstance->MSTarget1 != 0x7FFF) /* this indicates an off->on transtion */
+ )
+ {
+ pInstance->TransitionGain = pParams->EffectLevel;
+ }
+ else
+ {
+ /* Select no effect level */
+ pInstance->TransitionGain = 0;
+ }
+
+ /*
+ * Calculate the output gain table offset
+ */
+ Offset = (LVM_UINT16)(pParams->SpeakerType + (pParams->SourceFormat*(1+LVCS_EX_HEADPHONES)));
+ pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+
+ /*
+ * Setup the mixer gain for the processed path
+ */
+ Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * pInstance->TransitionGain);
+
+ pConfig->Mixer_Instance.MixerStream[0].CallbackParam = 0;
+ pConfig->Mixer_Instance.MixerStream[0].pCallbackHandle = LVM_NULL;
+ pConfig->Mixer_Instance.MixerStream[0].pCallBack = LVM_NULL;
+ pConfig->Mixer_Instance.MixerStream[0].CallbackSet=1;
+ Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[0]);
+ LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[0],(LVM_INT32)(Gain >> 15),Current);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+ /*
+ * Setup the mixer gain for the unprocessed path
+ */
+ Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * (0x7FFF - pInstance->TransitionGain));
+ Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
+ Current = LVC_Mixer_GetCurrent(&pConfig->Mixer_Instance.MixerStream[1]);
+ LVC_Mixer_Init(&pConfig->Mixer_Instance.MixerStream[1],(LVM_INT32)(Gain >> 15),Current);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+ pConfig->Mixer_Instance.MixerStream[1].CallbackParam = 0;
+ pConfig->Mixer_Instance.MixerStream[1].pCallbackHandle = hInstance;
+ pConfig->Mixer_Instance.MixerStream[1].CallbackSet=1;
+ pConfig->Mixer_Instance.MixerStream[1].pCallBack = LVCS_MixerCallback;
+
+ /*
+ * Setup the output gain shift
+ */
+ pConfig->Output_Shift = pOutputGainTable[Offset].Shift;
+
+
+ /*
+ * Correct gain for the effect level
+ */
+ {
+
+ LVM_INT16 GainCorrect;
+ LVM_INT32 Gain1;
+ LVM_INT32 Gain2;
+
+ Gain1 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[0]);
+ Gain2 = LVC_Mixer_GetTarget(&pConfig->Mixer_Instance.MixerStream[1]);
+ /*
+ * Calculate the gain correction
+ */
+ if (pInstance->Params.CompressorMode == LVM_MODE_ON)
+ {
+ GainCorrect = (LVM_INT16)( pInstance->VolCorrect.GainMin
+ - (((LVM_INT32)pInstance->VolCorrect.GainMin * (LVM_INT32)pInstance->TransitionGain) >> 15)
+ + (((LVM_INT32)pInstance->VolCorrect.GainFull * (LVM_INT32)pInstance->TransitionGain) >> 15) );
+
+ /*
+ * Apply the gain correction and shift, note the result is in Q3.13 format
+ */
+ Gain1 = (Gain1 * GainCorrect) << 4;
+ Gain2 = (Gain2 * GainCorrect) << 4;
+ }
+ else
+ {
+ Gain1 = Gain1 << 16;
+ Gain2 = Gain2 << 16;
+ }
+
+
+
+ /*
+ * Set the gain values
+ */
+ pConfig->Output_Shift = pConfig->Output_Shift;
+ LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[0],Gain1>>16);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[0],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+ LVC_Mixer_SetTarget(&pConfig->Mixer_Instance.MixerStream[1],Gain2>>16);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pConfig->Mixer_Instance.MixerStream[1],LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+ }
+
+ return(LVCS_SUCCESS);
+
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_BypassMixer */
+/* */
+/* DESCRIPTION: */
+/* Apply Bypass Mix. */
+/* */
+/* This mixes the processed and unprocessed data streams together to correct the */
+/* overall system gain and allow progressive control of the Concert Sound effect. */
+/* */
+/* When the bypass mixer is enabled the output is the processed signal only and */
+/* without gain correction. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pProcessed Pointer to the processed data */
+/* pUnprocessed Pointer to the unprocessed data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples to process */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pProcessed,
+ const LVM_INT16 *pUnprocessed,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_BypassMix_t *pConfig = (LVCS_BypassMix_t *)&pInstance->BypassMix;
+
+ /*
+ * Check if the bypass mixer is enabled
+ */
+ if ((pInstance->Params.OperatingMode & LVCS_BYPASSMIXSWITCH) != 0)
+ {
+ /*
+ * Apply the bypass mix
+ */
+ LVC_MixSoft_2St_D16C31_SAT(&pConfig->Mixer_Instance,
+ pProcessed,
+ (LVM_INT16 *) pUnprocessed,
+ pOutData,
+ (LVM_INT16)(2*NumSamples));
+
+ /*
+ * Apply output gain correction shift
+ */
+ Shift_Sat_v16xv16 ((LVM_INT16)pConfig->Output_Shift,
+ (LVM_INT16*)pOutData,
+ (LVM_INT16*)pOutData,
+ (LVM_INT16)(2*NumSamples)); /* Left and right*/
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_MixerCallback */
+/* */
+/************************************************************************************/
+LVM_INT32 LVCS_MixerCallback(LVCS_Handle_t hInstance,
+ void *pGeneralPurpose,
+ LVM_INT16 CallbackParam)
+{
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+
+ (void)pGeneralPurpose;
+
+ /*
+ * Off transition has completed in Headphone mode
+ */
+ if ((pInstance->OutputDevice == LVCS_HEADPHONE) &&
+ (pInstance->bInOperatingModeTransition) &&
+ (pInstance->MSTarget0 == 0x0000)&& /* this indicates an on->off transition */
+ (CallbackParam == 0))
+ {
+ /* Set operating mode to OFF */
+ pInstance->Params.OperatingMode = LVCS_OFF;
+
+ /* Exit transition state */
+ pInstance->bInOperatingModeTransition = LVM_FALSE;
+
+ /* Signal to the bundle */
+ if((*pInstance->Capabilities.CallBack) != LVM_NULL){
+ (*pInstance->Capabilities.CallBack)(pInstance->Capabilities.pBundleInstance,
+ LVM_NULL,
+ (ALGORITHM_CS_ID | LVCS_EVENT_ALGOFF));
+ }
+ }
+
+
+ if ((pInstance->OutputDevice == LVCS_HEADPHONE) &&
+ (pInstance->MSTarget0 == 1) &&
+ (pInstance->bTimerDone == LVM_TRUE)){
+
+ /* Exit transition state */
+ pInstance->bInOperatingModeTransition = LVM_FALSE;
+ }
+
+ return 1;
+}
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
new file mode 100755
index 0000000..79dff41
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_BypassMix.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_BYPASSMIX_H__
+#define __LVCS_BYPASSMIX_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVC_Mixer.h"
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+/* Bypass mixer structure */
+typedef struct
+{
+ /* Mixer settings */
+ LVMixer3_2St_st Mixer_Instance; /* Mixer instance */
+ LVM_UINT16 Output_Shift; /* Correcting gain output shift */
+
+} LVCS_BypassMix_t;
+
+
+/* Output gain type */
+typedef struct
+{
+ /* Output gain settings, Gain = (Loss/32768) * 2^Shift */
+ LVM_UINT16 Shift; /* Left shifts required */
+ LVM_UINT16 Loss; /* Loss required */
+ LVM_UINT16 UnprocLoss; /* Unprocessed path loss */
+} Gain_t;
+
+
+/************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_BypassMixInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams);
+
+
+LVCS_ReturnStatus_en LVCS_BypassMixer(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pProcessed,
+ const LVM_INT16 *unProcessed,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* BYPASSMIX_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
new file mode 100755
index 0000000..fea44bf
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Control.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq06068 $
+ $Revision: 1307 $
+ $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_GetParameters */
+/* */
+/* DESCRIPTION: */
+/* Request the Concert Sound parameters. The current parameter set is returned */
+/* via the parameter pointer. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to an empty parameter structure */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVCS_Process function */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_GetParameters(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams)
+{
+
+ LVCS_Instance_t *pInstance =(LVCS_Instance_t *)hInstance;
+
+ *pParams = pInstance->Params;
+
+ return(LVCS_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Control */
+/* */
+/* DESCRIPTION: */
+/* Sets or changes the Concert Sound parameters. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pParams Pointer to a parameter structure */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function must not be interrupted by the LVCS_Process function */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Control(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams)
+{
+ LVM_INT16 Offset;
+ LVCS_Instance_t *pInstance =(LVCS_Instance_t *)hInstance;
+ LVCS_ReturnStatus_en err;
+ LVCS_Modes_en OperatingModeSave = pInstance->Params.OperatingMode;
+
+ if (pParams->SampleRate != pInstance->Params.SampleRate)
+ {
+ pInstance->TimerParams.SamplingRate = LVCS_SampleRateTable[pParams->SampleRate];
+ }
+
+ /*
+ * If the reverb level has changed
+ */
+ if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+ {
+ err=LVCS_ReverbGeneratorInit(hInstance,pParams);
+ }
+
+ /*
+ * If the sample rate or speaker has changed then perform a full re-initialisation
+ */
+ if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.SpeakerType != pParams->SpeakerType))
+ {
+ const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+ /*
+ * Output device
+ */
+ pInstance->OutputDevice = LVCS_HEADPHONE;
+
+ /*
+ * Get the volume correction parameters
+ */
+ /* Use internal coefficient table */
+ pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+ Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
+
+ pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
+
+ LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
+
+
+ {
+ LVM_UINT32 Gain;
+ const Gain_t *pOutputGainTable = (Gain_t*)&LVCS_OutputGainTable[0];
+ Gain = (LVM_UINT32)(pOutputGainTable[Offset].Loss * LVM_MAXINT_16);
+ Gain = (LVM_UINT32)pOutputGainTable[Offset].UnprocLoss * (Gain >> 15);
+ Gain=Gain>>15;
+ /*
+ * Apply the gain correction and shift, note the result is in Q3.13 format
+ */
+ Gain = (Gain * pInstance->VolCorrect.GainMin) >>12;
+
+ LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,Gain);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],
+ LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+ LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],
+ LVCS_BYPASS_MIXER_TC,pParams->SampleRate,2);
+
+ }
+
+
+ err=LVCS_SEnhancerInit(hInstance,
+ pParams);
+
+ err=LVCS_ReverbGeneratorInit(hInstance,
+ pParams);
+
+ err=LVCS_EqualiserInit(hInstance,
+ pParams);
+
+ err=LVCS_BypassMixInit(hInstance,
+ pParams);
+
+ }
+
+
+ /*
+ * Check if the effect level or source format has changed
+ */
+ else if ((pInstance->Params.EffectLevel != pParams->EffectLevel) ||
+ (pInstance->Params.SourceFormat != pParams->SourceFormat))
+ {
+ const LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+ /*
+ * Get the volume correction parameters
+ */
+ /* Use internal coefficient table */
+ pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+ Offset = (LVM_INT16)(pParams->SpeakerType + pParams->SourceFormat*(1+LVCS_EX_HEADPHONES));
+
+ pInstance->VolCorrect = pLVCS_VolCorrectTable[Offset];
+
+ /* Update the effect level and alpha-mixer gains */
+ err=LVCS_BypassMixInit(hInstance,
+ pParams);
+
+ if(err != LVCS_SUCCESS)
+ {
+ return err;
+ }
+ }
+ else
+ {
+ pInstance->Params = *pParams;
+ }
+
+ /*
+ * Update the instance parameters
+ */
+ pInstance->Params = *pParams;
+
+ /* Stay on the current operating mode until the transition is done */
+ if((pParams->OperatingMode != OperatingModeSave) ||
+ (pInstance->bInOperatingModeTransition == LVM_TRUE)){
+
+ /* Set the reverb delay timeout */
+ if(pInstance->bInOperatingModeTransition != LVM_TRUE){
+ pInstance->bTimerDone = LVM_FALSE;
+ pInstance->TimerParams.TimeInMs = (LVM_INT16)(((pInstance->Reverberation.DelaySize << 2)/pInstance->TimerParams.SamplingRate) + 1);
+ LVM_Timer_Init ( &pInstance->TimerInstance,
+ &pInstance->TimerParams);
+ }
+
+ /* Update the effect level and alpha-mixer gains */
+ err=LVCS_BypassMixInit(hInstance,
+ pParams);
+
+ /* Change transition bypass mixer settings if needed depending on transition type */
+ if(pParams->OperatingMode != LVCS_OFF){
+ pInstance->MSTarget0=LVM_MAXINT_16;
+ pInstance->MSTarget1=0;
+ }
+ else
+ {
+ pInstance->Params.OperatingMode = OperatingModeSave;
+ pInstance->MSTarget1=LVM_MAXINT_16;
+ pInstance->MSTarget0=0;
+ }
+
+
+ /* Set transition flag */
+ pInstance->bInOperatingModeTransition = LVM_TRUE;
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_TimerCallBack */
+/* */
+/* DESCRIPTION: */
+/* CallBack function of the Timer. */
+/* */
+/****************************************************************************************/
+void LVCS_TimerCallBack (void* hInstance, void* pCallBackParams, LVM_INT32 CallbackParam)
+{
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+
+ /* Avoid warnings because pCallBackParams and CallbackParam are not used*/
+ if((pCallBackParams != LVM_NULL) || (CallbackParam != 0)){
+ pCallBackParams = hInstance;
+ CallbackParam = 0;
+ return;
+ }
+
+ pInstance->bTimerDone = LVM_TRUE;
+
+
+ return;
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
new file mode 100755
index 0000000..7ab6571
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1315 $
+ $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Equaliser.h"
+#include "BIQUAD.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_EqualiserInit */
+/* */
+/* DESCRIPTION: */
+/* Initialises the equaliser module */
+/* */
+/* The function selects the coefficients for the filters and clears the data */
+/* history. It is also used for re-initialisation when one of the system control */
+/* parameters changes but will only change the coefficients and clear the history */
+/* if the sample rate or speaker type has changed. */
+/* */
+/* To avoid excessive testing during the sample processing the biquad type is */
+/* set as a callback function in the init routine. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Initialisation parameters */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams)
+{
+
+ LVM_UINT16 Offset;
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_Equaliser_t *pConfig = (LVCS_Equaliser_t *)&pInstance->Equaliser;
+ LVCS_Data_t *pData = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+ LVCS_Coefficient_t *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+ BQ_C16_Coefs_t Coeffs;
+ const BiquadA012B12CoefsSP_t *pEqualiserCoefTable;
+
+ /*
+ * If the sample rate changes re-initialise the filters
+ */
+ if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.SpeakerType != pParams->SpeakerType))
+ {
+ /*
+ * Setup the filter coefficients and clear the history
+ */
+ Offset = (LVM_UINT16)(pParams->SampleRate + (pParams->SpeakerType * (1+LVM_FS_48000)));
+ pEqualiserCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_EqualiserCoefTable[0];
+
+ /* Left and right filters */
+ /* Convert incoming coefficients to the required format/ordering */
+ Coeffs.A0 = (LVM_INT16) pEqualiserCoefTable[Offset].A0;
+ Coeffs.A1 = (LVM_INT16) pEqualiserCoefTable[Offset].A1;
+ Coeffs.A2 = (LVM_INT16) pEqualiserCoefTable[Offset].A2;
+ Coeffs.B1 = (LVM_INT16)-pEqualiserCoefTable[Offset].B1;
+ Coeffs.B2 = (LVM_INT16)-pEqualiserCoefTable[Offset].B2;
+
+ LoadConst_16((LVM_INT16)0, /* Value */
+ (void *)&pData->EqualiserBiquadTaps, /* Destination Cast to void:\
+ no dereferencing in function*/
+ (LVM_UINT16)(sizeof(pData->EqualiserBiquadTaps)/sizeof(LVM_INT16))); /* Number of words */
+
+ BQ_2I_D16F32Css_TRC_WRA_01_Init(&pCoefficients->EqualiserBiquadInstance,
+ &pData->EqualiserBiquadTaps,
+ &Coeffs);
+
+ /* Callbacks */
+ switch(pEqualiserCoefTable[Offset].Scale)
+ {
+ case 13:
+ pConfig->pBiquadCallBack = BQ_2I_D16F32C13_TRC_WRA_01;
+ break;
+ case 14:
+ pConfig->pBiquadCallBack = BQ_2I_D16F32C14_TRC_WRA_01;
+ break;
+ case 15:
+ pConfig->pBiquadCallBack = BQ_2I_D16F32C15_TRC_WRA_01;
+ break;
+ }
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Equaliser */
+/* */
+/* DESCRIPTION: */
+/* Apply the equaliser filter. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pInputOutput Pointer to the input/output buffer */
+/* NumSamples The number of samples to process */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. Always processes in place. */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance,
+ LVM_INT16 *pInputOutput,
+ LVM_UINT16 NumSamples)
+{
+
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_Equaliser_t *pConfig = (LVCS_Equaliser_t *)&pInstance->Equaliser;
+ LVCS_Coefficient_t *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+
+
+ /*
+ * Check if the equaliser is required
+ */
+ if ((pInstance->Params.OperatingMode & LVCS_EQUALISERSWITCH) != 0)
+ {
+ /* Apply filter to the left and right channels */
+ (pConfig->pBiquadCallBack)((Biquad_Instance_t*)&pCoefficients->EqualiserBiquadInstance,
+ (LVM_INT16 *)pInputOutput,
+ (LVM_INT16 *)pInputOutput,
+ (LVM_INT16)NumSamples);
+ }
+
+ return(LVCS_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
new file mode 100755
index 0000000..10b02cc
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Equaliser.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_EQUALISER_H__
+#define __LVCS_EQUALISER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+/* Equaliser structure */
+typedef struct
+{
+ void (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+} LVCS_Equaliser_t;
+
+
+/************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_EqualiserInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams);
+
+LVCS_ReturnStatus_en LVCS_Equaliser(LVCS_Handle_t hInstance,
+ LVM_INT16 *pInputOutput,
+ LVM_UINT16 NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* EQUALISER_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
new file mode 100755
index 0000000..1d55281
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Headphone_Coeffs.h
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LVCS_HEADPHONE_COEFFS_H__
+#define __LVCS_HEADPHONE_COEFFS_H__
+
+
+/************************************************************************************/
+/* */
+/* The Stereo Enhancer */
+/* */
+/************************************************************************************/
+
+/* Stereo Enhancer coefficients for 8000 Hz sample rate, scaled with 0.161258 */
+#define CS_MIDDLE_8000_A0 7462 /* Floating point value 0.227720 */
+#define CS_MIDDLE_8000_A1 -7049 /* Floating point value -0.215125 */
+#define CS_MIDDLE_8000_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_8000_B1 -30209 /* Floating point value -0.921899 */
+#define CS_MIDDLE_8000_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_8000_SCALE 15
+#define CS_SIDE_8000_A0 20036 /* Floating point value 0.611441 */
+#define CS_SIDE_8000_A1 -12463 /* Floating point value -0.380344 */
+#define CS_SIDE_8000_A2 -7573 /* Floating point value -0.231097 */
+#define CS_SIDE_8000_B1 -20397 /* Floating point value -0.622470 */
+#define CS_SIDE_8000_B2 -4285 /* Floating point value -0.130759 */
+#define CS_SIDE_8000_SCALE 15
+
+/* Stereo Enhancer coefficients for 11025Hz sample rate, scaled with 0.162943 */
+#define CS_MIDDLE_11025_A0 7564 /* Floating point value 0.230838 */
+#define CS_MIDDLE_11025_A1 -7260 /* Floating point value -0.221559 */
+#define CS_MIDDLE_11025_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_11025_B1 -30902 /* Floating point value -0.943056 */
+#define CS_MIDDLE_11025_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_11025_SCALE 15
+#define CS_SIDE_11025_A0 18264 /* Floating point value 0.557372 */
+#define CS_SIDE_11025_A1 -12828 /* Floating point value -0.391490 */
+#define CS_SIDE_11025_A2 -5436 /* Floating point value -0.165881 */
+#define CS_SIDE_11025_B1 -28856 /* Floating point value -0.880608 */
+#define CS_SIDE_11025_B2 1062 /* Floating point value 0.032397 */
+#define CS_SIDE_11025_SCALE 15
+
+/* Stereo Enhancer coefficients for 12000Hz sample rate, scaled with 0.162191 */
+#define CS_MIDDLE_12000_A0 7534 /* Floating point value 0.229932 */
+#define CS_MIDDLE_12000_A1 -7256 /* Floating point value -0.221436 */
+#define CS_MIDDLE_12000_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_12000_B1 -31051 /* Floating point value -0.947616 */
+#define CS_MIDDLE_12000_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_12000_SCALE 15
+#define CS_SIDE_12000_A0 18298 /* Floating point value 0.558398 */
+#define CS_SIDE_12000_A1 -12852 /* Floating point value -0.392211 */
+#define CS_SIDE_12000_A2 -5446 /* Floating point value -0.166187 */
+#define CS_SIDE_12000_B1 -29247 /* Floating point value -0.892550 */
+#define CS_SIDE_12000_B2 1077 /* Floating point value 0.032856 */
+#define CS_SIDE_12000_SCALE 15
+
+/* Stereo Enhancer coefficients for 16000Hz sample rate, scaled with 0.162371 */
+#define CS_MIDDLE_16000_A0 7558 /* Floating point value 0.230638 */
+#define CS_MIDDLE_16000_A1 -7348 /* Floating point value -0.224232 */
+#define CS_MIDDLE_16000_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_16000_B1 -31475 /* Floating point value -0.960550 */
+#define CS_MIDDLE_16000_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_16000_SCALE 15
+#define CS_SIDE_16000_A0 8187 /* Floating point value 0.499695 */
+#define CS_SIDE_16000_A1 -5825 /* Floating point value -0.355543 */
+#define CS_SIDE_16000_A2 -2362 /* Floating point value -0.144152 */
+#define CS_SIDE_16000_B1 -17216 /* Floating point value -1.050788 */
+#define CS_SIDE_16000_B2 2361 /* Floating point value 0.144104 */
+#define CS_SIDE_16000_SCALE 14
+
+/* Stereo Enhancer coefficients for 22050Hz sample rate, scaled with 0.160781 */
+#define CS_MIDDLE_22050_A0 7496 /* Floating point value 0.228749 */
+#define CS_MIDDLE_22050_A1 -7344 /* Floating point value -0.224128 */
+#define CS_MIDDLE_22050_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_22050_B1 -31826 /* Floating point value -0.971262 */
+#define CS_MIDDLE_22050_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_22050_SCALE 15
+#define CS_SIDE_22050_A0 7211 /* Floating point value 0.440112 */
+#define CS_SIDE_22050_A1 -4278 /* Floating point value -0.261096 */
+#define CS_SIDE_22050_A2 -2933 /* Floating point value -0.179016 */
+#define CS_SIDE_22050_B1 -18297 /* Floating point value -1.116786 */
+#define CS_SIDE_22050_B2 2990 /* Floating point value 0.182507 */
+#define CS_SIDE_22050_SCALE 14
+
+/* Stereo Enhancer coefficients for 24000Hz sample rate, scaled with 0.161882 */
+#define CS_MIDDLE_24000_A0 7550 /* Floating point value 0.230395 */
+#define CS_MIDDLE_24000_A1 -7409 /* Floating point value -0.226117 */
+#define CS_MIDDLE_24000_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_24000_B1 -31902 /* Floating point value -0.973573 */
+#define CS_MIDDLE_24000_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_24000_SCALE 15
+#define CS_SIDE_24000_A0 6796 /* Floating point value 0.414770 */
+#define CS_SIDE_24000_A1 -4705 /* Floating point value -0.287182 */
+#define CS_SIDE_24000_A2 -2090 /* Floating point value -0.127588 */
+#define CS_SIDE_24000_B1 -20147 /* Floating point value -1.229648 */
+#define CS_SIDE_24000_B2 4623 /* Floating point value 0.282177 */
+#define CS_SIDE_24000_SCALE 14
+
+/* Stereo Enhancer coefficients for 32000Hz sample rate, scaled with 0.160322 */
+#define CS_MIDDLE_32000_A0 7484 /* Floating point value 0.228400 */
+#define CS_MIDDLE_32000_A1 -7380 /* Floating point value -0.225214 */
+#define CS_MIDDLE_32000_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_32000_B1 -32117 /* Floating point value -0.980126 */
+#define CS_MIDDLE_32000_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_32000_SCALE 15
+#define CS_SIDE_32000_A0 5973 /* Floating point value 0.364579 */
+#define CS_SIDE_32000_A1 -3397 /* Floating point value -0.207355 */
+#define CS_SIDE_32000_A2 -2576 /* Floating point value -0.157224 */
+#define CS_SIDE_32000_B1 -20877 /* Floating point value -1.274231 */
+#define CS_SIDE_32000_B2 5120 /* Floating point value 0.312495 */
+#define CS_SIDE_32000_SCALE 14
+
+/* Stereo Enhancer coefficients for 44100Hz sample rate, scaled with 0.163834 */
+#define CS_MIDDLE_44100_A0 7654 /* Floating point value 0.233593 */
+#define CS_MIDDLE_44100_A1 -7577 /* Floating point value -0.231225 */
+#define CS_MIDDLE_44100_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_44100_B1 -32294 /* Floating point value -0.985545 */
+#define CS_MIDDLE_44100_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_44100_SCALE 15
+#define CS_SIDE_44100_A0 4662 /* Floating point value 0.284573 */
+#define CS_SIDE_44100_A1 -4242 /* Floating point value -0.258910 */
+#define CS_SIDE_44100_A2 -420 /* Floating point value -0.025662 */
+#define CS_SIDE_44100_B1 -25760 /* Floating point value -1.572248 */
+#define CS_SIDE_44100_B2 9640 /* Floating point value 0.588399 */
+#define CS_SIDE_44100_SCALE 14
+
+/* Stereo Enhancer coefficients for 48000Hz sample rate, scaled with 0.164402 */
+#define CS_MIDDLE_48000_A0 7682 /* Floating point value 0.234445 */
+#define CS_MIDDLE_48000_A1 -7611 /* Floating point value -0.232261 */
+#define CS_MIDDLE_48000_A2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_48000_B1 -32333 /* Floating point value -0.986713 */
+#define CS_MIDDLE_48000_B2 0 /* Floating point value 0.000000 */
+#define CS_MIDDLE_48000_SCALE 15
+#define CS_SIDE_48000_A0 4466 /* Floating point value 0.272606 */
+#define CS_SIDE_48000_A1 -4374 /* Floating point value -0.266952 */
+#define CS_SIDE_48000_A2 -93 /* Floating point value -0.005654 */
+#define CS_SIDE_48000_B1 -26495 /* Floating point value -1.617141 */
+#define CS_SIDE_48000_B2 10329 /* Floating point value 0.630405 */
+#define CS_SIDE_48000_SCALE 14
+
+
+/************************************************************************************/
+/* */
+/* The Reverb Unit */
+/* */
+/************************************************************************************/
+
+/* Reverb delay settings in samples */
+#define LVCS_STEREODELAY_CS_8KHZ 93 /* Sample rate 8kS/s */
+#define LVCS_STEREODELAY_CS_11KHZ 128 /* Sample rate 11kS/s */
+#define LVCS_STEREODELAY_CS_12KHZ 139 /* Sample rate 12kS/s */
+#define LVCS_STEREODELAY_CS_16KHZ 186 /* Sample rate 16kS/s */
+#define LVCS_STEREODELAY_CS_22KHZ 256 /* Sample rate 22kS/s */
+#define LVCS_STEREODELAY_CS_24KHZ 279 /* Sample rate 24kS/s */
+#define LVCS_STEREODELAY_CS_32KHZ 372 /* Sample rate 32kS/s */
+#define LVCS_STEREODELAY_CS_44KHZ 512 /* Sample rate 44kS/s */
+#define LVCS_STEREODELAY_CS_48KHZ 512 /* Sample rate 48kS/s */
+
+/* Reverb coefficients for 8000 Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_8000_A0 21865 /* Floating point value 0.667271 */
+#define CS_REVERB_8000_A1 -21865 /* Floating point value -0.667271 */
+#define CS_REVERB_8000_A2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_8000_B1 -21895 /* Floating point value -0.668179 */
+#define CS_REVERB_8000_B2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_8000_SCALE 15
+
+/* Reverb coefficients for 11025Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_11025_A0 22926 /* Floating point value 0.699638 */
+#define CS_REVERB_11025_A1 -22926 /* Floating point value -0.699638 */
+#define CS_REVERB_11025_A2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_11025_B1 -24546 /* Floating point value -0.749096 */
+#define CS_REVERB_11025_B2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_11025_SCALE 15
+
+/* Reverb coefficients for 12000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_12000_A0 23165 /* Floating point value 0.706931 */
+#define CS_REVERB_12000_A1 -23165 /* Floating point value -0.706931 */
+#define CS_REVERB_12000_A2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_12000_B1 -25144 /* Floating point value -0.767327 */
+#define CS_REVERB_12000_B2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_12000_SCALE 15
+
+/* Reverb coefficients for 16000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_16000_A0 23864 /* Floating point value 0.728272 */
+#define CS_REVERB_16000_A1 -23864 /* Floating point value -0.728272 */
+#define CS_REVERB_16000_A2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_16000_B1 -26892 /* Floating point value -0.820679 */
+#define CS_REVERB_16000_B2 0 /* Floating point value 0.000000 */
+#define CS_REVERB_16000_SCALE 15
+
+/* Reverb coefficients for 22050Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_22050_A0 16921 /* Floating point value 0.516396 */
+#define CS_REVERB_22050_A1 0 /* Floating point value 0.000000 */
+#define CS_REVERB_22050_A2 -16921 /* Floating point value -0.516396 */
+#define CS_REVERB_22050_B1 -16991 /* Floating point value -0.518512 */
+#define CS_REVERB_22050_B2 -9535 /* Floating point value -0.290990 */
+#define CS_REVERB_22050_SCALE 15
+
+/* Reverb coefficients for 24000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_24000_A0 15714 /* Floating point value 0.479565 */
+#define CS_REVERB_24000_A1 0 /* Floating point value 0.000000 */
+#define CS_REVERB_24000_A2 -15714 /* Floating point value -0.479565 */
+#define CS_REVERB_24000_B1 -20898 /* Floating point value -0.637745 */
+#define CS_REVERB_24000_B2 -6518 /* Floating point value -0.198912 */
+#define CS_REVERB_24000_SCALE 15
+
+/* Reverb coefficients for 32000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_32000_A0 12463 /* Floating point value 0.380349 */
+#define CS_REVERB_32000_A1 0 /* Floating point value 0.000000 */
+#define CS_REVERB_32000_A2 -12463 /* Floating point value -0.380349 */
+#define CS_REVERB_32000_B1 -31158 /* Floating point value -0.950873 */
+#define CS_REVERB_32000_B2 1610 /* Floating point value 0.049127 */
+#define CS_REVERB_32000_SCALE 15
+
+/* Reverb coefficients for 44100Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_44100_A0 4872 /* Floating point value 0.297389 */
+#define CS_REVERB_44100_A1 0 /* Floating point value 0.000000 */
+#define CS_REVERB_44100_A2 -4872 /* Floating point value -0.297389 */
+#define CS_REVERB_44100_B1 -19668 /* Floating point value -1.200423 */
+#define CS_REVERB_44100_B2 4203 /* Floating point value 0.256529 */
+#define CS_REVERB_44100_SCALE 14
+
+/* Reverb coefficients for 48000Hz sample rate, scaled with 1.038030 */
+#define CS_REVERB_48000_A0 4566 /* Floating point value 0.278661 */
+#define CS_REVERB_48000_A1 0 /* Floating point value 0.000000 */
+#define CS_REVERB_48000_A2 -4566 /* Floating point value -0.278661 */
+#define CS_REVERB_48000_B1 -20562 /* Floating point value -1.254993 */
+#define CS_REVERB_48000_B2 4970 /* Floating point value 0.303347 */
+#define CS_REVERB_48000_SCALE 14
+
+/* Reverb Gain Settings */
+#define LVCS_HEADPHONE_DELAYGAIN 0.800000 /* Algorithm delay path gain */
+#define LVCS_HEADPHONE_OUTPUTGAIN 1.000000 /* Algorithm output gain */
+#define LVCS_HEADPHONE_PROCGAIN 18403 /* Processed path gain */
+#define LVCS_HEADPHONE_UNPROCGAIN 18403 /* Unprocessed path gain */
+#define LVCS_HEADPHONE_GAINCORRECT 1.009343 /* Delay mixer gain correction */
+
+
+/************************************************************************************/
+/* */
+/* The Equaliser */
+/* */
+/************************************************************************************/
+
+/* Equaliser coefficients for 8000 Hz sample rate, CS scaled with 1.038497 and CSEX scaled with 0.775480 */
+#define CS_EQUALISER_8000_A0 20698 /* Floating point value 1.263312 */
+#define CS_EQUALISER_8000_A1 -9859 /* Floating point value -0.601748 */
+#define CS_EQUALISER_8000_A2 -4599 /* Floating point value -0.280681 */
+#define CS_EQUALISER_8000_B1 -7797 /* Floating point value -0.475865 */
+#define CS_EQUALISER_8000_B2 -6687 /* Floating point value -0.408154 */
+#define CS_EQUALISER_8000_SCALE 14
+#define CSEX_EQUALISER_8000_A0 30912 /* Floating point value 0.943357 */
+#define CSEX_EQUALISER_8000_A1 -14724 /* Floating point value -0.449345 */
+#define CSEX_EQUALISER_8000_A2 -6868 /* Floating point value -0.209594 */
+#define CSEX_EQUALISER_8000_B1 -15593 /* Floating point value -0.475865 */
+#define CSEX_EQUALISER_8000_B2 -13374 /* Floating point value -0.408154 */
+#define CSEX_EQUALISER_8000_SCALE 15
+
+/* Equaliser coefficients for 11025Hz sample rate, CS scaled with 1.027761 and CSEX scaled with 0.767463 */
+#define CS_EQUALISER_11025_A0 18041 /* Floating point value 1.101145 */
+#define CS_EQUALISER_11025_A1 2278 /* Floating point value 0.139020 */
+#define CS_EQUALISER_11025_A2 -14163 /* Floating point value -0.864423 */
+#define CS_EQUALISER_11025_B1 402 /* Floating point value 0.024541 */
+#define CS_EQUALISER_11025_B2 -14892 /* Floating point value -0.908930 */
+#define CS_EQUALISER_11025_SCALE 14
+#define CSEX_EQUALISER_11025_A0 31983 /* Floating point value 0.976058 */
+#define CSEX_EQUALISER_11025_A1 -22784 /* Floating point value -0.695326 */
+#define CSEX_EQUALISER_11025_A2 -2976 /* Floating point value -0.090809 */
+#define CSEX_EQUALISER_11025_B1 -20008 /* Floating point value -0.610594 */
+#define CSEX_EQUALISER_11025_B2 -10196 /* Floating point value -0.311149 */
+#define CSEX_EQUALISER_11025_SCALE 15
+
+/* Equaliser coefficients for 12000Hz sample rate, CS scaled with 1.032521 and CSEX scaled with 0.771017 */
+#define CS_EQUALISER_12000_A0 20917 /* Floating point value 1.276661 */
+#define CS_EQUALISER_12000_A1 -16671 /* Floating point value -1.017519 */
+#define CS_EQUALISER_12000_A2 -723 /* Floating point value -0.044128 */
+#define CS_EQUALISER_12000_B1 -11954 /* Floating point value -0.729616 */
+#define CS_EQUALISER_12000_B2 -3351 /* Floating point value -0.204532 */
+#define CS_EQUALISER_12000_SCALE 14
+#define CSEX_EQUALISER_12000_A0 16500 /* Floating point value 1.007095 */
+#define CSEX_EQUALISER_12000_A1 -14285 /* Floating point value -0.871912 */
+#define CSEX_EQUALISER_12000_A2 381 /* Floating point value 0.023232 */
+#define CSEX_EQUALISER_12000_B1 -12220 /* Floating point value -0.745857 */
+#define CSEX_EQUALISER_12000_B2 -3099 /* Floating point value -0.189171 */
+#define CSEX_EQUALISER_12000_SCALE 14
+
+/* Equaliser coefficients for 16000Hz sample rate, CS scaled with 1.031378 and CSEX scaled with 0.770164 */
+#define CS_EQUALISER_16000_A0 20998 /* Floating point value 1.281629 */
+#define CS_EQUALISER_16000_A1 -17627 /* Floating point value -1.075872 */
+#define CS_EQUALISER_16000_A2 -678 /* Floating point value -0.041365 */
+#define CS_EQUALISER_16000_B1 -11882 /* Floating point value -0.725239 */
+#define CS_EQUALISER_16000_B2 -3676 /* Floating point value -0.224358 */
+#define CS_EQUALISER_16000_SCALE 14
+#define CSEX_EQUALISER_16000_A0 17713 /* Floating point value 1.081091 */
+#define CSEX_EQUALISER_16000_A1 -14208 /* Floating point value -0.867183 */
+#define CSEX_EQUALISER_16000_A2 -1151 /* Floating point value -0.070247 */
+#define CSEX_EQUALISER_16000_B1 -8440 /* Floating point value -0.515121 */
+#define CSEX_EQUALISER_16000_B2 -6978 /* Floating point value -0.425893 */
+#define CSEX_EQUALISER_16000_SCALE 14
+
+/* Equaliser coefficients for 22050Hz sample rate, CS scaled with 1.041576 and CSEX scaled with 0.777779 */
+#define CS_EQUALISER_22050_A0 22751 /* Floating point value 1.388605 */
+#define CS_EQUALISER_22050_A1 -21394 /* Floating point value -1.305799 */
+#define CS_EQUALISER_22050_A2 654 /* Floating point value 0.039922 */
+#define CS_EQUALISER_22050_B1 -11788 /* Floating point value -0.719494 */
+#define CS_EQUALISER_22050_B2 -3985 /* Floating point value -0.243245 */
+#define CS_EQUALISER_22050_SCALE 14
+#define CSEX_EQUALISER_22050_A0 20855 /* Floating point value 1.272910 */
+#define CSEX_EQUALISER_22050_A1 -21971 /* Floating point value -1.341014 */
+#define CSEX_EQUALISER_22050_A2 2744 /* Floating point value 0.167462 */
+#define CSEX_EQUALISER_22050_B1 -10063 /* Floating point value -0.614219 */
+#define CSEX_EQUALISER_22050_B2 -5659 /* Floating point value -0.345384 */
+#define CSEX_EQUALISER_22050_SCALE 14
+
+/* Equaliser coefficients for 24000Hz sample rate, CS scaled with 1.034495 and CSEX scaled with 0.772491 */
+#define CS_EQUALISER_24000_A0 23099 /* Floating point value 1.409832 */
+#define CS_EQUALISER_24000_A1 -23863 /* Floating point value -1.456506 */
+#define CS_EQUALISER_24000_A2 2481 /* Floating point value 0.151410 */
+#define CS_EQUALISER_24000_B1 -13176 /* Floating point value -0.804201 */
+#define CS_EQUALISER_24000_B2 -2683 /* Floating point value -0.163783 */
+#define CS_EQUALISER_24000_SCALE 14
+#define CSEX_EQUALISER_24000_A0 21286 /* Floating point value 1.299198 */
+#define CSEX_EQUALISER_24000_A1 -23797 /* Floating point value -1.452447 */
+#define CSEX_EQUALISER_24000_A2 3940 /* Floating point value 0.240489 */
+#define CSEX_EQUALISER_24000_B1 -10966 /* Floating point value -0.669303 */
+#define CSEX_EQUALISER_24000_B2 -4833 /* Floating point value -0.294984 */
+#define CSEX_EQUALISER_24000_SCALE 14
+
+/* Equaliser coefficients for 32000Hz sample rate, CS scaled with 1.044559 and CSEX scaled with 0.780006 */
+#define CS_EQUALISER_32000_A0 25575 /* Floating point value 1.560988 */
+#define CS_EQUALISER_32000_A1 -30765 /* Floating point value -1.877724 */
+#define CS_EQUALISER_32000_A2 6386 /* Floating point value 0.389741 */
+#define CS_EQUALISER_32000_B1 -14867 /* Floating point value -0.907410 */
+#define CS_EQUALISER_32000_B2 -1155 /* Floating point value -0.070489 */
+#define CS_EQUALISER_32000_SCALE 14
+#define CSEX_EQUALISER_32000_A0 14623 /* Floating point value 1.785049 */
+#define CSEX_EQUALISER_32000_A1 -18297 /* Floating point value -2.233497 */
+#define CSEX_EQUALISER_32000_A2 4313 /* Floating point value 0.526431 */
+#define CSEX_EQUALISER_32000_B1 -3653 /* Floating point value -0.445939 */
+#define CSEX_EQUALISER_32000_B2 -4280 /* Floating point value -0.522446 */
+#define CSEX_EQUALISER_32000_SCALE 13
+
+/* Equaliser coefficients for 44100Hz sample rate, CS scaled with 1.022170 and CSEX scaled with 0.763288 */
+#define CS_EQUALISER_44100_A0 13304 /* Floating point value 1.623993 */
+#define CS_EQUALISER_44100_A1 -18602 /* Floating point value -2.270743 */
+#define CS_EQUALISER_44100_A2 5643 /* Floating point value 0.688829 */
+#define CS_EQUALISER_44100_B1 -9152 /* Floating point value -1.117190 */
+#define CS_EQUALISER_44100_B2 1067 /* Floating point value 0.130208 */
+#define CS_EQUALISER_44100_SCALE 13
+#define CSEX_EQUALISER_44100_A0 16616 /* Floating point value 2.028315 */
+#define CSEX_EQUALISER_44100_A1 -23613 /* Floating point value -2.882459 */
+#define CSEX_EQUALISER_44100_A2 7410 /* Floating point value 0.904535 */
+#define CSEX_EQUALISER_44100_B1 -4860 /* Floating point value -0.593308 */
+#define CSEX_EQUALISER_44100_B2 -3161 /* Floating point value -0.385816 */
+#define CSEX_EQUALISER_44100_SCALE 13
+
+/* Equaliser coefficients for 48000Hz sample rate, CS scaled with 1.018635 and CSEX scaled with 0.760648 */
+#define CS_EQUALISER_48000_A0 13445 /* Floating point value 1.641177 */
+#define CS_EQUALISER_48000_A1 -19372 /* Floating point value -2.364687 */
+#define CS_EQUALISER_48000_A2 6225 /* Floating point value 0.759910 */
+#define CS_EQUALISER_48000_B1 -9558 /* Floating point value -1.166774 */
+#define CS_EQUALISER_48000_B2 1459 /* Floating point value 0.178074 */
+#define CS_EQUALISER_48000_SCALE 13
+#define CSEX_EQUALISER_48000_A0 17200 /* Floating point value 2.099655 */
+#define CSEX_EQUALISER_48000_A1 -25110 /* Floating point value -3.065220 */
+#define CSEX_EQUALISER_48000_A2 8277 /* Floating point value 1.010417 */
+#define CSEX_EQUALISER_48000_B1 -5194 /* Floating point value -0.634021 */
+#define CSEX_EQUALISER_48000_B2 -2845 /* Floating point value -0.347332 */
+#define CSEX_EQUALISER_48000_SCALE 13
+
+
+/************************************************************************************/
+/* */
+/* The Output Gain Correction */
+/* */
+/************************************************************************************/
+
+#define LVCS_HEADPHONE_SHIFT 2 /* Output Shift */
+#define LVCS_HEADPHONE_SHIFTLOSS 27779 /* Output Shift loss */
+#define LVCS_HEADPHONE_GAIN 6840 /* Unprocessed path gain */
+#define LVCS_EX_HEADPHONE_SHIFT 3 /* EX Output Shift */
+#define LVCS_EX_HEADPHONE_SHIFTLOSS 18600 /* EX Output Shift loss */
+#define LVCS_EX_HEADPHONE_GAIN 5108 /* EX Unprocessed path gain */
+
+#endif
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
new file mode 100755
index 0000000..f5f7cd0
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Init.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq06068 $
+ $Revision: 1307 $
+ $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_Tables.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Memory */
+/* */
+/* DESCRIPTION: */
+/* This function is used for memory allocation and free. It can be called in */
+/* two ways: */
+/* */
+/* hInstance = NULL Returns the memory requirements */
+/* hInstance = Instance handle Returns the memory requirements and */
+/* allocated base addresses for the instance */
+/* */
+/* When this function is called for memory allocation (hInstance=NULL) it is */
+/* passed the default capabilities. */
+/* */
+/* When called for memory allocation the memory base address pointers are NULL on */
+/* return. */
+/* */
+/* When the function is called for free (hInstance = Instance Handle) the */
+/* capabilities are ignored and the memory table returns the allocated memory and */
+/* base addresses used during initialisation. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pMemoryTable Pointer to an empty memory definition table */
+/* pCapabilities Pointer to the default capabilites */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* */
+/* NOTES: */
+/* 1. This function may be interrupted by the LVCS_Process function */
+/* */
+/****************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Memory(LVCS_Handle_t hInstance,
+ LVCS_MemTab_t *pMemoryTable,
+ LVCS_Capabilities_t *pCapabilities)
+{
+
+ LVM_UINT32 ScratchSize;
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+ /*
+ * Instance memory
+ */
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Size = (LVM_UINT32)sizeof(LVCS_Instance_t);
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].Type = LVCS_PERSISTENT;
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress = LVM_NULL;
+
+ /*
+ * Data memory
+ */
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Size = (LVM_UINT32)sizeof(LVCS_Data_t);
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].Type = LVCS_DATA;
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress = LVM_NULL;
+
+ /*
+ * Coefficient memory
+ */
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Size = (LVM_UINT32)sizeof(LVCS_Coefficient_t);
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].Type = LVCS_COEFFICIENT;
+ pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress = LVM_NULL;
+
+ /*
+ * Scratch memory
+ */
+ ScratchSize = (LVM_UINT32)(LVCS_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize); /* Inplace processing */
+ pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Size = ScratchSize;
+ pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].Type = LVCS_SCRATCH;
+ pMemoryTable->Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress = LVM_NULL;
+ }
+ else
+ {
+ /* Read back memory allocation table */
+ *pMemoryTable = pInstance->MemoryTable;
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Init */
+/* */
+/* DESCRIPTION: */
+/* Create and initialisation function for the Concert Sound module */
+/* */
+/* This function can be used to create an algorithm instance by calling with */
+/* hInstance set to LVM_NULL. In this case the algorithm returns the new instance */
+/* handle. */
+/* */
+/* This function can be used to force a full re-initialisation of the algorithm */
+/* by calling with hInstance = Instance Handle. In this case the memory table */
+/* should be correct for the instance, this can be ensured by calling the function */
+/* LVCS_Memory before calling this function. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pMemoryTable Pointer to the memory definition table */
+/* pCapabilities Pointer to the capabilities structure */
+/* */
+/* RETURNS: */
+/* LVCS_Success Initialisation succeeded */
+/* */
+/* NOTES: */
+/* 1. The instance handle is the pointer to the base address of the first memory */
+/* region. */
+/* 2. This function must not be interrupted by the LVCS_Process function */
+/* 3. This function must be called with the same capabilities as used for the */
+/* call to the memory function */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Init(LVCS_Handle_t *phInstance,
+ LVCS_MemTab_t *pMemoryTable,
+ LVCS_Capabilities_t *pCapabilities)
+{
+
+ LVCS_Instance_t *pInstance;
+ LVCS_VolCorrect_t *pLVCS_VolCorrectTable;
+
+
+ /*
+ * Set the instance handle if not already initialised
+ */
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = (LVCS_Handle_t)pMemoryTable->Region[LVCS_MEMREGION_PERSISTENT_SLOW_DATA].pBaseAddress;
+ }
+ pInstance =(LVCS_Instance_t *)*phInstance;
+
+
+ /*
+ * Save the capabilities in the instance structure
+ */
+ pInstance->Capabilities = *pCapabilities;
+
+ /*
+ * Save the memory table in the instance structure
+ */
+ pInstance->MemoryTable = *pMemoryTable;
+
+
+ /*
+ * Set all initial parameters to invalid to force a full initialisation
+ */
+ pInstance->Params.OperatingMode = LVCS_OFF;
+ pInstance->Params.SpeakerType = LVCS_SPEAKERTYPE_MAX;
+ pInstance->OutputDevice = LVCS_HEADPHONE;
+ pInstance->Params.SourceFormat = LVCS_SOURCEMAX;
+ pInstance->Params.CompressorMode = LVM_MODE_OFF;
+ pInstance->Params.SampleRate = LVM_FS_INVALID;
+ pInstance->Params.EffectLevel = 0;
+ pInstance->Params.ReverbLevel = (LVM_UINT16)0x8000;
+ pLVCS_VolCorrectTable = (LVCS_VolCorrect_t*)&LVCS_VolCorrectTable[0];
+ pInstance->VolCorrect = pLVCS_VolCorrectTable[0];
+ pInstance->TransitionGain = 0;
+ /* These current and target values are intialized again in LVCS_Control.c */
+ LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[0],0,0);
+ /* These current and target values are intialized again in LVCS_Control.c */
+ LVC_Mixer_Init(&pInstance->BypassMix.Mixer_Instance.MixerStream[1],0,0);
+
+ /*
+ * Initialise the bypass variables
+ */
+ pInstance->MSTarget0=0;
+ pInstance->MSTarget1=0;
+ pInstance->bInOperatingModeTransition = LVM_FALSE;
+ pInstance->bTimerDone = LVM_FALSE;
+ pInstance->TimerParams.CallBackParam = 0;
+ pInstance->TimerParams.pCallBack = LVCS_TimerCallBack;
+ pInstance->TimerParams.pCallbackInstance = pInstance;
+ pInstance->TimerParams.pCallBackParams = LVM_NULL;
+
+ return(LVCS_SUCCESS);
+}
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
new file mode 100755
index 0000000..a977690
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq06068 $
+ $Revision: 1307 $
+ $Date: 2010-07-22 17:41:25 +0200 (Thu, 22 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Header file for the private layer interface of concert sound. */
+/* */
+/* This files includes all definitions, types, structures and function */
+/* prototypes required by the execution layer. */
+/* */
+/************************************************************************************/
+
+#ifndef __LVCS_PRIVATE_H__
+#define __LVCS_PRIVATE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h" /* Calling or Application layer definitions */
+#include "LVCS_StereoEnhancer.h" /* Stereo enhancer module definitions */
+#include "LVCS_ReverbGenerator.h" /* Reverberation module definitions */
+#include "LVCS_Equaliser.h" /* Equaliser module definitions */
+#include "LVCS_BypassMix.h" /* Bypass Mixer module definitions */
+#include "LVM_Timer.h"
+
+
+/************************************************************************************/
+/* */
+/* Defines */
+/* */
+/************************************************************************************/
+
+/* Configuration switch controls */
+#define LVCS_STEREOENHANCESWITCH 0x0001 /* Stereo enhancement enable control */
+#define LVCS_REVERBSWITCH 0x0002 /* Reverberation enable control */
+#define LVCS_EQUALISERSWITCH 0x0004 /* Equaliser enable control */
+#define LVCS_BYPASSMIXSWITCH 0x0008 /* Bypass mixer enable control */
+
+/* Memory */
+#define LVCS_SCRATCHBUFFERS 6 /* Number of buffers required for inplace processing */
+
+/* General */
+#define LVCS_INVALID 0xFFFF /* Invalid init parameter */
+#define LVCS_BYPASS_MIXER_TC 100 /* Bypass mixer time */
+
+/* Access to external coefficients table */
+#define LVCS_NR_OF_FS 9
+#define LVCS_NR_OF_CHAN_CFG 2
+
+
+/************************************************************************************/
+/* */
+/* Types */
+/* */
+/************************************************************************************/
+
+typedef LVM_UINT16 LVCS_Configuration_t; /* Internal algorithm configuration */
+
+typedef enum
+{
+ LVCS_HEADPHONE = 0,
+ LVCS_DEVICE_MAX = LVM_MAXENUM
+} LVCS_OutputDevice_en;
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+/* Volume correction structure */
+typedef struct
+{
+ LVM_INT16 CompFull; /* Post CS compression 100% effect */
+ LVM_INT16 CompMin; /* Post CS compression 0% effect */
+ LVM_INT16 GainFull; /* CS gain correct 100% effect */
+ LVM_INT16 GainMin; /* CS gain correct 0% effect */
+} LVCS_VolCorrect_t;
+
+/* Instance structure */
+typedef struct
+{
+ /* Public parameters */
+ LVCS_MemTab_t MemoryTable; /* Instance memory allocation table */
+ LVCS_Params_t Params; /* Instance parameters */
+ LVCS_Capabilities_t Capabilities; /* Initialisation capabilities */
+
+ /* Private parameters */
+ LVCS_OutputDevice_en OutputDevice; /* Selected output device type */
+ LVCS_VolCorrect_t VolCorrect; /* Volume correction settings */
+ LVM_INT16 TransitionGain; /* Transition gain */
+
+ /* Sub-block configurations */
+ LVCS_StereoEnhancer_t StereoEnhancer; /* Stereo enhancer configuration */
+ LVCS_ReverbGenerator_t Reverberation; /* Reverberation configuration */
+ LVCS_Equaliser_t Equaliser; /* Equaliser configuration */
+ LVCS_BypassMix_t BypassMix; /* Bypass mixer configuration */
+
+ /* Bypass variable */
+ LVM_INT16 MSTarget0; /* Mixer state control variable for smooth transtion */
+ LVM_INT16 MSTarget1; /* Mixer state control variable for smooth transtion */
+ LVM_INT16 bInOperatingModeTransition; /* Operating mode transition flag */
+ LVM_INT16 bTimerDone; /* Timer completion flag */
+ LVM_Timer_Params_t TimerParams; /* Timer parameters */
+ LVM_Timer_Instance_t TimerInstance; /* Timer instance */
+
+} LVCS_Instance_t;
+
+/* Coefficient Structure */
+typedef struct
+{
+ Biquad_Instance_t EqualiserBiquadInstance;
+ Biquad_Instance_t ReverbBiquadInstance;
+ Biquad_Instance_t SEBiquadInstanceMid;
+ Biquad_Instance_t SEBiquadInstanceSide;
+
+} LVCS_Coefficient_t;
+
+/* Data Structure */
+typedef struct
+{
+ Biquad_2I_Order2_Taps_t EqualiserBiquadTaps;
+ Biquad_2I_Order2_Taps_t ReverbBiquadTaps;
+ Biquad_1I_Order1_Taps_t SEBiquadTapsMid;
+ Biquad_1I_Order2_Taps_t SEBiquadTapsSide;
+
+} LVCS_Data_t;
+
+
+void LVCS_TimerCallBack ( void* hInstance,
+ void* pCallBackParams,
+ LVM_INT32 CallbackParam);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PRIVATE_H */
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
new file mode 100755
index 0000000..999b8bb
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "VectorArithmetic.h"
+#include "CompLim.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Process_CS */
+/* */
+/* DESCRIPTION: */
+/* Process function for the Concert Sound module based on the following block */
+/* diagram: */
+/* _________ ________ _____ _______ ___ ______ */
+/* | | | | | | | | | | | | */
+/* ----->| Stereo |->| Reverb |->| Equ |->| Alpha |-->| + |-| Gain |----> */
+/* | | Enhance | |________| |_____| |_______| |___| |______| */
+/* | |_________| | */
+/* | ___________ | */
+/* | | | | */
+/* |------------------------------->| 1 - Alpha |-----| */
+/* |___________| */
+/* */
+/* The Stereo Enhancer, Reverb and Equaliser blocks are each configured to have */
+/* their gain to give a near peak to peak output (-0.1dBFS) with a worst case */
+/* input signal. The gains of these blocks are re-combined in the Alpha mixer and */
+/* the gain block folloing the sum. */
+/* */
+/* The processing uses the output buffer for data storage after each processing */
+/* block. When processing is inplace a copy of the input signal is made in scratch */
+/* memory for the 1-Alpha path. */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+ const LVM_INT16 *pInput;
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVM_INT16 *pScratch = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+ LVCS_ReturnStatus_en err;
+
+ /*
+ * Check if the processing is inplace
+ */
+ if (pInData == pOutData)
+ {
+ /* Processing inplace */
+ pInput = pScratch + (2*NumSamples);
+ Copy_16((LVM_INT16 *)pInData, /* Source */
+ (LVM_INT16 *)pInput, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+ }
+ else
+ {
+ /* Processing outplace */
+ pInput = pInData;
+ }
+
+ /*
+ * Call the stereo enhancer
+ */
+ err=LVCS_StereoEnhancer(hInstance, /* Instance handle */
+ pInData, /* Pointer to the input data */
+ pOutData, /* Pointer to the output data */
+ NumSamples); /* Number of samples to process */
+
+ /*
+ * Call the reverb generator
+ */
+ err=LVCS_ReverbGenerator(hInstance, /* Instance handle */
+ pOutData, /* Pointer to the input data */
+ pOutData, /* Pointer to the output data */
+ NumSamples); /* Number of samples to process */
+
+ /*
+ * Call the equaliser
+ */
+ err=LVCS_Equaliser(hInstance, /* Instance handle */
+ pOutData, /* Pointer to the input data */
+ NumSamples); /* Number of samples to process */
+
+ /*
+ * Call the bypass mixer
+ */
+ err=LVCS_BypassMixer(hInstance, /* Instance handle */
+ pOutData, /* Pointer to the processed data */
+ pInput, /* Pointer to the input (unprocessed) data */
+ pOutData, /* Pointer to the output data */
+ NumSamples); /* Number of samples to process */
+
+ if(err !=LVCS_SUCCESS)
+ {
+ return err;
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the Concert Sound module. The implementation supports two */
+/* variants of the algorithm, one for headphones and one for mobile speakers. */
+/* */
+/* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */
+/* format is not supported, the calling routine must convert the mono stream to */
+/* mono-in-stereo. */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVCS_Success Succeeded */
+/* LVCS_TooManySamples NumSamples was larger than the maximum block size */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+
+ LVCS_Instance_t *pInstance =(LVCS_Instance_t *)hInstance;
+ LVCS_ReturnStatus_en err;
+
+ /*
+ * Check the number of samples is not too large
+ */
+ if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+ {
+ return(LVCS_TOOMANYSAMPLES);
+ }
+
+ /*
+ * Check if the algorithm is enabled
+ */
+ if (pInstance->Params.OperatingMode != LVCS_OFF)
+ {
+ /*
+ * Call CS process function
+ */
+ err=LVCS_Process_CS(hInstance,
+ pInData,
+ pOutData,
+ NumSamples);
+
+ /*
+ * Compress to reduce expansion effect of Concert Sound and correct volume
+ * differences for difference settings. Not applied in test modes
+ */
+ if ((pInstance->Params.OperatingMode == LVCS_ON)&&(pInstance->Params.CompressorMode == LVM_MODE_ON))
+ {
+ LVM_INT16 Gain = pInstance->VolCorrect.CompMin;
+ LVM_INT32 Current1;
+
+ Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
+ Gain = (LVM_INT16)( pInstance->VolCorrect.CompMin
+ - (((LVM_INT32)pInstance->VolCorrect.CompMin * (Current1)) >> 15)
+ + (((LVM_INT32)pInstance->VolCorrect.CompFull * (Current1)) >> 15) );
+
+ NonLinComp_D16(Gain, /* Compressor gain setting */
+ pOutData,
+ pOutData,
+ (LVM_INT32)(2*NumSamples));
+ }
+
+
+ if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+
+ /*
+ * Re-init bypass mix when timer has completed
+ */
+ if ((pInstance->bTimerDone == LVM_TRUE) &&
+ (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
+ {
+ err=LVCS_BypassMixInit(hInstance,
+ &pInstance->Params);
+
+ if(err != LVCS_SUCCESS)
+ {
+ return err;
+ }
+
+ }
+ else{
+ LVM_Timer ( &pInstance->TimerInstance,
+ (LVM_INT16)NumSamples);
+ }
+ }
+ }
+ else
+ {
+ if (pInData != pOutData)
+ {
+ /*
+ * The algorithm is disabled so just copy the data
+ */
+ Copy_16((LVM_INT16 *)pInData, /* Source */
+ (LVM_INT16 *)pOutData, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+ }
+ }
+
+
+ return(LVCS_SUCCESS);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
new file mode 100755
index 0000000..861bde6
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1315 $
+ $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_ReverbGenerator.h"
+#include "LVC_Mixer.h"
+#include "VectorArithmetic.h"
+#include "BIQUAD.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_ReverbGeneratorInit */
+/* */
+/* DESCRIPTION: */
+/* Initialises the reverb module. The delay buffer size is configured for the */
+/* sample rate and the speaker type. */
+/* */
+/* The routine may also be called for re-initialisation, i.e. when one of the */
+/* control parameters has changed. In this case the delay and filters are only */
+/* re-initialised if one of the following two conditions is met: */
+/* - the sample rate has changed */
+/* - the speaker type changes to/from the mobile speaker */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Pointer to the inialisation parameters */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. In the delay settings 'Samples' is the number of samples to the end of the */
+/* buffer. */
+/* 2. The numerator coefficients of the filter are negated to cause an inversion. */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams)
+{
+
+ LVM_UINT16 Delay;
+ LVM_UINT16 Offset;
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_ReverbGenerator_t *pConfig = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+ LVCS_Data_t *pData = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+ LVCS_Coefficient_t *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+ BQ_C16_Coefs_t Coeffs;
+ const BiquadA012B12CoefsSP_t *pReverbCoefTable;
+
+ /*
+ * Initialise the delay and filters if:
+ * - the sample rate has changed
+ * - the speaker type has changed to or from the mobile speaker
+ */
+ if(pInstance->Params.SampleRate != pParams->SampleRate ) /* Sample rate change test */
+
+ {
+ /*
+ * Setup the delay
+ */
+ Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
+
+
+ pConfig->DelaySize = (LVM_INT16)(2 * Delay);
+ pConfig->DelayOffset = 0;
+ LoadConst_16(0, /* Value */
+ (LVM_INT16 *)&pConfig->StereoSamples[0], /* Destination */
+ (LVM_UINT16)(sizeof(pConfig->StereoSamples)/sizeof(LVM_INT16))); /* Number of words */
+
+ /*
+ * Setup the filters
+ */
+ Offset = (LVM_UINT16)pParams->SampleRate;
+ pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
+
+ /* Convert incoming coefficients to the required format/ordering */
+ Coeffs.A0 = (LVM_INT16)pReverbCoefTable[Offset].A0;
+ Coeffs.A1 = (LVM_INT16)pReverbCoefTable[Offset].A1;
+ Coeffs.A2 = (LVM_INT16)pReverbCoefTable[Offset].A2;
+ Coeffs.B1 = (LVM_INT16)-pReverbCoefTable[Offset].B1;
+ Coeffs.B2 = (LVM_INT16)-pReverbCoefTable[Offset].B2;
+
+ LoadConst_16(0, /* Value */
+ (void *)&pData->ReverbBiquadTaps, /* Destination Cast to void: no dereferencing in function*/
+ (LVM_UINT16)(sizeof(pData->ReverbBiquadTaps)/sizeof(LVM_INT16))); /* Number of words */
+
+ BQ_2I_D16F16Css_TRC_WRA_01_Init(&pCoefficients->ReverbBiquadInstance,
+ &pData->ReverbBiquadTaps,
+ &Coeffs);
+
+ /* Callbacks */
+ switch(pReverbCoefTable[Offset].Scale)
+ {
+ case 14:
+ pConfig->pBiquadCallBack = BQ_2I_D16F16C14_TRC_WRA_01;
+ break;
+ case 15:
+ pConfig->pBiquadCallBack = BQ_2I_D16F16C15_TRC_WRA_01;
+ break;
+ }
+
+
+ /*
+ * Setup the mixer
+ */
+ pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
+ pConfig->UnprocGain = (LVM_UINT16)(HEADPHONEGAINUNPROC);
+ }
+
+ if(pInstance->Params.ReverbLevel != pParams->ReverbLevel)
+ {
+ LVM_INT32 ReverbPercentage=83886; // 1 Percent Reverb i.e 1/100 in Q 23 format
+ ReverbPercentage*=pParams->ReverbLevel; // Actual Reverb Level in Q 23 format
+ pConfig->ReverbLevel=(LVM_INT16)(ReverbPercentage>>8); // Reverb Level in Q 15 format
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_Reverb */
+/* */
+/* DESCRIPTION: */
+/* Create reverb using the block of input samples based on the following block */
+/* diagram: */
+/* ________ ________ */
+/* | | | | */
+/* _____ _______ | |----------->| | ______ ___ */
+/* | | | | | Stereo | | L & R | | | | | */
+/* -->| LPF |-->| Delay |-->| to | ____ | to |-->| Gain |-->| + |--> */
+/* | |_____| |_______| | L & R | | | | Stereo | |______| |___| */
+/* | | |-->| -1 |-->| | | */
+/* | |________| |____| |________| | */
+/* | | */
+/* |-----------------------------------------------------------------------| */
+/* */
+/* The input buffer is broken in to sub-blocks of the size of the delay or less. */
+/* This allows the delay buffer to be treated as a circular buffer but processed */
+/* as a linear buffer. */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pInData Pointer to the input buffer */
+/* pOutData Pointer to the output buffer */
+/* NumSamples Number of samples to process */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. Process in blocks of samples the size of the delay where possible, if not */
+/* the number of samples left over */
+/* 2. The Gain is combined with the LPF and incorporated in to the coefficients */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_ReverbGenerator_t *pConfig = (LVCS_ReverbGenerator_t *)&pInstance->Reverberation;
+ LVCS_Coefficient_t *pCoefficients = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+ LVM_INT16 *pScratch = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+
+ /*
+ * Copy the data to the output in outplace processing
+ */
+ if (pInData != pOutData)
+ {
+ /*
+ * Reverb not required so just copy the data
+ */
+ Copy_16((LVM_INT16 *)pInData, /* Source */
+ (LVM_INT16 *)pOutData, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+ }
+
+
+ /*
+ * Check if the reverb is required
+ */
+ if (((pInstance->Params.SpeakerType == LVCS_HEADPHONE) || /* Disable when CS4MS in stereo mode */
+ (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
+ (pInstance->Params.SourceFormat != LVCS_STEREO)) &&
+ ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) !=0)) /* For validation testing */
+ {
+ /********************************************************************************/
+ /* */
+ /* Copy the input data to scratch memory and filter it */
+ /* */
+ /********************************************************************************/
+
+ /*
+ * Copy the input data to the scratch memory
+ */
+ Copy_16((LVM_INT16 *)pInData, /* Source */
+ (LVM_INT16 *)pScratch, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+
+
+ /*
+ * Filter the data
+ */
+ (pConfig->pBiquadCallBack)((Biquad_Instance_t*)&pCoefficients->ReverbBiquadInstance,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16)NumSamples);
+
+ Mult3s_16x16( (LVM_INT16 *)pScratch,
+ pConfig->ReverbLevel,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16)(2*NumSamples));
+
+
+ /*
+ * Apply the delay mix
+ */
+ DelayMix_16x16((LVM_INT16 *)pScratch,
+ &pConfig->StereoSamples[0],
+ pConfig->DelaySize,
+ pOutData,
+ &pConfig->DelayOffset,
+ (LVM_INT16)NumSamples);
+
+
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
new file mode 100755
index 0000000..1164bce
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_ReverbGenerator.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_REVERBGENERATOR_H__
+#define __LVCS_REVERBGENERATOR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVC_Mixer.h"
+
+
+/************************************************************************************/
+/* */
+/* Defines */
+/* */
+/************************************************************************************/
+
+#define HEADPHONEGAINPROC LVCS_HEADPHONE_PROCGAIN
+#define HEADPHONEGAINUNPROC LVCS_HEADPHONE_UNPROCGAIN
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+
+/* Reverberation module structure */
+typedef struct
+{
+
+ /* Stereo delay */
+ LVM_INT16 DelaySize;
+ LVM_INT16 DelayOffset;
+ LVM_INT16 ProcGain;
+ LVM_INT16 UnprocGain;
+ LVM_INT16 StereoSamples[2*LVCS_STEREODELAY_CS_48KHZ];
+
+ /* Reverb Level */
+ LVM_INT16 ReverbLevel;
+
+ /* Filter */
+ void (*pBiquadCallBack) (Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+} LVCS_ReverbGenerator_t;
+
+
+/************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams);
+
+LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInput,
+ LVM_INT16 *pOutput,
+ LVM_UINT16 NumSamples);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* REVERB_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
new file mode 100755
index 0000000..b67d824
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1315 $
+ $Date: 2010-07-23 11:52:08 +0200 (Fri, 23 Jul 2010) $
+
+*************************************************************************************/
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS.h"
+#include "LVCS_Private.h"
+#include "LVCS_StereoEnhancer.h"
+#include "VectorArithmetic.h"
+#include "LVCS_Tables.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_StereoEnhanceInit */
+/* */
+/* DESCRIPTION: */
+/* Initialises the stereo enhancement module based on the sample rate. */
+/* */
+/* The function selects the coefficients for the filters and clears the data */
+/* history. It is also used for re-initialisation when one of the system control */
+/* parameters changes but will only change the coefficients and clear the history */
+/* if the sample rate or speaker type has changed. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pParams Initialisation parameters */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams)
+{
+
+ LVM_UINT16 Offset;
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_StereoEnhancer_t *pConfig = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+ LVCS_Data_t *pData = (LVCS_Data_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_DATA].pBaseAddress;
+ LVCS_Coefficient_t *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+ FO_C16_Coefs_t CoeffsMid;
+ BQ_C16_Coefs_t CoeffsSide;
+ const BiquadA012B12CoefsSP_t *pSESideCoefs;
+
+ /*
+ * If the sample rate or speaker type has changed update the filters
+ */
+ if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
+ (pInstance->Params.SpeakerType != pParams->SpeakerType))
+ {
+ /*
+ * Set the filter coefficients based on the sample rate
+ */
+ /* Mid filter */
+ Offset = (LVM_UINT16)pParams->SampleRate;
+
+ /* Convert incoming coefficients to the required format/ordering */
+ CoeffsMid.A0 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A0;
+ CoeffsMid.A1 = (LVM_INT16) LVCS_SEMidCoefTable[Offset].A1;
+ CoeffsMid.B1 = (LVM_INT16)-LVCS_SEMidCoefTable[Offset].B1;
+
+ /* Clear the taps */
+ LoadConst_16(0, /* Value */
+ (void *)&pData->SEBiquadTapsMid, /* Destination Cast to void:\
+ no dereferencing in function*/
+ (LVM_UINT16)(sizeof(pData->SEBiquadTapsMid)/sizeof(LVM_UINT16))); /* Number of words */
+
+ FO_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceMid,
+ &pData->SEBiquadTapsMid,
+ &CoeffsMid);
+
+ /* Callbacks */
+ if(LVCS_SEMidCoefTable[Offset].Scale==15)
+ {
+ pConfig->pBiquadCallBack_Mid = FO_1I_D16F16C15_TRC_WRA_01;
+ }
+
+ Offset = (LVM_UINT16)(pParams->SampleRate);
+ pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
+
+ /* Side filter */
+ /* Convert incoming coefficients to the required format/ordering */
+ CoeffsSide.A0 = (LVM_INT16) pSESideCoefs[Offset].A0;
+ CoeffsSide.A1 = (LVM_INT16) pSESideCoefs[Offset].A1;
+ CoeffsSide.A2 = (LVM_INT16) pSESideCoefs[Offset].A2;
+ CoeffsSide.B1 = (LVM_INT16)-pSESideCoefs[Offset].B1;
+ CoeffsSide.B2 = (LVM_INT16)-pSESideCoefs[Offset].B2;
+
+ /* Clear the taps */
+ LoadConst_16(0, /* Value */
+ (void *)&pData->SEBiquadTapsSide, /* Destination Cast to void:\
+ no dereferencing in function*/
+ (LVM_UINT16)(sizeof(pData->SEBiquadTapsSide)/sizeof(LVM_UINT16))); /* Number of words */
+
+
+ /* Callbacks */
+ switch(pSESideCoefs[Offset].Scale)
+ {
+ case 14:
+ BQ_1I_D16F32Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+ &pData->SEBiquadTapsSide,
+ &CoeffsSide);
+
+ pConfig->pBiquadCallBack_Side = BQ_1I_D16F32C14_TRC_WRA_01;
+ break;
+ case 15:
+ BQ_1I_D16F16Css_TRC_WRA_01_Init(&pCoefficient->SEBiquadInstanceSide,
+ &pData->SEBiquadTapsSide,
+ &CoeffsSide);
+
+ pConfig->pBiquadCallBack_Side = BQ_1I_D16F16C15_TRC_WRA_01;
+ break;
+ }
+
+ }
+
+
+ return(LVCS_SUCCESS);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVCS_StereoEnhance */
+/* */
+/* DESCRIPTION: */
+/* Enhance the stereo image in the input samples based on the following block */
+/* diagram: */
+/* */
+/* ________ */
+/* ________ | | ________ */
+/* | | Middle | Treble | | | */
+/* | |---------->| Boost |-------->| | */
+/* | Stereo | |________| | M & S | */
+/* -->| to | ________ | to |--> */
+/* | M & S | Side | | | Stereo | */
+/* | |---------->| Side |-------->| | */
+/* |________| | Boost | |________| */
+/* |________| */
+/* */
+/* */
+/* If the input signal is a mono signal there will be no side signal and hence */
+/* the side filter will not be run. In mobile speaker mode the middle filter is */
+/* not required and the Trebble boost filter is replaced by a simple gain block. */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance Handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples to process */
+/* */
+/* RETURNS: */
+/* LVCS_Success Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The side filter is not used in Mobile Speaker mode */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples)
+{
+
+ LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
+ LVCS_StereoEnhancer_t *pConfig = (LVCS_StereoEnhancer_t *)&pInstance->StereoEnhancer;
+ LVCS_Coefficient_t *pCoefficient = (LVCS_Coefficient_t *)pInstance->MemoryTable.Region[LVCS_MEMREGION_PERSISTENT_FAST_COEF].pBaseAddress;
+ LVM_INT16 *pScratch = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
+
+ /*
+ * Check if the Stereo Enhancer is enabled
+ */
+ if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0)
+ {
+ /*
+ * Convert from stereo to middle and side
+ */
+ From2iToMS_16x16(pInData,
+ pScratch,
+ pScratch+NumSamples,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Apply filter to the middle signal
+ */
+ if (pInstance->OutputDevice == LVCS_HEADPHONE)
+ {
+ (pConfig->pBiquadCallBack_Mid)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceMid,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16 *)pScratch,
+ (LVM_INT16)NumSamples);
+ }
+ else
+ {
+ Mult3s_16x16(pScratch, /* Source */
+ (LVM_INT16)pConfig->MidGain, /* Gain */
+ pScratch, /* Destination */
+ (LVM_INT16)NumSamples); /* Number of samples */
+ }
+
+ /*
+ * Apply the filter the side signal only in stereo mode for headphones
+ * and in all modes for mobile speakers
+ */
+ if (pInstance->Params.SourceFormat == LVCS_STEREO)
+ {
+ (pConfig->pBiquadCallBack_Side)((Biquad_Instance_t*)&pCoefficient->SEBiquadInstanceSide,
+ (LVM_INT16 *)(pScratch + NumSamples),
+ (LVM_INT16 *)(pScratch + NumSamples),
+ (LVM_INT16)NumSamples);
+ }
+
+ /*
+ * Convert from middle and side to stereo
+ */
+ MSTo2i_Sat_16x16(pScratch,
+ pScratch+NumSamples,
+ pOutData,
+ (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * The stereo enhancer is disabled so just copy the data
+ */
+ Copy_16((LVM_INT16 *)pInData, /* Source */
+ (LVM_INT16 *)pOutData, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Left and right */
+
+ }
+
+ return(LVCS_SUCCESS);
+}
+
+
+
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
new file mode 100755
index 0000000..c3f6296
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_StereoEnhancer.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+#ifndef __LVCS_STEREOENHANCER_H__
+#define __LVCS_STEREOENHANCER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "Filters.h" /* Filter definitions */
+#include "LVCS_Headphone_Coeffs.h" /* Headphone coefficients */
+#include "BIQUAD.h"
+
+
+/************************************************************************************/
+/* */
+/* Structures */
+/* */
+/************************************************************************************/
+
+/* Stereo enhancer structure */
+typedef struct
+{
+ /*
+ * Middle filter
+ */
+ void (*pBiquadCallBack_Mid)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+ /*
+ * Side filter
+ */
+ void (*pBiquadCallBack_Side)(Biquad_Instance_t*, LVM_INT16*, LVM_INT16*, LVM_INT16);
+
+ LVM_UINT16 MidGain; /* Middle gain in mobile speaker mode */
+
+} LVCS_StereoEnhancer_t;
+
+
+/************************************************************************************/
+/* */
+/* Function prototypes */
+/* */
+/************************************************************************************/
+
+LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance,
+ LVCS_Params_t *pParams);
+
+LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 NumSamples);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* STEREOENHANCE_H */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
new file mode 100755
index 0000000..ad4eb1e
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: beq07716 $
+ $Revision: 1001 $
+ $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
+
+*************************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVCS_Private.h"
+#include "Filters.h" /* Filter definitions */
+#include "BIQUAD.h" /* Biquad definitions */
+#include "LVCS_Headphone_Coeffs.h" /* Headphone coefficients */
+
+
+/************************************************************************************/
+/* */
+/* Stereo Enhancer coefficient constant tables */
+/* */
+/************************************************************************************/
+
+/* Coefficient table for the middle filter */
+const BiquadA01B1CoefsSP_t LVCS_SEMidCoefTable[] = {
+ {CS_MIDDLE_8000_A0, /* 8kS/s coefficients */
+ CS_MIDDLE_8000_A1,
+ CS_MIDDLE_8000_B1,
+ (LVM_UINT16 )CS_MIDDLE_8000_SCALE},
+ {CS_MIDDLE_11025_A0, /* 11kS/s coefficients */
+ CS_MIDDLE_11025_A1,
+ CS_MIDDLE_11025_B1,
+ (LVM_UINT16 )CS_MIDDLE_11025_SCALE},
+ {CS_MIDDLE_12000_A0, /* 12kS/s coefficients */
+ CS_MIDDLE_12000_A1,
+ CS_MIDDLE_12000_B1,
+ (LVM_UINT16 )CS_MIDDLE_12000_SCALE},
+ {CS_MIDDLE_16000_A0, /* 16kS/s coefficients */
+ CS_MIDDLE_16000_A1,
+ CS_MIDDLE_16000_B1,
+ (LVM_UINT16 )CS_MIDDLE_16000_SCALE},
+ {CS_MIDDLE_22050_A0, /* 22kS/s coefficients */
+ CS_MIDDLE_22050_A1,
+ CS_MIDDLE_22050_B1,
+ (LVM_UINT16 )CS_MIDDLE_22050_SCALE},
+ {CS_MIDDLE_24000_A0, /* 24kS/s coefficients */
+ CS_MIDDLE_24000_A1,
+ CS_MIDDLE_24000_B1,
+ (LVM_UINT16 )CS_MIDDLE_24000_SCALE},
+ {CS_MIDDLE_32000_A0, /* 32kS/s coefficients */
+ CS_MIDDLE_32000_A1,
+ CS_MIDDLE_32000_B1,
+ (LVM_UINT16 )CS_MIDDLE_32000_SCALE},
+ {CS_MIDDLE_44100_A0, /* 44kS/s coefficients */
+ CS_MIDDLE_44100_A1,
+ CS_MIDDLE_44100_B1,
+ (LVM_UINT16 )CS_MIDDLE_44100_SCALE},
+ {CS_MIDDLE_48000_A0, /* 48kS/s coefficients */
+ CS_MIDDLE_48000_A1,
+ CS_MIDDLE_48000_B1,
+ (LVM_UINT16 )CS_MIDDLE_48000_SCALE}};
+
+/* Coefficient table for the side filter */
+const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[] = {
+ /* Headphone Side coefficients */
+ {CS_SIDE_8000_A0, /* 8kS/s coefficients */
+ CS_SIDE_8000_A1,
+ CS_SIDE_8000_A2,
+ CS_SIDE_8000_B1,
+ CS_SIDE_8000_B2,
+ (LVM_UINT16 )CS_SIDE_8000_SCALE},
+ {CS_SIDE_11025_A0, /* 11kS/s coefficients */
+ CS_SIDE_11025_A1,
+ CS_SIDE_11025_A2,
+ CS_SIDE_11025_B1,
+ CS_SIDE_11025_B2,
+ (LVM_UINT16 )CS_SIDE_11025_SCALE},
+ {CS_SIDE_12000_A0, /* 12kS/s coefficients */
+ CS_SIDE_12000_A1,
+ CS_SIDE_12000_A2,
+ CS_SIDE_12000_B1,
+ CS_SIDE_12000_B2,
+ (LVM_UINT16 )CS_SIDE_12000_SCALE},
+ {CS_SIDE_16000_A0, /* 16kS/s coefficients */
+ CS_SIDE_16000_A1,
+ CS_SIDE_16000_A2,
+ CS_SIDE_16000_B1,
+ CS_SIDE_16000_B2,
+ (LVM_UINT16 )CS_SIDE_16000_SCALE},
+ {CS_SIDE_22050_A0, /* 22kS/s coefficients */
+ CS_SIDE_22050_A1,
+ CS_SIDE_22050_A2,
+ CS_SIDE_22050_B1,
+ CS_SIDE_22050_B2,
+ (LVM_UINT16 )CS_SIDE_22050_SCALE},
+ {CS_SIDE_24000_A0, /* 24kS/s coefficients */
+ CS_SIDE_24000_A1,
+ CS_SIDE_24000_A2,
+ CS_SIDE_24000_B1,
+ CS_SIDE_24000_B2,
+ (LVM_UINT16 )CS_SIDE_24000_SCALE},
+ {CS_SIDE_32000_A0, /* 32kS/s coefficients */
+ CS_SIDE_32000_A1,
+ CS_SIDE_32000_A2,
+ CS_SIDE_32000_B1,
+ CS_SIDE_32000_B2,
+ (LVM_UINT16 )CS_SIDE_32000_SCALE},
+ {CS_SIDE_44100_A0, /* 44kS/s coefficients */
+ CS_SIDE_44100_A1,
+ CS_SIDE_44100_A2,
+ CS_SIDE_44100_B1,
+ CS_SIDE_44100_B2,
+ (LVM_UINT16 )CS_SIDE_44100_SCALE},
+ {CS_SIDE_48000_A0, /* 48kS/s coefficients */
+ CS_SIDE_48000_A1,
+ CS_SIDE_48000_A2,
+ CS_SIDE_48000_B1,
+ CS_SIDE_48000_B2,
+ (LVM_UINT16 )CS_SIDE_48000_SCALE}
+};
+
+
+/************************************************************************************/
+/* */
+/* Equaliser coefficient constant tables */
+/* */
+/************************************************************************************/
+
+const BiquadA012B12CoefsSP_t LVCS_EqualiserCoefTable[] = {
+ /* Headphone coefficients */
+ {CS_EQUALISER_8000_A0, /* 8kS/s coefficients */
+ CS_EQUALISER_8000_A1,
+ CS_EQUALISER_8000_A2,
+ CS_EQUALISER_8000_B1,
+ CS_EQUALISER_8000_B2,
+ (LVM_UINT16 )CS_EQUALISER_8000_SCALE},
+ {CS_EQUALISER_11025_A0, /* 11kS/s coefficients */
+ CS_EQUALISER_11025_A1,
+ CS_EQUALISER_11025_A2,
+ CS_EQUALISER_11025_B1,
+ CS_EQUALISER_11025_B2,
+ (LVM_UINT16 )CS_EQUALISER_11025_SCALE},
+ {CS_EQUALISER_12000_A0, /* 12kS/s coefficients */
+ CS_EQUALISER_12000_A1,
+ CS_EQUALISER_12000_A2,
+ CS_EQUALISER_12000_B1,
+ CS_EQUALISER_12000_B2,
+ (LVM_UINT16 )CS_EQUALISER_12000_SCALE},
+ {CS_EQUALISER_16000_A0, /* 16kS/s coefficients */
+ CS_EQUALISER_16000_A1,
+ CS_EQUALISER_16000_A2,
+ CS_EQUALISER_16000_B1,
+ CS_EQUALISER_16000_B2,
+ (LVM_UINT16 )CS_EQUALISER_16000_SCALE},
+ {CS_EQUALISER_22050_A0, /* 22kS/s coefficients */
+ CS_EQUALISER_22050_A1,
+ CS_EQUALISER_22050_A2,
+ CS_EQUALISER_22050_B1,
+ CS_EQUALISER_22050_B2,
+ (LVM_UINT16 )CS_EQUALISER_22050_SCALE},
+ {CS_EQUALISER_24000_A0, /* 24kS/s coefficients */
+ CS_EQUALISER_24000_A1,
+ CS_EQUALISER_24000_A2,
+ CS_EQUALISER_24000_B1,
+ CS_EQUALISER_24000_B2,
+ (LVM_UINT16 )CS_EQUALISER_24000_SCALE},
+ {CS_EQUALISER_32000_A0, /* 32kS/s coefficients */
+ CS_EQUALISER_32000_A1,
+ CS_EQUALISER_32000_A2,
+ CS_EQUALISER_32000_B1,
+ CS_EQUALISER_32000_B2,
+ (LVM_UINT16 )CS_EQUALISER_32000_SCALE},
+ {CS_EQUALISER_44100_A0, /* 44kS/s coefficients */
+ CS_EQUALISER_44100_A1,
+ CS_EQUALISER_44100_A2,
+ CS_EQUALISER_44100_B1,
+ CS_EQUALISER_44100_B2,
+ (LVM_UINT16 )CS_EQUALISER_44100_SCALE},
+ {CS_EQUALISER_48000_A0, /* 48kS/s coefficients */
+ CS_EQUALISER_48000_A1,
+ CS_EQUALISER_48000_A2,
+ CS_EQUALISER_48000_B1,
+ CS_EQUALISER_48000_B2,
+ (LVM_UINT16 )CS_EQUALISER_48000_SCALE},
+
+ /* Concert Sound EX Headphone coefficients */
+ {CSEX_EQUALISER_8000_A0, /* 8kS/s coefficients */
+ CSEX_EQUALISER_8000_A1,
+ CSEX_EQUALISER_8000_A2,
+ CSEX_EQUALISER_8000_B1,
+ CSEX_EQUALISER_8000_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_8000_SCALE},
+ {CSEX_EQUALISER_11025_A0, /* 11kS/s coefficients */
+ CSEX_EQUALISER_11025_A1,
+ CSEX_EQUALISER_11025_A2,
+ CSEX_EQUALISER_11025_B1,
+ CSEX_EQUALISER_11025_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_11025_SCALE},
+ {CSEX_EQUALISER_12000_A0, /* 12kS/s coefficients */
+ CSEX_EQUALISER_12000_A1,
+ CSEX_EQUALISER_12000_A2,
+ CSEX_EQUALISER_12000_B1,
+ CSEX_EQUALISER_12000_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_12000_SCALE},
+ {CSEX_EQUALISER_16000_A0, /* 16kS/s coefficients */
+ CSEX_EQUALISER_16000_A1,
+ CSEX_EQUALISER_16000_A2,
+ CSEX_EQUALISER_16000_B1,
+ CSEX_EQUALISER_16000_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_16000_SCALE},
+ {CSEX_EQUALISER_22050_A0, /* 22kS/s coefficients */
+ CSEX_EQUALISER_22050_A1,
+ CSEX_EQUALISER_22050_A2,
+ CSEX_EQUALISER_22050_B1,
+ CSEX_EQUALISER_22050_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_22050_SCALE},
+ {CSEX_EQUALISER_24000_A0, /* 24kS/s coefficients */
+ CSEX_EQUALISER_24000_A1,
+ CSEX_EQUALISER_24000_A2,
+ CSEX_EQUALISER_24000_B1,
+ CSEX_EQUALISER_24000_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_24000_SCALE},
+ {CSEX_EQUALISER_32000_A0, /* 32kS/s coefficients */
+ CSEX_EQUALISER_32000_A1,
+ CSEX_EQUALISER_32000_A2,
+ CSEX_EQUALISER_32000_B1,
+ CSEX_EQUALISER_32000_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_32000_SCALE},
+ {CSEX_EQUALISER_44100_A0, /* 44kS/s coefficients */
+ CSEX_EQUALISER_44100_A1,
+ CSEX_EQUALISER_44100_A2,
+ CSEX_EQUALISER_44100_B1,
+ CSEX_EQUALISER_44100_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_44100_SCALE},
+ {CSEX_EQUALISER_48000_A0, /* 48kS/s coefficients */
+ CSEX_EQUALISER_48000_A1,
+ CSEX_EQUALISER_48000_A2,
+ CSEX_EQUALISER_48000_B1,
+ CSEX_EQUALISER_48000_B2,
+ (LVM_UINT16 )CSEX_EQUALISER_48000_SCALE}
+};
+
+
+/************************************************************************************/
+/* */
+/* Reverb delay constant tables */
+/* */
+/************************************************************************************/
+
+/* Stereo delay table for Concert Sound */
+const LVM_UINT16 LVCS_StereoDelayCS[] = {
+ LVCS_STEREODELAY_CS_8KHZ,
+ LVCS_STEREODELAY_CS_11KHZ,
+ LVCS_STEREODELAY_CS_12KHZ,
+ LVCS_STEREODELAY_CS_16KHZ,
+ LVCS_STEREODELAY_CS_22KHZ,
+ LVCS_STEREODELAY_CS_24KHZ,
+ LVCS_STEREODELAY_CS_32KHZ,
+ LVCS_STEREODELAY_CS_44KHZ,
+ LVCS_STEREODELAY_CS_48KHZ};
+
+/************************************************************************************/
+/* */
+/* Reverb coefficients constant table */
+/* */
+/************************************************************************************/
+
+const BiquadA012B12CoefsSP_t LVCS_ReverbCoefTable[] = {
+ /* Headphone coefficients */
+ {CS_REVERB_8000_A0, /* 8kS/s coefficients */
+ CS_REVERB_8000_A1,
+ CS_REVERB_8000_A2,
+ CS_REVERB_8000_B1,
+ CS_REVERB_8000_B2,
+ (LVM_UINT16 )CS_REVERB_8000_SCALE},
+ {CS_REVERB_11025_A0, /* 11kS/s coefficients */
+ CS_REVERB_11025_A1,
+ CS_REVERB_11025_A2,
+ CS_REVERB_11025_B1,
+ CS_REVERB_11025_B2,
+ (LVM_UINT16 )CS_REVERB_11025_SCALE},
+ {CS_REVERB_12000_A0, /* 12kS/s coefficients */
+ CS_REVERB_12000_A1,
+ CS_REVERB_12000_A2,
+ CS_REVERB_12000_B1,
+ CS_REVERB_12000_B2,
+ (LVM_UINT16 )CS_REVERB_12000_SCALE},
+ {CS_REVERB_16000_A0, /* 16kS/s coefficients */
+ CS_REVERB_16000_A1,
+ CS_REVERB_16000_A2,
+ CS_REVERB_16000_B1,
+ CS_REVERB_16000_B2,
+ (LVM_UINT16 )CS_REVERB_16000_SCALE},
+ {CS_REVERB_22050_A0, /* 22kS/s coefficients */
+ CS_REVERB_22050_A1,
+ CS_REVERB_22050_A2,
+ CS_REVERB_22050_B1,
+ CS_REVERB_22050_B2,
+ (LVM_UINT16 )CS_REVERB_22050_SCALE},
+ {CS_REVERB_24000_A0, /* 24kS/s coefficients */
+ CS_REVERB_24000_A1,
+ CS_REVERB_24000_A2,
+ CS_REVERB_24000_B1,
+ CS_REVERB_24000_B2,
+ (LVM_UINT16 )CS_REVERB_24000_SCALE},
+ {CS_REVERB_32000_A0, /* 32kS/s coefficients */
+ CS_REVERB_32000_A1,
+ CS_REVERB_32000_A2,
+ CS_REVERB_32000_B1,
+ CS_REVERB_32000_B2,
+ (LVM_UINT16 )CS_REVERB_32000_SCALE},
+ {CS_REVERB_44100_A0, /* 44kS/s coefficients */
+ CS_REVERB_44100_A1,
+ CS_REVERB_44100_A2,
+ CS_REVERB_44100_B1,
+ CS_REVERB_44100_B2,
+ (LVM_UINT16 )CS_REVERB_44100_SCALE},
+ {CS_REVERB_48000_A0, /* 48kS/s coefficients */
+ CS_REVERB_48000_A1,
+ CS_REVERB_48000_A2,
+ CS_REVERB_48000_B1,
+ CS_REVERB_48000_B2,
+ (LVM_UINT16 )CS_REVERB_48000_SCALE}
+};
+
+
+/************************************************************************************/
+/* */
+/* Bypass mixer constant tables */
+/* */
+/************************************************************************************/
+
+const Gain_t LVCS_OutputGainTable[] = {
+ {LVCS_HEADPHONE_SHIFT, /* Headphone, stereo mode */
+ LVCS_HEADPHONE_SHIFTLOSS,
+ LVCS_HEADPHONE_GAIN},
+ {LVCS_EX_HEADPHONE_SHIFT, /* EX Headphone, stereo mode */
+ LVCS_EX_HEADPHONE_SHIFTLOSS,
+ LVCS_EX_HEADPHONE_GAIN},
+ {LVCS_HEADPHONE_SHIFT, /* Headphone, mono mode */
+ LVCS_HEADPHONE_SHIFTLOSS,
+ LVCS_HEADPHONE_GAIN},
+ {LVCS_EX_HEADPHONE_SHIFT, /* EX Headphone, mono mode */
+ LVCS_EX_HEADPHONE_SHIFTLOSS,
+ LVCS_EX_HEADPHONE_GAIN}
+};
+
+
+/************************************************************************************/
+/* */
+/* Volume correction table */
+/* */
+/* Coefficient order: */
+/* Compression 100% effect */
+/* Compression 0% effect */
+/* Gain 100% effect */
+/* Gain 0% effect */
+/* */
+/* The Compression gain is represented by a Q1.15 number to give a range of 0dB */
+/* to +6dB, E.g.: */
+/* 0 is 0dB compression (no effect) */
+/* 5461 is 1dB compression gain */
+/* 10923 is 2dB compression gain */
+/* 32767 is 6dB compression gain */
+/* */
+/* The Gain is represented as a Q3.13 number to give a range of +8 to -infinity */
+/* E.g.: */
+/* 0 is -infinity */
+/* 32767 is +18dB (x8) gain */
+/* 4096 is 0dB gain */
+/* 1024 is -12dB gain */
+/* */
+/************************************************************************************/
+const LVCS_VolCorrect_t LVCS_VolCorrectTable[] = {
+ {14200, /* Headphone, stereo mode */
+ 0,
+ 4096,
+ 5786},
+ {14200, /* EX Headphone, stereo mode */
+ 0,
+ 4096,
+ 5786},
+ {32767, /* Headphone, mono mode */
+ 0,
+ 4096,
+ 5786},
+ {32767, /* EX Headphone, mono mode */
+ 0,
+ 4096,
+ 5786}
+};
+
+/************************************************************************************/
+/* */
+/* Mixer time constants, 100ms */
+/* */
+/************************************************************************************/
+
+#define LVCS_VOL_TC_Fs8000 32580 /* Floating point value 0.994262695 */
+#define LVCS_VOL_TC_Fs11025 32632 /* Floating point value 0.995849609 */
+#define LVCS_VOL_TC_Fs12000 32643 /* Floating point value 0.996185303 */
+#define LVCS_VOL_TC_Fs16000 32674 /* Floating point value 0.997131348 */
+#define LVCS_VOL_TC_Fs22050 32700 /* Floating point value 0.997924805 */
+#define LVCS_VOL_TC_Fs24000 32705 /* Floating point value 0.998077393 */
+#define LVCS_VOL_TC_Fs32000 32721 /* Floating point value 0.998565674 */
+#define LVCS_VOL_TC_Fs44100 32734 /* Floating point value 0.998962402 */
+#define LVCS_VOL_TC_Fs48000 32737 /* Floating point value 0.999053955 */
+
+
+const LVM_INT16 LVCS_VolumeTCTable[9] = {LVCS_VOL_TC_Fs8000,
+ LVCS_VOL_TC_Fs11025,
+ LVCS_VOL_TC_Fs12000,
+ LVCS_VOL_TC_Fs16000,
+ LVCS_VOL_TC_Fs22050,
+ LVCS_VOL_TC_Fs24000,
+ LVCS_VOL_TC_Fs32000,
+ LVCS_VOL_TC_Fs44100,
+ LVCS_VOL_TC_Fs48000};
+
+/************************************************************************************/
+/* */
+/* Sample rate table */
+/* */
+/************************************************************************************/
+
+const LVM_INT32 LVCS_SampleRateTable[9] = {8000,
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000};
+
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
new file mode 100755
index 0000000..72d6855
--- /dev/null
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/************************************************************************************
+
+ $Author: nxp27078 $
+ $Revision: 672 $
+ $Date: 2010-06-08 19:39:38 +0200 (Tue, 08 Jun 2010) $
+
+*************************************************************************************/
+#ifndef __LVCS_TABLES_H__
+#define __LVCS_TABLES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "BIQUAD.h" /* Biquad definitions */
+
+/************************************************************************************/
+/* */
+/* Stereo Enhancer coefficient constant tables */
+/* */
+/************************************************************************************/
+
+/* Coefficient table for the middle filter */
+extern const BiquadA01B1CoefsSP_t LVCS_SEMidCoefTable[];
+
+/* Coefficient table for the side filter */
+extern const BiquadA012B12CoefsSP_t LVCS_SESideCoefTable[];
+
+/************************************************************************************/
+/* */
+/* Equaliser coefficient constant tables */
+/* */
+/************************************************************************************/
+
+extern const BiquadA012B12CoefsSP_t LVCS_EqualiserCoefTable[];
+
+/************************************************************************************/
+/* */
+/* Reverb delay constant tables */
+/* */
+/************************************************************************************/
+
+/* Stereo delay table for Concert Sound */
+extern const LVM_UINT16 LVCS_StereoDelayCS[];
+
+/************************************************************************************/
+/* */
+/* Reverb coefficients constant table */
+/* */
+/************************************************************************************/
+
+extern const BiquadA012B12CoefsSP_t LVCS_ReverbCoefTable[];
+
+/************************************************************************************/
+/* */
+/* Bypass mixer constant tables */
+/* */
+/************************************************************************************/
+
+extern const Gain_t LVCS_OutputGainTable[];
+
+/************************************************************************************/
+/* */
+/* Volume correction table */
+/* */
+/* Coefficient order: */
+/* Compression 100% effect */
+/* Compression 0% effect */
+/* Gain 100% effect */
+/* Gain 0% effect */
+/* */
+/* The Compression gain is represented by a Q1.15 number to give a range of 0dB */
+/* to +6dB, E.g.: */
+/* 0 is 0dB compression (no effect) */
+/* 5461 is 1dB compression gain */
+/* 10923 is 2dB compression gain */
+/* 32767 is 6dB compression gain */
+/* */
+/* The Gain is represented as a Q3.13 number to give a range of +8 to -infinity */
+/* E.g.: */
+/* 0 is -infinity */
+/* 32767 is +18dB (x8) gain */
+/* 4096 is 0dB gain */
+/* 1024 is -12dB gain */
+/* */
+/************************************************************************************/
+
+extern const LVCS_VolCorrect_t LVCS_VolCorrectTable[];
+extern const LVM_INT16 LVCS_VolumeTCTable[];
+
+
+/************************************************************************************/
+/* */
+/* Sample rates */
+/* */
+/************************************************************************************/
+
+extern LVM_INT32 LVCS_SampleRateTable[];
+
+
+/*Speaker coeffient tables*/
+extern LVM_UINT16 LVCS_MS_Small_SEMiddleGainTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Small_SESideCoefTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Small_EqualiserCoefTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Small_ReverbCoefTable[] ;
+extern LVM_UINT16 LVCS_MS_Small_StereoDelayCS4MS[];
+extern Gain_t LVCS_MS_Small_OutputGainTable[];
+extern LVCS_VolCorrect_t LVCS_MS_Small_VolCorrectTable[];
+extern LVM_UINT16 LVCS_MS_Small_ReverbGainTable[];
+
+extern LVM_UINT16 LVCS_MS_Medium_SEMiddleGainTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Medium_SESideCoefTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Medium_EqualiserCoefTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Medium_ReverbCoefTable[] ;
+extern LVM_UINT16 LVCS_MS_Medium_StereoDelayCS4MS[];
+extern Gain_t LVCS_MS_Medium_OutputGainTable[];
+extern LVCS_VolCorrect_t LVCS_MS_Medium_VolCorrectTable[];
+extern LVM_UINT16 LVCS_MS_Medium_ReverbGainTable[];
+
+extern LVM_UINT16 LVCS_MS_Large_SEMiddleGainTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Large_SESideCoefTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Large_EqualiserCoefTable[];
+extern BiquadA012B12CoefsSP_t LVCS_MS_Large_ReverbCoefTable[] ;
+extern LVM_UINT16 LVCS_MS_Large_StereoDelayCS4MS[];
+extern Gain_t LVCS_MS_Large_OutputGainTable[];
+extern LVCS_VolCorrect_t LVCS_MS_Large_VolCorrectTable[];
+extern LVM_UINT16 LVCS_MS_Large_ReverbGainTable[];
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __LVCS_TABLES_H__ */
+
diff --git a/media/libeffects/lvm/wrapper/Android.mk b/media/libeffects/lvm/wrapper/Android.mk
new file mode 100644
index 0000000..7855dcd
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+
+# music bundle wrapper
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_SRC_FILES:= \
+ Bundle/EffectBundle.cpp
+
+LOCAL_MODULE:= libbundlewrapper
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_STATIC_LIBRARIES += libmusicbundle
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_LDLIBS += -ldl
+else
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/Bundle \
+ $(LOCAL_PATH)/../lib/Common/lib/ \
+ $(LOCAL_PATH)/../lib/Bundle/lib/
+
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
new file mode 100644
index 0000000..4c3ebca
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -0,0 +1,2909 @@
+/*
+ * Copyright (C) 2010-2010 NXP Software
+ * Copyright (C) 2009 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Bundle"
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+#define LOG_NDEBUG 0
+
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <EffectBundle.h>
+
+#define LVM_MAX_SESSIONS 32
+#define MAX_NUM_BANDS 5
+#define MAX_CALL_SIZE 256
+
+// effect_interface_t interface implementation for bass boost
+extern "C" const struct effect_interface_s gLvmEffectInterface;
+
+#define LVM_ERROR_CHECK(LvmStatus, callingFunc, calledFunc){\
+ if (LvmStatus == LVM_NULLADDRESS){\
+ LOGV("\tLVM_ERROR : Parameter error - "\
+ "null pointer returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVM_ALIGNMENTERROR){\
+ LOGV("\tLVM_ERROR : Parameter error - "\
+ "bad alignment returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVM_INVALIDNUMSAMPLES){\
+ LOGV("\tLVM_ERROR : Parameter error - "\
+ "bad number of samples returned by %s in %s\n\n\n\n", callingFunc, calledFunc);\
+ }\
+ if (LvmStatus == LVM_OUTOFRANGE){\
+ LOGV("\tLVM_ERROR : Parameter error - "\
+ "out of range returned by %s in %s\n", callingFunc, calledFunc);\
+ }\
+ }
+
+// Namespaces
+namespace android {
+namespace {
+
+/* local functions */
+#define CHECK_ARG(cond) { \
+ if (!(cond)) { \
+ LOGV("\tLVM_ERROR : Invalid argument: "#cond); \
+ return -EINVAL; \
+ } \
+}
+
+// Flag to allow a one time init of global memory, only happens on first call ever
+int LvmInitFlag = LVM_FALSE;
+SessionContext GlobalSessionMemory[32];
+
+// NXP SW BassBoost UUID
+const effect_descriptor_t gBassBoostDescriptor = {
+ {0x0634f220, 0xddd4, 0x11db, 0xa0fc, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
+ {0x8631f300, 0x72e2, 0x11df, 0xb57e, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+ | EFFECT_FLAG_VOLUME_CTRL),
+ 0, // TODO
+ 1,
+ "Dynamic Bass Boost",
+ "NXP Software Ltd.",
+};
+
+// NXP SW Virtualizer UUID
+const effect_descriptor_t gVirtualizerDescriptor = {
+ {0x37cc2c00, 0xdddd, 0x11db, 0x8577, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0x1d4033c0, 0x8557, 0x11df, 0x9f2d, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_DEVICE_IND
+ | EFFECT_FLAG_VOLUME_CTRL),
+ 0, // TODO
+ 1,
+ "Virtualizer",
+ "NXP Software Ltd.",
+};
+
+// NXP SW Equalizer UUID
+const effect_descriptor_t gEqualizerDescriptor = {
+ {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xce772f20, 0x847d, 0x11df, 0xbb17, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid Eq NXP
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+ 0, // TODO
+ 1,
+ "Equalizer",
+ "NXP Software Ltd.",
+};
+
+// NXP SW Volume UUID
+const effect_descriptor_t gVolumeDescriptor = {
+ {0x09e8ede0, 0xddde, 0x11db, 0xb4f6, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }},
+ {0x119341a0, 0x8469, 0x11df, 0x81f9, { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b }}, //uuid VOL NXP
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST | EFFECT_FLAG_VOLUME_CTRL),
+ 0, // TODO
+ 1,
+ "Volume",
+ "NXP Software Ltd.",
+};
+
+//--- local function prototypes
+void LvmGlobalBundle_init (void);
+int LvmBundle_init (EffectContext *pContext);
+int LvmEffect_enable (EffectContext *pContext);
+int LvmEffect_disable (EffectContext *pContext);
+void LvmEffect_free (EffectContext *pContext);
+int Effect_configure (EffectContext *pContext, effect_config_t *pConfig);
+int BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int BassBoost_getParameter (EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int Virtualizer_getParameter (EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int Equalizer_getParameter (EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue);
+int Volume_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue);
+int Volume_getParameter (EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue);
+
+/* Effect Library Interface Implementation */
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects){
+ LOGV("\n\tEffectQueryNumberEffects start");
+ *pNumEffects = 4;
+ LOGV("\tEffectQueryNumberEffects creating %d effects", *pNumEffects);
+ LOGV("\tEffectQueryNumberEffects end\n");
+ return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor){
+ LOGV("\n\tEffectQueryEffect start");
+ LOGV("\tEffectQueryEffect processing index %d", index);
+
+ if (pDescriptor == NULL){
+ LOGV("\tLVM_ERROR : EffectQueryEffect was passed NULL pointer");
+ return -EINVAL;
+ }
+ if (index > 3){
+ LOGV("\tLVM_ERROR : EffectQueryEffect index out of range %d", index);
+ return -ENOENT;
+ }
+ if(index == LVM_BASS_BOOST){
+ LOGV("\tEffectQueryEffect processing LVM_BASS_BOOST");
+ memcpy(pDescriptor, &gBassBoostDescriptor, sizeof(effect_descriptor_t));
+ }else if(index == LVM_VIRTUALIZER){
+ LOGV("\tEffectQueryEffect processing LVM_VIRTUALIZER");
+ memcpy(pDescriptor, &gVirtualizerDescriptor, sizeof(effect_descriptor_t));
+ } else if(index == LVM_EQUALIZER){
+ LOGV("\tEffectQueryEffect processing LVM_EQUALIZER");
+ memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
+ } else if(index == LVM_VOLUME){
+ LOGV("\tEffectQueryEffect processing LVM_VOLUME");
+ memcpy(pDescriptor, &gVolumeDescriptor, sizeof(effect_descriptor_t));
+ }
+ LOGV("\tEffectQueryEffect end\n");
+ return 0;
+} /* end EffectQueryEffect */
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface){
+ int ret;
+ int i;
+ EffectContext *pContext = new EffectContext;
+
+ LOGV("\n\tEffectCreate start session %d", sessionId);
+
+ if (pInterface == NULL || uuid == NULL){
+ LOGV("\tLVM_ERROR : EffectCreate() called with NULL pointer");
+ return -EINVAL;
+ }
+
+ if((sessionId < 0)||(sessionId >= LVM_MAX_SESSIONS)){
+ LOGV("\tLVM_ERROR : EffectCreate sessionId is less than 0");
+ return -EINVAL;
+ }
+
+ if(LvmInitFlag == LVM_FALSE){
+ LvmInitFlag = LVM_TRUE;
+ LOGV("\tEffectCreate - Initializing all global memory");
+ LvmGlobalBundle_init();
+ }
+
+ // If this is the first create in this session
+ if(GlobalSessionMemory[sessionId].bBundledEffectsEnabled == LVM_FALSE){
+ LOGV("\tEffectCreate - This is the first effect in current session %d", sessionId);
+ LOGV("\tEffectCreate - Setting up Bundled Effects Instance for session %d", sessionId);
+
+ GlobalSessionMemory[sessionId].bBundledEffectsEnabled = LVM_TRUE;
+ GlobalSessionMemory[sessionId].pBundledContext = new BundledEffectContext;
+
+ pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext;
+ pContext->pBundledContext->SessionNo = sessionId;
+ pContext->pBundledContext->hInstance = NULL;
+ pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
+ pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
+ pContext->pBundledContext->bBassEnabled = LVM_FALSE;
+ pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
+ pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
+ pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
+ pContext->pBundledContext->NumberEffectsEnabled = 0;
+ pContext->pBundledContext->NumberEffectsCalled = 0;
+ pContext->pBundledContext->frameCount = 0;
+
+ #ifdef LVM_PCM
+ pContext->pBundledContext->PcmInPtr = NULL;
+ pContext->pBundledContext->PcmOutPtr = NULL;
+
+ pContext->pBundledContext->PcmInPtr = fopen("/data/tmp/bundle_pcm_in.pcm", "w");
+ pContext->pBundledContext->PcmOutPtr = fopen("/data/tmp/bundle_pcm_out.pcm", "w");
+
+ if((pContext->pBundledContext->PcmInPtr == NULL)||
+ (pContext->pBundledContext->PcmOutPtr == NULL)){
+ return -EINVAL;
+ }
+ #endif
+
+ /* Saved strength is used to return the exact strength that was used in the set to the get
+ * because we map the original strength range of 0:1000 to 1:15, and this will avoid
+ * quantisation like effect when returning
+ */
+ pContext->pBundledContext->BassStrengthSaved = 0;
+ pContext->pBundledContext->VirtStrengthSaved = 0;
+ pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
+ pContext->pBundledContext->levelSaved = 0;
+ pContext->pBundledContext->bMuteEnabled = LVM_FALSE;
+ pContext->pBundledContext->bStereoPositionEnabled = LVM_FALSE;
+ pContext->pBundledContext->positionSaved = 0;
+
+ LOGV("\tEffectCreate - Calling LvmBundle_init");
+ ret = LvmBundle_init(pContext);
+
+ if (ret < 0){
+ LOGV("\tLVM_ERROR : EffectCreate() Bundle init failed");
+ delete pContext->pBundledContext;
+ delete pContext;
+ return ret;
+ }
+ }
+ else{
+ pContext->pBundledContext = GlobalSessionMemory[sessionId].pBundledContext;
+ }
+
+ LOGV("\tEffectCreate - pBundledContext is %p", pContext->pBundledContext);
+
+ // Create each Effect
+ if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Bass Boost
+ LOGV("\tEffectCreate - Effect to be created is LVM_BASS_BOOST");
+ GlobalSessionMemory[sessionId].bBassInstantiated = LVM_TRUE;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_BASS_BOOST;
+ } else if (memcmp(uuid, &gVirtualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Virtualizer
+ LOGV("\tEffectCreate - Effect to be created is LVM_VIRTUALIZER");
+ GlobalSessionMemory[sessionId].bVirtualizerInstantiated = LVM_TRUE;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_VIRTUALIZER;
+ } else if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Equalizer
+ LOGV("\tEffectCreate - Effect to be created is LVM_EQUALIZER");
+ GlobalSessionMemory[sessionId].bEqualizerInstantiated = LVM_TRUE;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_EQUALIZER;
+ } else if (memcmp(uuid, &gVolumeDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
+ // Create Volume
+ LOGV("\tEffectCreate - Effect to be created is LVM_VOLUME");
+ GlobalSessionMemory[sessionId].bVolumeInstantiated = LVM_TRUE;
+
+ pContext->itfe = &gLvmEffectInterface;
+ pContext->EffectType = LVM_VOLUME;
+ }
+ else{
+ LOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
+ return -EINVAL;
+ }
+
+ *pInterface = (effect_interface_t)pContext;
+ LOGV("\tEffectCreate end..\n\n");
+ return 0;
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_interface_t interface){
+ LOGV("\n\tEffectRelease start %p", interface);
+ EffectContext * pContext = (EffectContext *)interface;
+
+ if (pContext == NULL){
+ LOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
+ return -EINVAL;
+ }
+
+ // Clear the instantiated flag for the effect
+ if(pContext->EffectType == LVM_BASS_BOOST) {
+ LOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated = LVM_FALSE;
+ } else if(pContext->EffectType == LVM_VIRTUALIZER) {
+ LOGV("\tEffectRelease LVM_VIRTUALIZER Clearing global intstantiated flag");
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated
+ = LVM_FALSE;
+ } else if(pContext->EffectType == LVM_EQUALIZER) {
+ LOGV("\tEffectRelease LVM_EQUALIZER Clearing global intstantiated flag");
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated =LVM_FALSE;
+ } else if(pContext->EffectType == LVM_VOLUME) {
+ LOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated = LVM_FALSE;
+ } else {
+ LOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
+ }
+
+ // if all effects are no longer instantiaed free the lvm memory and delete BundledEffectContext
+ if((GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBassInstantiated == LVM_FALSE)&&
+ (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVolumeInstantiated == LVM_FALSE)&&
+ (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bEqualizerInstantiated ==LVM_FALSE)&&
+ (GlobalSessionMemory[pContext->pBundledContext->SessionNo].bVirtualizerInstantiated==LVM_FALSE))
+ {
+ #ifdef LVM_PCM
+ fclose(pContext->pBundledContext->PcmInPtr);
+ fclose(pContext->pBundledContext->PcmOutPtr);
+ #endif
+ LOGV("\tEffectRelease: All effects are no longer instantiated\n");
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].bBundledEffectsEnabled =LVM_FALSE;
+ GlobalSessionMemory[pContext->pBundledContext->SessionNo].pBundledContext = LVM_NULL;
+ LOGV("\tEffectRelease: Freeing LVM Bundle memory\n");
+ LvmEffect_free(pContext);
+ LOGV("\tEffectRelease: Deleting LVM Bundle context\n");
+ delete pContext->pBundledContext;
+ }
+ // free the effect context for current effect
+ delete pContext;
+
+ LOGV("\tEffectRelease end\n");
+ return 0;
+
+} /* end EffectRelease */
+
+void LvmGlobalBundle_init(){
+ LOGV("\tLvmGlobalBundle_init start");
+ for(int i=0; i<LVM_MAX_SESSIONS; i++){
+ GlobalSessionMemory[i].bBundledEffectsEnabled = LVM_FALSE;
+ GlobalSessionMemory[i].bVolumeInstantiated = LVM_FALSE;
+ GlobalSessionMemory[i].bEqualizerInstantiated = LVM_FALSE;
+ GlobalSessionMemory[i].bBassInstantiated = LVM_FALSE;
+ GlobalSessionMemory[i].bVirtualizerInstantiated = LVM_FALSE;
+ GlobalSessionMemory[i].pBundledContext = LVM_NULL;
+ }
+ return;
+}
+//----------------------------------------------------------------------------
+// LvmBundle_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration, creates instance
+// with all effects disabled.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int LvmBundle_init(EffectContext *pContext){
+ int status;
+
+ LOGV("\tLvmBundle_init start");
+
+ pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pContext->config.inputCfg.channels = CHANNEL_STEREO;
+ pContext->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->config.inputCfg.samplingRate = 44100;
+ pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
+ pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->config.inputCfg.bufferProvider.cookie = NULL;
+ pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+ pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pContext->config.outputCfg.channels = CHANNEL_STEREO;
+ pContext->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->config.outputCfg.samplingRate = 44100;
+ pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
+ pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->config.outputCfg.bufferProvider.cookie = NULL;
+ pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ CHECK_ARG(pContext != NULL);
+
+ if (pContext->pBundledContext->hInstance != NULL){
+ LOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
+ "-> Calling pContext->pBassBoost->free()");
+
+ LvmEffect_free(pContext);
+
+ LOGV("\tLvmBundle_init pContext->pBassBoost != NULL "
+ "-> Called pContext->pBassBoost->free()");
+ }
+
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+ LVM_ControlParams_t params; /* Control Parameters */
+ LVM_InstParams_t InstParams; /* Instance parameters */
+ LVM_EQNB_BandDef_t BandDefs[MAX_NUM_BANDS]; /* Equaliser band definitions */
+ LVM_HeadroomParams_t HeadroomParams; /* Headroom parameters */
+ LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS];
+ LVM_MemTab_t MemTab; /* Memory allocation table */
+ bool bMallocFailure = LVM_FALSE;
+
+ /* Set the capabilities */
+ InstParams.BufferMode = LVM_UNMANAGED_BUFFERS;
+ InstParams.MaxBlockSize = MAX_CALL_SIZE;
+ InstParams.EQNB_NumBands = MAX_NUM_BANDS;
+ InstParams.PSA_Included = LVM_PSA_ON;
+
+ /* Allocate memory, forcing alignment */
+ LvmStatus = LVM_GetMemoryTable(LVM_NULL,
+ &MemTab,
+ &InstParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "LvmBundle_init")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ LOGV("\tCreateInstance Succesfully called LVM_GetMemoryTable\n");
+
+ /* Allocate memory */
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].Size != 0){
+ MemTab.Region[i].pBaseAddress = malloc(MemTab.Region[i].Size);
+
+ if (MemTab.Region[i].pBaseAddress == LVM_NULL){
+ LOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %ld bytes for region %u\n",
+ MemTab.Region[i].Size, i );
+ bMallocFailure = LVM_TRUE;
+ }else{
+ LOGV("\tLvmBundle_init CreateInstance allocated %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }
+ }
+ }
+
+ /* If one or more of the memory regions failed to allocate, free the regions that were
+ * succesfully allocated and return with an error
+ */
+ if(bMallocFailure == LVM_TRUE){
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].pBaseAddress == LVM_NULL){
+ LOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed to allocate %ld bytes for region %u - +"
+ "Not freeing\n", MemTab.Region[i].Size, i );
+ }else{
+ LOGV("\tLVM_ERROR :LvmBundle_init CreateInstance Failed: but allocated %ld bytes "
+ "for region %u at %p- free\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ free(MemTab.Region[i].pBaseAddress);
+ }
+ }
+ return -EINVAL;
+ }
+ LOGV("\tLvmBundle_init CreateInstance Succesfully malloc'd memory\n");
+
+ /* Initialise */
+ pContext->pBundledContext->hInstance = LVM_NULL;
+
+ /* Init sets the instance handle */
+ LvmStatus = LVM_GetInstanceHandle(&pContext->pBundledContext->hInstance,
+ &MemTab,
+ &InstParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetInstanceHandle", "LvmBundle_init")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ LOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_GetInstanceHandle\n");
+
+ /* Set the initial process parameters */
+ /* General parameters */
+ params.OperatingMode = LVM_MODE_ON;
+ params.SampleRate = LVM_FS_44100;
+ params.SourceFormat = LVM_STEREO;
+ params.SpeakerType = LVM_HEADPHONES;
+
+ pContext->pBundledContext->SampleRate = LVM_FS_44100;
+
+ /* Concert Sound parameters */
+ params.VirtualizerOperatingMode = LVM_MODE_OFF;
+ params.VirtualizerType = LVM_CONCERTSOUND;
+ params.VirtualizerReverbLevel = 100;
+ params.CS_EffectLevel = LVM_CS_EFFECT_HIGH;
+
+ /* N-Band Equaliser parameters */
+ params.EQNB_OperatingMode = LVM_EQNB_OFF;
+ params.EQNB_NBands = FIVEBAND_NUMBANDS;
+ params.pEQNB_BandDefinition = &BandDefs[0];
+
+ for (int i=0; i<FIVEBAND_NUMBANDS; i++)
+ {
+ BandDefs[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+ BandDefs[i].QFactor = EQNB_5BandPresetsQFactors[i];
+ BandDefs[i].Gain = EQNB_5BandSoftPresets[i];
+ }
+
+ /* Volume Control parameters */
+ params.VC_EffectLevel = 0;
+ params.VC_Balance = 0;
+
+ /* Treble Enhancement parameters */
+ params.TE_OperatingMode = LVM_TE_OFF;
+ params.TE_EffectLevel = 0;
+
+ /* PSA Control parameters */
+ params.PSA_Enable = LVM_PSA_OFF;
+ params.PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
+
+ /* Bass Enhancement parameters */
+ params.BE_OperatingMode = LVM_BE_OFF;
+ params.BE_EffectLevel = 0;
+ params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+ params.BE_HPF = LVM_BE_HPF_ON;
+
+ /* PSA Control parameters */
+ params.PSA_Enable = LVM_PSA_OFF;
+ params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance,
+ &params);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmBundle_init")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ LOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_SetControlParameters\n");
+
+ /* Set the headroom parameters */
+ HeadroomBandDef[0].Limit_Low = 20;
+ HeadroomBandDef[0].Limit_High = 4999;
+ HeadroomBandDef[0].Headroom_Offset = 3;
+ HeadroomBandDef[1].Limit_Low = 5000;
+ HeadroomBandDef[1].Limit_High = 24000;
+ HeadroomBandDef[1].Headroom_Offset = 4;
+ HeadroomParams.pHeadroomDefinition = &HeadroomBandDef[0];
+ HeadroomParams.Headroom_OperatingMode = LVM_HEADROOM_ON;
+ HeadroomParams.NHeadroomBands = 2;
+
+ LvmStatus = LVM_SetHeadroomParams(pContext->pBundledContext->hInstance,
+ &HeadroomParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetHeadroomParams", "LvmBundle_init")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ LOGV("\tLvmBundle_init CreateInstance Succesfully called LVM_SetHeadroomParams\n");
+ LOGV("\tLvmBundle_init End");
+ return 0;
+} /* end LvmBundle_init */
+
+//----------------------------------------------------------------------------
+// LvmBundle_process()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply LVM Bundle effects
+//
+// Inputs:
+// pIn: pointer to stereo 16 bit input data
+// pOut: pointer to stereo 16 bit output data
+// frameCount: Frames to process
+// pContext: effect engine context
+// strength strength to be applied
+//
+// Outputs:
+// pOut: pointer to updated stereo 16 bit output data
+//
+//----------------------------------------------------------------------------
+
+int LvmBundle_process(LVM_INT16 *pIn,
+ LVM_INT16 *pOut,
+ int frameCount,
+ EffectContext *pContext){
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+
+ LVM_INT16 *pOutTmp;
+ if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
+ pOutTmp = pOut;
+ }else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+ pOutTmp = (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+ if(pOutTmp == NULL){
+ LOGV("\tLVM_ERROR : LvmBundle_process failed to allocate memory for "
+ "EFFECT_BUFFER_ACCESS_ACCUMULATE mode");
+ return -EINVAL;
+ }
+ }else{
+ LOGV("LVM_ERROR : LvmBundle_process invalid access mode");
+ return -EINVAL;
+ }
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmBundle_process")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ pContext->pBundledContext->frameCount++;
+ if(pContext->pBundledContext->frameCount == 100)
+ {
+ //LOGV("\tBB: %d VIRT: %d EQ: %d, session (%d), context is %p\n",
+ //ActiveParams.BE_OperatingMode,
+ //ActiveParams.VirtualizerOperatingMode, ActiveParams.EQNB_OperatingMode,
+ //pContext->pBundledContext->SessionNo, pContext->pBundledContext);
+ pContext->pBundledContext->frameCount = 0;
+ }
+
+ #ifdef LVM_PCM
+ fwrite(pIn, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmInPtr);
+ fflush(pContext->pBundledContext->PcmInPtr);
+ #endif
+
+ /* Process the samples */
+ LvmStatus = LVM_Process(pContext->pBundledContext->hInstance, /* Instance handle */
+ pIn, /* Input buffer */
+ pOutTmp, /* Output buffer */
+ (LVM_UINT16)frameCount, /* Number of samples to read */
+ 0); /* Audo Time */
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_Process", "LvmBundle_process")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ #ifdef LVM_PCM
+ fwrite(pOutTmp, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmOutPtr);
+ fflush(pContext->pBundledContext->PcmOutPtr);
+ #endif
+
+ if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+ for (int i=0; i<frameCount*2; i++){
+ pOut[i] += pOutTmp[i];
+ }
+ free(pOutTmp);
+ }
+ return 0;
+} /* end LvmBundle_process */
+
+//----------------------------------------------------------------------------
+// LvmEffect_enable()
+//----------------------------------------------------------------------------
+// Purpose: Enable the effect in the bundle
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int LvmEffect_enable(EffectContext *pContext){
+ //LOGV("\tLvmEffect_enable start");
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_enable")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ //LOGV("\tLvmEffect_enable Succesfully called LVM_GetControlParameters\n");
+
+ if(pContext->EffectType == LVM_BASS_BOOST) {
+ LOGV("\tLvmEffect_enable : Enabling LVM_BASS_BOOST");
+ ActiveParams.BE_OperatingMode = LVM_BE_ON;
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER) {
+ LOGV("\tLvmEffect_enable : Enabling LVM_VIRTUALIZER");
+ ActiveParams.VirtualizerOperatingMode = LVM_MODE_ON;
+ }
+ if(pContext->EffectType == LVM_EQUALIZER) {
+ LOGV("\tLvmEffect_enable : Enabling LVM_EQUALIZER");
+ ActiveParams.EQNB_OperatingMode = LVM_EQNB_ON;
+ }
+ if(pContext->EffectType == LVM_VOLUME) {
+ LOGV("\tLvmEffect_enable : Enabling LVM_VOLUME");
+ }
+
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_enable")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tLvmEffect_enable Succesfully called LVM_SetControlParameters\n");
+ //LOGV("\tLvmEffect_enable end");
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// LvmEffect_disable()
+//----------------------------------------------------------------------------
+// Purpose: Disable the effect in the bundle
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int LvmEffect_disable(EffectContext *pContext){
+ //LOGV("\tLvmEffect_disable start");
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmEffect_disable")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ //LOGV("\tLvmEffect_disable Succesfully called LVM_GetControlParameters\n");
+
+ if(pContext->EffectType == LVM_BASS_BOOST) {
+ LOGV("\tLvmEffect_disable : Disabling LVM_BASS_BOOST");
+ ActiveParams.BE_OperatingMode = LVM_BE_OFF;
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER) {
+ LOGV("\tLvmEffect_disable : Enabling LVM_VIRTUALIZER");
+ ActiveParams.VirtualizerOperatingMode = LVM_MODE_OFF;
+ }
+ if(pContext->EffectType == LVM_EQUALIZER) {
+ LOGV("\tLvmEffect_disable : Enabling LVM_EQUALIZER");
+ ActiveParams.EQNB_OperatingMode = LVM_EQNB_OFF;
+ }
+ if(pContext->EffectType == LVM_VOLUME) {
+ LOGV("\tLvmEffect_disable : Enabling LVM_VOLUME");
+ }
+
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "LvmEffect_disable")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tLvmEffect_disable Succesfully called LVM_SetControlParameters\n");
+ //LOGV("\tLvmEffect_disable end");
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// LvmEffect_free()
+//----------------------------------------------------------------------------
+// Purpose: Free all memory associated with the Bundle.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+void LvmEffect_free(EffectContext *pContext){
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+ LVM_ControlParams_t params; /* Control Parameters */
+ LVM_MemTab_t MemTab;
+
+ /* Free the algorithm memory */
+ LvmStatus = LVM_GetMemoryTable(pContext->pBundledContext->hInstance,
+ &MemTab,
+ LVM_NULL);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetMemoryTable", "LvmEffect_free")
+
+ for (int i=0; i<LVM_NR_MEMORY_REGIONS; i++){
+ if (MemTab.Region[i].Size != 0){
+ if (MemTab.Region[i].pBaseAddress != NULL){
+ LOGV("\tLvmEffect_free - START freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+
+ free(MemTab.Region[i].pBaseAddress);
+
+ LOGV("\tLvmEffect_free - END freeing %ld bytes for region %u at %p\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }else{
+ LOGV("\tLVM_ERROR : LvmEffect_free - trying to free with NULL pointer %ld bytes "
+ "for region %u at %p ERROR\n",
+ MemTab.Region[i].Size, i, MemTab.Region[i].pBaseAddress);
+ }
+ }
+ }
+} /* end LvmEffect_free */
+
+//----------------------------------------------------------------------------
+// Effect_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Effect_configure(EffectContext *pContext, effect_config_t *pConfig){
+ LVM_Fs_en SampleRate;
+ //LOGV("\tEffect_configure start");
+
+ CHECK_ARG(pContext != NULL);
+ CHECK_ARG(pConfig != NULL);
+
+ CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+ CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
+ CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+ CHECK_ARG(pConfig->inputCfg.channels == CHANNEL_STEREO);
+ CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ CHECK_ARG(pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S15);
+
+ memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
+ switch (pConfig->inputCfg.samplingRate) {
+ case 8000:
+ SampleRate = LVM_FS_8000;
+ break;
+ case 16000:
+ SampleRate = LVM_FS_16000;
+ break;
+ case 22050:
+ SampleRate = LVM_FS_22050;
+ break;
+ case 32000:
+ SampleRate = LVM_FS_32000;
+ break;
+ case 44100:
+ SampleRate = LVM_FS_44100;
+ break;
+ case 48000:
+ SampleRate = LVM_FS_48000;
+ break;
+ default:
+ LOGV("\tEffect_Configure invalid sampling rate %d", pConfig->inputCfg.samplingRate);
+ return -EINVAL;
+ }
+
+ if(pContext->pBundledContext->SampleRate != SampleRate){
+
+ LVM_ControlParams_t ActiveParams;
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS;
+
+ LOGV("\tEffect_configure change sampling rate to %d", SampleRate);
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "Effect_configure")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "Effect_configure")
+ LOGV("\tEffect_configure Succesfully called LVM_SetControlParameters\n");
+
+ }else{
+ //LOGV("\tEffect_configure keep sampling rate at %d", SampleRate);
+ }
+
+ //LOGV("\tEffect_configure End....");
+ return 0;
+} /* end Effect_configure */
+
+//----------------------------------------------------------------------------
+// BassGetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// get the effect strength currently being used, what is actually returned is the strengh that was
+// previously used in the set, this is because the app uses a strength in the range 0-1000 while
+// the bassboost uses 1-15, so to avoid a quantisation the original set value is used. However the
+// actual used value is checked to make sure it corresponds to the one being returned
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+uint32_t BassGetStrength(EffectContext *pContext){
+ //LOGV("\tBassGetStrength() (0-1000) -> %d\n", pContext->pBundledContext->BassStrengthSaved);
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "BassGetStrength")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tBassGetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+ /* Check that the strength returned matches the strength that was set earlier */
+ if(ActiveParams.BE_EffectLevel !=
+ (LVM_INT16)((15*pContext->pBundledContext->BassStrengthSaved)/1000)){
+ LOGV("\tLVM_ERROR : BassGetStrength module strength does not match savedStrength %d %d\n",
+ ActiveParams.BE_EffectLevel, pContext->pBundledContext->BassStrengthSaved);
+ return -EINVAL;
+ }
+
+ //LOGV("\tBassGetStrength() (0-15) -> %d\n", ActiveParams.BE_EffectLevel );
+ //LOGV("\tBassGetStrength() (saved) -> %d\n", pContext->pBundledContext->BassStrengthSaved );
+ return pContext->pBundledContext->BassStrengthSaved;
+} /* end BassGetStrength */
+
+//----------------------------------------------------------------------------
+// BassSetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the strength to the BassBosst. Must first be converted from the range 0-1000 to 1-15
+//
+// Inputs:
+// pContext: effect engine context
+// strength strength to be applied
+//
+//----------------------------------------------------------------------------
+
+void BassSetStrength(EffectContext *pContext, uint32_t strength){
+ //LOGV("\tBassSetStrength(%d)", strength);
+
+ pContext->pBundledContext->BassStrengthSaved = (int)strength;
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "BassSetStrength")
+ //LOGV("\tBassSetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+ /* Bass Enhancement parameters */
+ ActiveParams.BE_EffectLevel = (LVM_INT16)((15*strength)/1000);
+ ActiveParams.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+
+ //LOGV("\tBassSetStrength() (0-15) -> %d\n", ActiveParams.BE_EffectLevel );
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "BassSetStrength")
+ //LOGV("\tBassSetStrength Succesfully called LVM_SetControlParameters\n");
+} /* end BassSetStrength */
+
+//----------------------------------------------------------------------------
+// VirtualizerGetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// get the effect strength currently being used, what is actually returned is the strengh that was
+// previously used in the set, this is because the app uses a strength in the range 0-1000 while
+// the Virtualizer uses 1-100, so to avoid a quantisation the original set value is used.However the
+// actual used value is checked to make sure it corresponds to the one being returned
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+uint32_t VirtualizerGetStrength(EffectContext *pContext){
+ //LOGV("\tVirtualizerGetStrength (0-1000) -> %d\n",pContext->pBundledContext->VirtStrengthSaved);
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VirtualizerGetStrength")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVirtualizerGetStrength Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tVirtualizerGetStrength() (0-100) -> %d\n", ActiveParams.VirtualizerReverbLevel*10);
+ return ActiveParams.VirtualizerReverbLevel*10;
+} /* end getStrength */
+
+//----------------------------------------------------------------------------
+// VirtualizerSetStrength()
+//----------------------------------------------------------------------------
+// Purpose:
+// Apply the strength to the Virtualizer. Must first be converted from the range 0-1000 to 1-15
+//
+// Inputs:
+// pContext: effect engine context
+// strength strength to be applied
+//
+//----------------------------------------------------------------------------
+
+void VirtualizerSetStrength(EffectContext *pContext, uint32_t strength){
+ //LOGV("\tVirtualizerSetStrength(%d)", strength);
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ pContext->pBundledContext->VirtStrengthSaved = (int)strength;
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VirtualizerSetStrength")
+ //LOGV("\tVirtualizerSetStrength Succesfully returned from LVM_GetControlParameters\n");
+
+ /* Virtualizer parameters */
+ ActiveParams.VirtualizerReverbLevel = (LVM_INT16)(strength/10);
+
+ //LOGV("\tVirtualizerSetStrength() (0-1000) -> %d\n", strength );
+ //LOGV("\tVirtualizerSetStrength() (0- 100) -> %d\n", ActiveParams.VirtualizerReverbLevel );
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VirtualizerSetStrength")
+ //LOGV("\tVirtualizerSetStrength Succesfully called LVM_SetControlParameters\n");
+} /* end setStrength */
+
+//----------------------------------------------------------------------------
+// EqualizerGetBandLevel()
+//----------------------------------------------------------------------------
+// Purpose: Retrieve the gain currently being used for the band passed in
+//
+// Inputs:
+// band: band number
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+int32_t EqualizerGetBandLevel(EffectContext *pContext, int32_t band){
+
+ int32_t Gain =0;
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ LVM_EQNB_BandDef_t *BandDef;
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerGetBandLevel")
+
+ BandDef = ActiveParams.pEQNB_BandDefinition;
+ Gain = (int32_t)BandDef[band].Gain*100; // Convert to millibels
+
+ //LOGV("\tEqualizerGetBandLevel -> %d\n", Gain );
+ //LOGV("\tEqualizerGetBandLevel Succesfully returned from LVM_GetControlParameters\n");
+ return Gain;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerSetBandLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+// Sets gain value for the given band.
+//
+// Inputs:
+// band: band number
+// Gain: Gain to be applied in millibels
+// pContext: effect engine context
+//
+// Outputs:
+//
+//---------------------------------------------------------------------------
+void EqualizerSetBandLevel(EffectContext *pContext, int band, int Gain){
+ int gainRounded;
+ if(Gain > 0){
+ gainRounded = (int)((Gain+50)/100);
+ }else{
+ gainRounded = (int)((Gain-50)/100);
+ }
+ //LOGV("\tEqualizerSetBandLevel(%d)->(%d)", Gain, gainRounded);
+
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+ LVM_EQNB_BandDef_t *BandDef;
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerSetBandLevel")
+ //LOGV("\tEqualizerSetBandLevel Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tEqualizerSetBandLevel just Got -> %d\n", ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+ /* Set local EQ parameters */
+ BandDef = ActiveParams.pEQNB_BandDefinition;
+ ActiveParams.pEQNB_BandDefinition[band].Gain = gainRounded;
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerSetBandLevel")
+ //LOGV("\tEqualizerSetBandLevel just Set -> %d\n", ActiveParams.pEQNB_BandDefinition[band].Gain);
+
+ pContext->pBundledContext->CurPreset = PRESET_CUSTOM;
+ return;
+}
+//----------------------------------------------------------------------------
+// EqualizerGetCentreFrequency()
+//----------------------------------------------------------------------------
+// Purpose: Retrieve the frequency being used for the band passed in
+//
+// Inputs:
+// band: band number
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+int32_t EqualizerGetCentreFrequency(EffectContext *pContext, int32_t band){
+ int32_t Frequency =0;
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ LVM_EQNB_BandDef_t *BandDef;
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
+ &ActiveParams);
+
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerGetCentreFrequency")
+
+ BandDef = ActiveParams.pEQNB_BandDefinition;
+ Frequency = (int32_t)BandDef[band].Frequency*1000; // Convert to millibels
+
+ //LOGV("\tEqualizerGetCentreFrequency -> %d\n", Frequency );
+ //LOGV("\tEqualizerGetCentreFrequency Succesfully returned from LVM_GetControlParameters\n");
+ return Frequency;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetBandFreqRange(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Gets lower and upper boundaries of a band.
+// For the high shelf, the low bound is the band frequency and the high
+// bound is Nyquist.
+// For the peaking filters, they are the gain[dB]/2 points.
+//
+// Inputs:
+// band: band number
+// pContext: effect engine context
+//
+// Outputs:
+// pLow: lower band range
+// pLow: upper band range
+//----------------------------------------------------------------------------
+int32_t EqualizerGetBandFreqRange(EffectContext *pContext, int32_t band, uint32_t *pLow,
+ uint32_t *pHi){
+ *pLow = bandFreqRange[band][0];
+ *pHi = bandFreqRange[band][1];
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetBand(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Returns the band with the maximum influence on a given frequency.
+// Result is unaffected by whether EQ is enabled or not, or by whether
+// changes have been committed or not.
+//
+// Inputs:
+// targetFreq The target frequency, in millihertz.
+// pContext: effect engine context
+//
+// Outputs:
+// pLow: lower band range
+// pLow: upper band range
+//----------------------------------------------------------------------------
+int32_t EqualizerGetBand(EffectContext *pContext, uint32_t targetFreq){
+ int band = 0;
+
+ if(targetFreq < bandFreqRange[0][0]){
+ return -EINVAL;
+ }else if(targetFreq == bandFreqRange[0][0]){
+ return 0;
+ }
+ for(int i=0; i<FIVEBAND_NUMBANDS;i++){
+ if((targetFreq > bandFreqRange[i][0])&&(targetFreq <= bandFreqRange[i][1])){
+ band = i;
+ }
+ }
+ return band;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetPreset(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Gets the currently set preset ID.
+// Will return PRESET_CUSTOM in case the EQ parameters have been modified
+// manually since a preset was set.
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+int32_t EqualizerGetPreset(EffectContext *pContext){
+ return pContext->pBundledContext->CurPreset;
+}
+
+//----------------------------------------------------------------------------
+// EqualizerSetPreset(
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Sets the current preset by ID.
+// All the band parameters will be overridden.
+//
+// Inputs:
+// pContext: effect engine context
+// preset The preset ID.
+//
+//----------------------------------------------------------------------------
+void EqualizerSetPreset(EffectContext *pContext, int preset){
+
+ //LOGV("\tEqualizerSetPreset(%d)", preset);
+ pContext->pBundledContext->CurPreset = preset;
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "EqualizerSetPreset")
+ //LOGV("\tEqualizerSetPreset Succesfully returned from LVM_GetControlParameters\n");
+
+ //ActiveParams.pEQNB_BandDefinition = &BandDefs[0];
+ for (int i=0; i<FIVEBAND_NUMBANDS; i++)
+ {
+ ActiveParams.pEQNB_BandDefinition[i].Frequency = EQNB_5BandPresetsFrequencies[i];
+ ActiveParams.pEQNB_BandDefinition[i].QFactor = EQNB_5BandPresetsQFactors[i];
+ ActiveParams.pEQNB_BandDefinition[i].Gain
+ = EQNB_5BandSoftPresets[i + preset * FIVEBAND_NUMBANDS];
+ }
+ /* Activate the new settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "EqualizerSetPreset")
+
+ //LOGV("\tEqualizerSetPreset Succesfully called LVM_SetControlParameters\n");
+ return;
+}
+
+int32_t EqualizerGetNumPresets(){
+ return sizeof(gEqualizerPresets) / sizeof(PresetConfig);
+}
+
+//----------------------------------------------------------------------------
+// EqualizerGetPresetName(
+//----------------------------------------------------------------------------
+// Purpose:
+// Gets a human-readable name for a preset ID. Will return "Custom" if
+// PRESET_CUSTOM is passed.
+//
+// Inputs:
+// preset The preset ID. Must be less than number of presets.
+//
+//-------------------------------------------------------------------------
+const char * EqualizerGetPresetName(int32_t preset){
+ //LOGV("\tEqualizerGetPresetName start(%d)", preset);
+ if (preset == PRESET_CUSTOM) {
+ return "Custom";
+ } else {
+ return gEqualizerPresets[preset].name;
+ }
+ //LOGV("\tEqualizerGetPresetName end(%d)", preset);
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+// VolumeSetVolumeLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+// level level to be applied
+//
+//----------------------------------------------------------------------------
+
+int VolumeSetVolumeLevel(EffectContext *pContext, int16_t level){
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ //LOGV("\tVolumeSetVolumeLevel Level to be set is %d %d\n", level, (LVM_INT16)(level/100));
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetVolumeLevel")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ //LOGV("\tVolumeSetVolumeLevel Succesfully returned from LVM_GetControlParameters got: %d\n",
+ //ActiveParams.VC_EffectLevel);
+
+ /* Volume parameters */
+ ActiveParams.VC_EffectLevel = (LVM_INT16)(level/100);
+ //LOGV("\tVolumeSetVolumeLevel() (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetVolumeLevel")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeSetVolumeLevel Succesfully called LVM_SetControlParameters\n");
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetVolumeLevel")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeSetVolumeLevel just set (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
+ return 0;
+} /* end setVolumeLevel */
+
+//----------------------------------------------------------------------------
+// VolumeGetVolumeLevel()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+//
+//----------------------------------------------------------------------------
+
+int VolumeGetVolumeLevel(EffectContext *pContext, int16_t *level){
+
+ //LOGV("\tVolumeGetVolumeLevel start");
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetVolumeLevel")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeGetVolumeLevel() (-96dB -> 0dB) -> %d\n", ActiveParams.VC_EffectLevel );
+ //LOGV("\tVolumeGetVolumeLevel Succesfully returned from LVM_GetControlParameters\n");
+
+ *level = ActiveParams.VC_EffectLevel*100; // Convert dB to millibels
+ //LOGV("\tVolumeGetVolumeLevel end");
+ return 0;
+} /* end VolumeGetVolumeLevel */
+
+//----------------------------------------------------------------------------
+// VolumeSetMute()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+// mute: enable/disable flag
+//
+//----------------------------------------------------------------------------
+
+int32_t VolumeSetMute(EffectContext *pContext, uint32_t mute){
+ //LOGV("\tVolumeSetMute start(%d)", mute);
+
+ pContext->pBundledContext->bMuteEnabled = mute;
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetMute")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeSetMute Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tVolumeSetMute to %d, level was %d\n", mute, ActiveParams.VC_EffectLevel );
+
+ /* Set appropriate volume level */
+ if(pContext->pBundledContext->bMuteEnabled == LVM_TRUE){
+ pContext->pBundledContext->levelSaved = ActiveParams.VC_EffectLevel;
+ ActiveParams.VC_EffectLevel = -96;
+ }else{
+ ActiveParams.VC_EffectLevel = pContext->pBundledContext->levelSaved;
+ }
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetMute")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeSetMute Succesfully called LVM_SetControlParameters\n");
+ //LOGV("\tVolumeSetMute end");
+ return 0;
+} /* end setMute */
+
+//----------------------------------------------------------------------------
+// VolumeGetMute()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Ourputs:
+// mute: enable/disable flag
+//----------------------------------------------------------------------------
+
+int32_t VolumeGetMute(EffectContext *pContext, uint32_t *mute){
+ //LOGV("\tVolumeGetMute start");
+ if((pContext->pBundledContext->bMuteEnabled == LVM_FALSE)||
+ (pContext->pBundledContext->bMuteEnabled == LVM_TRUE)){
+ *mute = pContext->pBundledContext->bMuteEnabled;
+ return 0;
+ }else{
+ LOGV("\tLVM_ERROR : VolumeGetMute read an invalid value from context %d",
+ pContext->pBundledContext->bMuteEnabled);
+ return -EINVAL;
+ }
+ //LOGV("\tVolumeGetMute end");
+} /* end getMute */
+
+int16_t VolumeConvertStereoPosition(int16_t position){
+ int16_t convertedPosition = 0;
+
+ convertedPosition = (int16_t)(((float)position/1000)*96);
+ return convertedPosition;
+
+}
+
+//----------------------------------------------------------------------------
+// VolumeSetStereoPosition()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+// position: stereo position
+//
+// Outputs:
+//----------------------------------------------------------------------------
+
+int VolumeSetStereoPosition(EffectContext *pContext, int16_t position){
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+ LVM_INT16 Balance = 0;
+
+
+
+ pContext->pBundledContext->positionSaved = position;
+ Balance = VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
+
+ //LOGV("\tVolumeSetStereoPosition start pContext->pBundledContext->positionSaved = %d", pContext->pBundledContext->positionSaved);
+
+ if(pContext->pBundledContext->bStereoPositionEnabled == LVM_TRUE){
+
+ //LOGV("\tVolumeSetStereoPosition Position to be set is %d %d\n", position, Balance);
+ pContext->pBundledContext->positionSaved = position;
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ //LOGV("\tVolumeSetStereoPosition Succesfully returned from LVM_GetControlParameters got:"
+ // " %d\n", ActiveParams.VC_Balance);
+
+ /* Volume parameters */
+ ActiveParams.VC_Balance = Balance;
+ //LOGV("\tVolumeSetStereoPosition() (-96dB -> +96dB) -> %d\n", ActiveParams.VC_Balance );
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeSetStereoPosition Succesfully called LVM_SetControlParameters\n");
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+ //LOGV("\tVolumeSetStereoPosition Succesfully returned from LVM_GetControlParameters got: "
+ // "%d\n", ActiveParams.VC_Balance);
+ }
+ else{
+ //LOGV("\tVolumeSetStereoPosition Position attempting to set, but not enabled %d %d\n",
+ //position, Balance);
+ }
+ //LOGV("\tVolumeSetStereoPosition end pContext->pBundledContext->positionSaved = %d\n", pContext->pBundledContext->positionSaved);
+ return 0;
+} /* end VolumeSetStereoPosition */
+
+
+//----------------------------------------------------------------------------
+// VolumeGetStereoPosition()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+// position: stereo position
+//----------------------------------------------------------------------------
+
+int32_t VolumeGetStereoPosition(EffectContext *pContext, int16_t *position){
+ //LOGV("\tVolumeGetStereoPosition start");
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
+ LVM_INT16 balance;
+
+ //LOGV("\tVolumeGetStereoPosition start pContext->pBundledContext->positionSaved = %d", pContext->pBundledContext->positionSaved);
+
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeGetStereoPosition -> %d\n", ActiveParams.VC_Balance);
+ //LOGV("\tVolumeGetStereoPosition Succesfully returned from LVM_GetControlParameters\n");
+
+ balance = VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
+
+ if(pContext->pBundledContext->bStereoPositionEnabled == LVM_TRUE){
+ if(balance != ActiveParams.VC_Balance){
+ return -EINVAL;
+ }
+ }
+ *position = (LVM_INT16)pContext->pBundledContext->positionSaved; // Convert dB to millibels
+ //LOGV("\tVolumeGetStereoPosition end returning pContext->pBundledContext->positionSaved = %d\n", pContext->pBundledContext->positionSaved);
+ return 0;
+} /* end VolumeGetStereoPosition */
+
+//----------------------------------------------------------------------------
+// VolumeEnableStereoPosition()
+//----------------------------------------------------------------------------
+// Purpose:
+//
+// Inputs:
+// pContext: effect engine context
+// mute: enable/disable flag
+//
+//----------------------------------------------------------------------------
+
+int32_t VolumeEnableStereoPosition(EffectContext *pContext, uint32_t enabled){
+ //LOGV("\tVolumeEnableStereoPosition start()");
+
+ pContext->pBundledContext->bStereoPositionEnabled = enabled;
+
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
+
+ /* Get the current settings */
+ LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeEnableStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeEnableStereoPosition Succesfully returned from LVM_GetControlParameters\n");
+ //LOGV("\tVolumeEnableStereoPosition to %d, position was %d\n",
+ // enabled, ActiveParams.VC_Balance );
+
+ /* Set appropriate stereo position */
+ if(pContext->pBundledContext->bStereoPositionEnabled == LVM_FALSE){
+ ActiveParams.VC_Balance = 0;
+ }else{
+ ActiveParams.VC_Balance =
+ VolumeConvertStereoPosition(pContext->pBundledContext->positionSaved);
+ }
+
+ /* Activate the initial settings */
+ LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeEnableStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ //LOGV("\tVolumeEnableStereoPosition Succesfully called LVM_SetControlParameters\n");
+ //LOGV("\tVolumeEnableStereoPosition end()\n");
+ return 0;
+} /* end VolumeEnableStereoPosition */
+
+//----------------------------------------------------------------------------
+// BassBoost_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a BassBoost parameter
+//
+// Inputs:
+// pBassBoost - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to variable to hold retrieved value
+// pValueSize - pointer to value size: maximum size as input
+//
+// Outputs:
+// *pValue updated with parameter value
+// *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int BassBoost_getParameter(EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int32_t param = *pParam++;
+ int32_t param2;
+ char *name;
+
+ //LOGV("\tBassBoost_getParameter start");
+
+ switch (param){
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+ case BASSBOOST_PARAM_STRENGTH:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid pValueSize2 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param){
+ case BASSBOOST_PARAM_STRENGTH_SUPPORTED:
+ *(uint32_t *)pValue = 1;
+
+ //LOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH_SUPPORTED Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+
+ case BASSBOOST_PARAM_STRENGTH:
+ *(int16_t *)pValue = BassGetStrength(pContext);
+
+ //LOGV("\tBassBoost_getParameter() BASSBOOST_PARAM_STRENGTH Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : BassBoost_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //LOGV("\tBassBoost_getParameter end");
+ return status;
+} /* end BassBoost_getParameter */
+
+//----------------------------------------------------------------------------
+// BassBoost_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a BassBoost parameter
+//
+// Inputs:
+// pBassBoost - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int BassBoost_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+ int status = 0;
+ int16_t strength;
+
+ //LOGV("\tBassBoost_setParameter start");
+
+ switch (*pParam){
+ case BASSBOOST_PARAM_STRENGTH:
+ strength = *(int16_t *)pValue;
+ //LOGV("\tBassBoost_setParameter() BASSBOOST_PARAM_STRENGTH value is %d", strength);
+ //LOGV("\tBassBoost_setParameter() Calling pBassBoost->BassSetStrength");
+ BassSetStrength(pContext, (int32_t)strength);
+ //LOGV("\tBassBoost_setParameter() Called pBassBoost->BassSetStrength");
+ break;
+ default:
+ LOGV("\tLVM_ERROR : BassBoost_setParameter() invalid param %d", *pParam);
+ break;
+ }
+
+ //LOGV("\tBassBoost_setParameter end");
+ return status;
+} /* end BassBoost_setParameter */
+
+//----------------------------------------------------------------------------
+// Virtualizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Virtualizer parameter
+//
+// Inputs:
+// pVirtualizer - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to variable to hold retrieved value
+// pValueSize - pointer to value size: maximum size as input
+//
+// Outputs:
+// *pValue updated with parameter value
+// *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Virtualizer_getParameter(EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int32_t param = *pParam++;
+ int32_t param2;
+ char *name;
+
+ //LOGV("\tVirtualizer_getParameter start");
+
+ switch (param){
+ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
+ case VIRTUALIZER_PARAM_STRENGTH:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid pValueSize2 %d",*pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param){
+ case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED:
+ *(uint32_t *)pValue = 1;
+
+ //LOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH_SUPPORTED Value is %d",
+ // *(uint32_t *)pValue);
+ break;
+
+ case VIRTUALIZER_PARAM_STRENGTH:
+ *(int16_t *)pValue = VirtualizerGetStrength(pContext);
+
+ //LOGV("\tVirtualizer_getParameter() VIRTUALIZER_PARAM_STRENGTH Value is %d",
+ // *(int16_t *)pValue);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Virtualizer_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //LOGV("\tVirtualizer_getParameter end");
+ return status;
+} /* end Virtualizer_getParameter */
+
+//----------------------------------------------------------------------------
+// Virtualizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Virtualizer parameter
+//
+// Inputs:
+// pVirtualizer - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Virtualizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+ int status = 0;
+ int16_t strength;
+
+ //LOGV("\tVirtualizer_setParameter start");
+
+ switch (*pParam){
+ case VIRTUALIZER_PARAM_STRENGTH:
+ strength = *(int16_t *)pValue;
+ //LOGV("\tVirtualizer_setParameter() VIRTUALIZER_PARAM_STRENGTH value is %d", strength);
+ //LOGV("\tVirtualizer_setParameter() Calling pVirtualizer->setStrength");
+ VirtualizerSetStrength(pContext, (int32_t)strength);
+ //LOGV("\tVirtualizer_setParameter() Called pVirtualizer->setStrength");
+ break;
+ default:
+ LOGV("\tLVM_ERROR : Virtualizer_setParameter() invalid param %d", *pParam);
+ break;
+ }
+
+ //LOGV("\tVirtualizer_setParameter end");
+ return status;
+} /* end Virtualizer_setParameter */
+
+//----------------------------------------------------------------------------
+// Equalizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Equalizer parameter
+//
+// Inputs:
+// pEqualizer - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to variable to hold retrieved value
+// pValueSize - pointer to value size: maximum size as input
+//
+// Outputs:
+// *pValue updated with parameter value
+// *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+int Equalizer_getParameter(EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int bMute = 0;
+ int32_t param = *pParam++;
+ int32_t param2;
+ char *name;
+
+ //LOGV("\tEqualizer_getParameter start");
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ case EQ_PARAM_CUR_PRESET:
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ if (*pValueSize < sizeof(int16_t)) {
+ LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ if (*pValueSize < 2 * sizeof(int32_t)) {
+ LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 2 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = 2 * sizeof(int32_t);
+ break;
+ case EQ_PARAM_BAND_LEVEL:
+ case EQ_PARAM_GET_BAND:
+ case EQ_PARAM_CENTER_FREQ:
+ if (*pValueSize < sizeof(int32_t)) {
+ LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int32_t);
+ break;
+
+ case EQ_PARAM_GET_PRESET_NAME:
+ break;
+
+ case EQ_PARAM_PROPERTIES:
+ if (*pValueSize < (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t)) {
+ LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid pValueSize 1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = (2 + FIVEBAND_NUMBANDS) * sizeof(uint16_t);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Equalizer_getParameter unknown param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ *(int16_t *)pValue = FIVEBAND_NUMBANDS;
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ *(int32_t *)pValue = -1500;
+ *((int32_t *)pValue + 1) = 1500;
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d",
+ // *(int32_t *)pValue, *((int32_t *)pValue + 1));
+ break;
+
+ case EQ_PARAM_BAND_LEVEL:
+ param2 = *pParam;
+ if (param2 >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ *(int32_t *)pValue = EqualizerGetBandLevel(pContext, param2);
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d",
+ // param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_CENTER_FREQ:
+ param2 = *pParam;
+ if (param2 >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ *(int32_t *)pValue = EqualizerGetCentreFrequency(pContext, param2);
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d",
+ // param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ param2 = *pParam;
+ if (param2 >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ EqualizerGetBandFreqRange(pContext, param2, (uint32_t *)pValue, ((uint32_t *)pValue + 1));
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d",
+ // param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+ break;
+
+ case EQ_PARAM_GET_BAND:
+ param2 = *pParam;
+ *(int32_t *)pValue = EqualizerGetBand(pContext, param2);
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d",
+ // param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_CUR_PRESET:
+ *(int16_t *)pValue = EqualizerGetPreset(pContext);
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ *(int16_t *)pValue = EqualizerGetNumPresets();
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_PRESET_NAME:
+ param2 = *pParam;
+ if (param2 >= EqualizerGetNumPresets()) {
+ //if (param2 >= 20) { // AGO FIX
+ status = -EINVAL;
+ break;
+ }
+ name = (char *)pValue;
+ strncpy(name, EqualizerGetPresetName(param2), *pValueSize - 1);
+ name[*pValueSize - 1] = 0;
+ *pValueSize = strlen(name) + 1;
+ //LOGV("\tEqualizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d",
+ // param2, gEqualizerPresets[param2].name, *pValueSize);
+ break;
+
+ case EQ_PARAM_PROPERTIES: {
+ uint16_t *p = (uint16_t *)pValue;
+ LOGV("\tEqualizer_getParameter() EQ_PARAM_PROPERTIES");
+ p[0] = EqualizerGetPreset(pContext);
+ p[1] = FIVEBAND_NUMBANDS;
+ for (int i = 0; i < FIVEBAND_NUMBANDS; i++) {
+ p[2 + i] = EqualizerGetBandLevel(pContext, i);
+ }
+ } break;
+
+ default:
+ LOGV("\tLVM_ERROR : Equalizer_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //LOGV("\tEqualizer_getParameter end");
+ return status;
+} /* end Equalizer_getParameter */
+
+//----------------------------------------------------------------------------
+// Equalizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Equalizer parameter
+//
+// Inputs:
+// pEqualizer - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+int Equalizer_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+ int status = 0;
+ int32_t preset;
+ int32_t band;
+ int32_t level;
+ int32_t param = *pParam++;
+
+ //LOGV("\tEqualizer_setParameter start");
+ switch (param) {
+ case EQ_PARAM_CUR_PRESET:
+ preset = *(int16_t *)pValue;
+
+ //LOGV("\tEqualizer_setParameter() EQ_PARAM_CUR_PRESET %d", preset);
+ if ((preset >= EqualizerGetNumPresets())||(preset < 0)) {
+ status = -EINVAL;
+ break;
+ }
+ EqualizerSetPreset(pContext, preset);
+ break;
+ case EQ_PARAM_BAND_LEVEL:
+ band = *pParam;
+ level = *(int32_t *)pValue;
+ //LOGV("\tEqualizer_setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
+ if (band >= FIVEBAND_NUMBANDS) {
+ status = -EINVAL;
+ break;
+ }
+ EqualizerSetBandLevel(pContext, band, level);
+ break;
+ default:
+ LOGV("\tLVM_ERROR : setParameter() invalid param %d", param);
+ break;
+ }
+
+ //LOGV("\tEqualizer_setParameter end");
+ return status;
+} /* end Equalizer_setParameter */
+
+//----------------------------------------------------------------------------
+// Volume_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Volume parameter
+//
+// Inputs:
+// pVolume - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to variable to hold retrieved value
+// pValueSize - pointer to value size: maximum size as input
+//
+// Outputs:
+// *pValue updated with parameter value
+// *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Volume_getParameter(EffectContext *pContext,
+ int32_t *pParam,
+ size_t *pValueSize,
+ void *pValue){
+ int status = 0;
+ int bMute = 0;
+ int32_t param = *pParam++;
+ int32_t param2;
+ char *name;
+
+ LOGV("\tVolume_getParameter start");
+
+ switch (param){
+ case VOLUME_PARAM_LEVEL:
+ case VOLUME_PARAM_MAXLEVEL:
+ case VOLUME_PARAM_STEREOPOSITION:
+ if (*pValueSize != sizeof(int16_t)){
+ LOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 1 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ case VOLUME_PARAM_MUTE:
+ case VOLUME_PARAM_ENABLESTEREOPOSITION:
+ if (*pValueSize < sizeof(int32_t)){
+ LOGV("\tLVM_ERROR : Volume_getParameter() invalid pValueSize 2 %d", *pValueSize);
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int32_t);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Volume_getParameter unknown param %d", param);
+ return -EINVAL;
+ }
+
+ switch (param){
+ case VOLUME_PARAM_LEVEL:
+ status = VolumeGetVolumeLevel(pContext, (int16_t *)(pValue));
+ LOGV("\tVolume_getParameter() VOLUME_PARAM_LEVEL Value is %d",
+ *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_MAXLEVEL:
+ *(int16_t *)pValue = 0;
+ LOGV("\tVolume_getParameter() VOLUME_PARAM_MAXLEVEL Value is %d",
+ *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_STEREOPOSITION:
+ VolumeGetStereoPosition(pContext, (int16_t *)pValue);
+ LOGV("\tVolume_getParameter() VOLUME_PARAM_STEREOPOSITION Value is %d",
+ *(int16_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_MUTE:
+ status = VolumeGetMute(pContext, (uint32_t *)pValue);
+ LOGV("\tVolume_getParameter() VOLUME_PARAM_MUTE Value is %d",
+ *(uint32_t *)pValue);
+ break;
+
+ case VOLUME_PARAM_ENABLESTEREOPOSITION:
+ *(int32_t *)pValue = pContext->pBundledContext->bStereoPositionEnabled;
+ LOGV("\tVolume_getParameter() VOLUME_PARAM_ENABLESTEREOPOSITION Value is %d",
+ *(uint32_t *)pValue);
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Volume_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ //LOGV("\tVolume_getParameter end");
+ return status;
+} /* end Volume_getParameter */
+
+
+//----------------------------------------------------------------------------
+// Volume_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Volume parameter
+//
+// Inputs:
+// pVolume - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Volume_setParameter (EffectContext *pContext, int32_t *pParam, void *pValue){
+ int status = 0;
+ int16_t level;
+ int16_t position;
+ uint32_t mute;
+ uint32_t positionEnabled;
+
+ LOGV("\tVolume_setParameter start");
+
+ switch (*pParam){
+ case VOLUME_PARAM_LEVEL:
+ level = *(int16_t *)pValue;
+ LOGV("\tVolume_setParameter() VOLUME_PARAM_LEVEL value is %d", level);
+ LOGV("\tVolume_setParameter() Calling pVolume->setVolumeLevel");
+ status = VolumeSetVolumeLevel(pContext, (int16_t)level);
+ LOGV("\tVolume_setParameter() Called pVolume->setVolumeLevel");
+ break;
+
+ case VOLUME_PARAM_MUTE:
+ mute = *(uint32_t *)pValue;
+ LOGV("\tVolume_setParameter() Calling pVolume->setMute, mute is %d", mute);
+ LOGV("\tVolume_setParameter() Calling pVolume->setMute");
+ status = VolumeSetMute(pContext, mute);
+ LOGV("\tVolume_setParameter() Called pVolume->setMute");
+ break;
+
+ case VOLUME_PARAM_ENABLESTEREOPOSITION:
+ positionEnabled = *(uint32_t *)pValue;
+ status = VolumeEnableStereoPosition(pContext, positionEnabled);
+ status = VolumeSetStereoPosition(pContext, pContext->pBundledContext->positionSaved);
+ LOGV("\tVolume_setParameter() VOLUME_PARAM_ENABLESTEREOPOSITION called");
+ break;
+
+ case VOLUME_PARAM_STEREOPOSITION:
+ position = *(int16_t *)pValue;
+ LOGV("\tVolume_setParameter() VOLUME_PARAM_STEREOPOSITION value is %d", position);
+ LOGV("\tVolume_setParameter() Calling pVolume->VolumeSetStereoPosition");
+ status = VolumeSetStereoPosition(pContext, (int16_t)position);
+ LOGV("\tVolume_setParameter() Called pVolume->VolumeSetStereoPosition");
+ break;
+
+ default:
+ LOGV("\tLVM_ERROR : Volume_setParameter() invalid param %d", *pParam);
+ break;
+ }
+
+ //LOGV("\tVolume_setParameter end");
+ return status;
+} /* end Volume_setParameter */
+
+/****************************************************************************************
+ * Name : LVC_ToDB_s32Tos16()
+ * Input : Signed 32-bit integer
+ * Output : Signed 16-bit integer
+ * MSB (16) = sign bit
+ * (15->05) = integer part
+ * (04->01) = decimal part
+ * Returns : Db value with respect to full scale
+ * Description :
+ * Remarks :
+ ****************************************************************************************/
+
+LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix)
+{
+ LVM_INT16 db_fix;
+ LVM_INT16 Shift;
+ LVM_INT16 SmallRemainder;
+ LVM_UINT32 Remainder = (LVM_UINT32)Lin_fix;
+
+ /* Count leading bits, 1 cycle in assembly*/
+ for (Shift = 0; Shift<32; Shift++)
+ {
+ if ((Remainder & 0x80000000U)!=0)
+ {
+ break;
+ }
+ Remainder = Remainder << 1;
+ }
+
+ /*
+ * Based on the approximation equation (for Q11.4 format):
+ *
+ * dB = -96 * Shift + 16 * (8 * Remainder - 2 * Remainder^2)
+ */
+ db_fix = (LVM_INT16)(-96 * Shift); /* Six dB steps in Q11.4 format*/
+ SmallRemainder = (LVM_INT16)((Remainder & 0x7fffffff) >> 24);
+ db_fix = (LVM_INT16)(db_fix + SmallRemainder );
+ SmallRemainder = (LVM_INT16)(SmallRemainder * SmallRemainder);
+ db_fix = (LVM_INT16)(db_fix - (LVM_INT16)((LVM_UINT16)SmallRemainder >> 9));
+
+ /* Correct for small offset */
+ db_fix = (LVM_INT16)(db_fix - 5);
+
+ return db_fix;
+}
+
+} // namespace
+} // namespace
+
+/* Effect Control Interface Implementation: Process */
+extern "C" int Effect_process(effect_interface_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer){
+ EffectContext * pContext = (EffectContext *) self;
+ int status = 0;
+ int lvmStatus = 0;
+ LVM_INT16 *in = (LVM_INT16 *)inBuffer->raw;
+ LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
+
+ //LOGV("\tEffect_process Start : Enabled = %d Called = %d",
+ //pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled);
+
+ if (pContext == NULL){
+ LOGV("\tLVM_ERROR : Effect_process() ERROR pContext == NULL");
+ return -EINVAL;
+ }
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount){
+ LOGV("\tLVM_ERROR : Effect_process() ERROR NULL INPUT POINTER OR FRAME COUNT IS WRONG");
+ return -EINVAL;
+ }
+ if ((pContext->pBundledContext->bBassEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_BASS_BOOST)){
+ LOGV("\tEffect_process() ERROR LVM_BASS_BOOST Effect is not enabled");
+ status = -ENODATA;
+ }
+ if ((pContext->pBundledContext->bVolumeEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_VOLUME)){
+ LOGV("\tEffect_process() ERROR LVM_VOLUME Effect is not enabled");
+ status = -ENODATA;
+ }
+ if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_EQUALIZER)){
+ LOGV("\tEffect_process() ERROR LVM_EQUALIZER Effect is not enabled");
+ status = -ENODATA;
+ }
+ if ((pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE)&&
+ (pContext->EffectType == LVM_VIRTUALIZER)){
+ LOGV("\tEffect_process() ERROR LVM_VIRTUALIZER Effect is not enabled");
+ status = -ENODATA;
+ }
+
+ // If this is the last frame of an effect process its output with no effect
+ if(status == -ENODATA){
+ if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
+ //LOGV("\tLVM_ERROR : Effect_process() accumulating last frame into output buffer");
+ //LOGV("\tLVM_ERROR : Effect_process() trying copying last frame into output buffer");
+ //LOGV("\tLVM_ERROR : Enabled = %d Called = %d",
+ //pContext->pBundledContext->NumberEffectsEnabled,
+ //pContext->pBundledContext->NumberEffectsCalled);
+
+ }else{
+ //LOGV("\tLVM_ERROR : Effect_process() copying last frame into output buffer");
+ }
+ }
+
+ if(status != -ENODATA){
+ pContext->pBundledContext->NumberEffectsCalled++;
+ }
+
+ if(pContext->pBundledContext->NumberEffectsCalled ==
+ pContext->pBundledContext->NumberEffectsEnabled){
+ //LOGV("\tEffect_process Calling process with %d effects enabled, %d called: Effect %d",
+ //pContext->pBundledContext->NumberEffectsEnabled,
+ //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
+
+ if(status == -ENODATA){
+ //LOGV("\tLVM_ERROR : Effect_process() actually processing last frame");
+ }
+ pContext->pBundledContext->NumberEffectsCalled = 0;
+ /* Process all the available frames, block processing is
+ handled internalLY by the LVM bundle */
+ lvmStatus = android::LvmBundle_process( (LVM_INT16 *)inBuffer->raw,
+ (LVM_INT16 *)outBuffer->raw,
+ outBuffer->frameCount,
+ pContext);
+ if(lvmStatus != LVM_SUCCESS){
+ LOGV("\tLVM_ERROR : LvmBundle_process returned error %d", lvmStatus);
+ return lvmStatus;
+ }
+ }else{
+ //LOGV("\tEffect_process Not Calling process with %d effects enabled, %d called: Effect %d",
+ //pContext->pBundledContext->NumberEffectsEnabled,
+ //pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
+ // 2 is for stereo input
+ memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount*sizeof(LVM_INT16)*2);
+ }
+
+ return status;
+} /* end Effect_process */
+
+/* Effect Control Interface Implementation: Command */
+extern "C" int Effect_command(effect_interface_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData){
+ EffectContext * pContext = (EffectContext *) self;
+ int retsize;
+
+ //LOGV("\t\nEffect_command start");
+
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ //LOGV("\tEffect_command setting command for LVM_BASS_BOOST");
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ //LOGV("\tEffect_command setting command for LVM_VIRTUALIZER");
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //LOGV("\tEffect_command setting command for LVM_EQUALIZER");
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //LOGV("\tEffect_command setting command for LVM_VOLUME");
+ }
+
+ if (pContext == NULL){
+ LOGV("\tLVM_ERROR : Effect_command ERROR pContext == NULL");
+ return -EINVAL;
+ }
+
+ //LOGV("\tEffect_command INPUTS are: command %d cmdSize %d",cmdCode, cmdSize);
+
+ // Incase we disable an effect, next time process is
+ // called the number of effect called could be greater
+ // pContext->pBundledContext->NumberEffectsCalled = 0;
+
+ //LOGV("\tEffect_command NumberEffectsCalled = %d, NumberEffectsEnabled = %d",
+ // pContext->pBundledContext->NumberEffectsCalled,
+ // pContext->pBundledContext->NumberEffectsEnabled);
+
+ switch (cmdCode){
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR, EFFECT_CMD_INIT: ERROR for effect type %d",
+ pContext->EffectType);
+ return -EINVAL;
+ }
+ *(int *) pReplyData = 0;
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT start");
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_BASS_BOOST");
+ android::BassSetStrength(pContext, 0);
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_VIRTUALIZER");
+ android::VirtualizerSetStrength(pContext, 0);
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_INIT for LVM_EQUALIZER");
+ android::EqualizerSetPreset(pContext, 0);
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //LOGV("\tEffect_command cmdCode Case: "
+ // "EFFECT_CMD_INIT start");
+ *(int *) pReplyData = android::VolumeSetVolumeLevel(pContext, 0);
+ }
+ break;
+
+ case EFFECT_CMD_CONFIGURE:
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_CONFIGURE start");
+ if (pCmdData == NULL||
+ cmdSize != sizeof(effect_config_t)||
+ pReplyData == NULL||
+ *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_CONFIGURE: ERROR");
+ return -EINVAL;
+ }
+ *(int *) pReplyData = android::Effect_configure(pContext, (effect_config_t *) pCmdData);
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_CONFIGURE end");
+ break;
+
+ case EFFECT_CMD_RESET:
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_RESET start");
+ android::Effect_configure(pContext, &pContext->config);
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_RESET end");
+ break;
+
+ case EFFECT_CMD_GET_PARAM:{
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM start");
+
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ if (pCmdData == NULL ||
+ cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+ LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+ "EFFECT_CMD_GET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *)pCmdData;
+
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+ p = (effect_param_t *)pReplyData;
+
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+ p->status = android::BassBoost_getParameter(pContext,
+ (int32_t *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //LOGV("\tBassBoost_command EFFECT_CMD_GET_PARAM "
+ // "*pCmdData %d, *replySize %d, *pReplyData %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+ }
+
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ if (pCmdData == NULL ||
+ cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+ LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+ "EFFECT_CMD_GET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *)pCmdData;
+
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+ p = (effect_param_t *)pReplyData;
+
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+ p->status = android::Virtualizer_getParameter(pContext,
+ (int32_t *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //LOGV("\tVirtualizer_command EFFECT_CMD_GET_PARAM "
+ // "*pCmdData %d, *replySize %d, *pReplyData %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //LOGV("\tEqualizer_command cmdCode Case: "
+ // "EFFECT_CMD_GET_PARAM start");
+ if (pCmdData == NULL ||
+ cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
+ LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+ "EFFECT_CMD_GET_PARAM");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *)pCmdData;
+
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+ p = (effect_param_t *)pReplyData;
+
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+ p->status = android::Equalizer_getParameter(pContext, (int32_t *)p->data, &p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //LOGV("\tEqualizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, "
+ // "*pReplyData %08x %08x",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
+ // *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
+ // *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset +
+ // sizeof(int32_t)));
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //LOGV("\tVolume_command cmdCode Case: "
+ // "EFFECT_CMD_GET_PARAM start");
+ if (pCmdData == NULL ||
+ cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))){
+ LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+ "EFFECT_CMD_GET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *)pCmdData;
+
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+
+ p = (effect_param_t *)pReplyData;
+
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+
+ p->status = android::Volume_getParameter(pContext,
+ (int32_t *)p->data,
+ (size_t *)&p->vsize,
+ p->data + voffset);
+
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+
+ //LOGV("\tVolume_command EFFECT_CMD_GET_PARAM "
+ // "*pCmdData %d, *replySize %d, *pReplyData %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset));
+ }
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_GET_PARAM end");
+ } break;
+ case EFFECT_CMD_SET_PARAM:{
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ //LOGV("\tBassBoost_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+ if (pCmdData == NULL||
+ cmdSize != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
+ pReplyData == NULL||
+ *replySize != sizeof(int32_t)){
+ LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ if (p->psize != sizeof(int32_t)){
+ LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+
+ //LOGV("\tnBassBoost_command cmdSize is %d\n"
+ // "\tsizeof(effect_param_t) is %d\n"
+ // "\tp->psize is %d\n"
+ // "\tp->vsize is %d"
+ // "\n",
+ // cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
+
+ *(int *)pReplyData = android::BassBoost_setParameter(pContext,
+ (int32_t *)p->data,
+ p->data + p->psize);
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ //LOGV("\tVirtualizer_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+ if (pCmdData == NULL||
+ cmdSize != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
+ pReplyData == NULL||
+ *replySize != sizeof(int32_t)){
+ LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ if (p->psize != sizeof(int32_t)){
+ LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR, psize is not sizeof(int32_t)");
+ return -EINVAL;
+ }
+
+ //LOGV("\tnVirtualizer_command cmdSize is %d\n"
+ // "\tsizeof(effect_param_t) is %d\n"
+ // "\tp->psize is %d\n"
+ // "\tp->vsize is %d"
+ // "\n",
+ // cmdSize, sizeof(effect_param_t), p->psize, p->vsize );
+
+ *(int *)pReplyData = android::Virtualizer_setParameter(pContext,
+ (int32_t *)p->data,
+ p->data + p->psize);
+ }
+ if(pContext->EffectType == LVM_EQUALIZER){
+ //LOGV("\tEqualizer_command cmdCode Case: "
+ // "EFFECT_CMD_SET_PARAM start");
+ //LOGV("\tEqualizer_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+ if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL || *replySize != sizeof(int32_t)) {
+ LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ *(int *)pReplyData = android::Equalizer_setParameter(pContext,
+ (int32_t *)p->data,
+ p->data + p->psize);
+ }
+ if(pContext->EffectType == LVM_VOLUME){
+ //LOGV("\tVolume_command cmdCode Case: "
+ // "EFFECT_CMD_SET_PARAM start");
+ //LOGV("\tVolume_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+
+ if ( pCmdData == NULL||
+ cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t))||
+ pReplyData == NULL||
+ *replySize != sizeof(int32_t)){
+ LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+ "EFFECT_CMD_SET_PARAM: ERROR");
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *) pCmdData;
+
+ *(int *)pReplyData = android::Volume_setParameter(pContext,
+ (int32_t *)p->data,
+ p->data + p->psize);
+ }
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM end");
+ } break;
+
+ case EFFECT_CMD_ENABLE:
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE start");
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_ENABLE: ERROR");
+ return -EINVAL;
+ }
+ switch (pContext->EffectType){
+ case LVM_BASS_BOOST:
+ if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
+ LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bBassEnabled = LVM_TRUE;
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_BASS_BOOST enabled");
+ break;
+ case LVM_EQUALIZER:
+ if(pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE){
+ LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_EQUALIZER enabled");
+ break;
+ case LVM_VIRTUALIZER:
+ if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
+ LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
+ //LOGV("\tEffect_command cmdCode Case:EFFECT_CMD_ENABLE LVM_VIRTUALIZER enabled");
+ break;
+ case LVM_VOLUME:
+ if(pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
+ LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR-Effect is already enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE LVM_VOLUME enabled");
+ break;
+ default:
+ LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_ENABLE: ERROR, invalid Effect Type");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ android::LvmEffect_enable(pContext);
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE NumberEffectsEnabled = %d",
+ // pContext->pBundledContext->NumberEffectsEnabled);
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_ENABLE end");
+ break;
+
+ case EFFECT_CMD_DISABLE:
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE start");
+ if (pReplyData == NULL || *replySize != sizeof(int)){
+ LOGV("\tLVM_ERROR : Effect_command cmdCode Case: EFFECT_CMD_DISABLE: ERROR");
+ return -EINVAL;
+ }
+ switch (pContext->EffectType){
+ case LVM_BASS_BOOST:
+ if(pContext->pBundledContext->bBassEnabled == LVM_FALSE){
+ LOGV("\tLVM_ERROR : BassBoost_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bBassEnabled = LVM_FALSE;
+ //LOGV("\tEffect_command cmdCode Case: "
+ // "EFFECT_CMD_DISABLE LVM_BASS_BOOST disabled");
+ break;
+ case LVM_EQUALIZER:
+ if(pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE){
+ LOGV("\tLVM_ERROR : Equalizer_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
+ //LOGV("\tEffect_command cmdCode Case: "
+ // "EFFECT_CMD_DISABLE LVM_EQUALIZER disabled");
+ break;
+ case LVM_VIRTUALIZER:
+ if(pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE){
+ LOGV("\tLVM_ERROR : Virtualizer_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
+ //LOGV("\tEffect_command cmdCode Case: "
+ // "EFFECT_CMD_DISABLE LVM_VIRTUALIZER disabled");
+ break;
+ case LVM_VOLUME:
+ if(pContext->pBundledContext->bVolumeEnabled == LVM_FALSE){
+ LOGV("\tLVM_ERROR : Volume_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR-Effect is not yet enabled");
+ return -EINVAL;
+ }
+ pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE LVM_VOLUME disabled");
+ break;
+ default:
+ LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_DISABLE: ERROR, invalid Effect Type");
+ return -EINVAL;
+ }
+ *(int *)pReplyData = 0;
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ android::LvmEffect_disable(pContext);
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE NumberEffectsEnabled = %d",
+ // pContext->pBundledContext->NumberEffectsEnabled);
+ //LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_DISABLE end");
+ break;
+
+ case EFFECT_CMD_SET_DEVICE:
+ {
+ LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE start");
+ audio_device_e device = *(audio_device_e *)pCmdData;
+
+ if(pContext->EffectType == LVM_BASS_BOOST){
+ if((device == DEVICE_SPEAKER)||(device == DEVICE_BLUETOOTH_SCO_CARKIT)||
+ (device == DEVICE_BLUETOOTH_A2DP_SPEAKER)){
+ LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_BASS_BOOST %d",
+ *(int32_t *)pCmdData);
+ LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_BAS_BOOST");
+
+ // If a device doesnt support bassboost the effect must be temporarily disabled
+ // the effect must still report its original state as this can only be changed
+ // by the ENABLE/DISABLE command
+
+ if(pContext->pBundledContext->bBassEnabled == LVM_TRUE){
+ LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_BASS_BOOST %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_disable(pContext);
+ pContext->pBundledContext->bBassTempDisabled = LVM_TRUE;
+ }
+ }else{
+ LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_BASS_BOOST %d",
+ *(int32_t *)pCmdData);
+
+ // If a device supports bassboost and the effect has been temporarily disabled
+ // previously then re-enable it
+
+ if(pContext->pBundledContext->bBassTempDisabled == LVM_TRUE){
+ LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_BASS_BOOST %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_enable(pContext);
+ pContext->pBundledContext->bBassTempDisabled = LVM_FALSE;
+ }
+ }
+ }
+ if(pContext->EffectType == LVM_VIRTUALIZER){
+ if((device == DEVICE_SPEAKER)||(device == DEVICE_BLUETOOTH_SCO_CARKIT)||
+ (device == DEVICE_BLUETOOTH_A2DP_SPEAKER)){
+ LOGV("\tEFFECT_CMD_SET_DEVICE device is invalid for LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+ LOGV("\tEFFECT_CMD_SET_DEVICE temporary disable LVM_VIRTUALIZER");
+
+ //If a device doesnt support virtualizer the effect must be temporarily disabled
+ // the effect must still report its original state as this can only be changed
+ // by the ENABLE/DISABLE command
+
+ if(pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE){
+ LOGV("\tEFFECT_CMD_SET_DEVICE disable LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_disable(pContext);
+ pContext->pBundledContext->bVirtualizerTempDisabled = LVM_TRUE;
+ }
+ }else{
+ LOGV("\tEFFECT_CMD_SET_DEVICE device is valid for LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+
+ // If a device supports virtualizer and the effect has been temporarily disabled
+ // previously then re-enable it
+
+ if(pContext->pBundledContext->bVirtualizerTempDisabled == LVM_TRUE){
+ LOGV("\tEFFECT_CMD_SET_DEVICE re-enable LVM_VIRTUALIZER %d",
+ *(int32_t *)pCmdData);
+ android::LvmEffect_enable(pContext);
+ pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
+ }
+ }
+ }
+ LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_DEVICE end");
+ break;
+ }
+ case EFFECT_CMD_SET_VOLUME:
+ {
+ int32_t channels = cmdSize/sizeof(int32_t);
+ int32_t vol = *(int32_t *)pCmdData;
+ int16_t vol_db;
+ int16_t dB;
+ int16_t vol_db_rnd;
+ int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
+
+ // if pReplyData is NULL, VOL_CTRL is delegated to another effect
+ if(pReplyData == LVM_NULL){
+ break;
+ }
+
+ if(vol==0x1000000){
+ vol -= 1;
+ }
+ // Convert volume linear (Q8.24) to volume dB (0->-96)
+ dB = android::LVC_ToDB_s32Tos16(vol <<7);
+ dB = (dB +8)>>4;
+ dB = (dB <-96) ? -96 : dB ;
+
+ //LOGV("\tSession: %d, VOLUME is %d dB (%d), effect is %d",
+ //pContext->pBundledContext->SessionNo, (int32_t)dB, vol<<7, pContext->EffectType);
+ memcpy(pReplyData, vol_ret, sizeof(int32_t)*2);
+ android::VolumeSetVolumeLevel(pContext, (int16_t)(dB*100));
+ break;
+ }
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ //LOGV("\tEffect_command end...\n\n");
+ return 0;
+} /* end Effect_command */
+
+// effect_interface_t interface implementation for effect
+const struct effect_interface_s gLvmEffectInterface = {
+ Effect_process,
+ Effect_command
+}; /* end gLvmEffectInterface */
+
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
new file mode 100644
index 0000000..d009bf9
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTBUNDLE_H_
+#define ANDROID_EFFECTBUNDLE_H_
+
+#include <media/EffectEqualizerApi.h>
+#include <media/EffectBassBoostApi.h>
+#include <media/EffectVirtualizerApi.h>
+#include <LVM.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+#define FIVEBAND_NUMBANDS 5
+#define MAX_NUM_BANDS 5
+#define MAX_CALL_SIZE 256
+//#define LVM_PCM
+
+#ifndef OPENSL_ES_H_
+static const effect_uuid_t SL_IID_VOLUME_ = { 0x09e8ede0, 0xddde, 0x11db, 0xb4f6,
+ { 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b } };
+const effect_uuid_t * const SL_IID_VOLUME = &SL_IID_VOLUME_;
+#endif //OPENSL_ES_H_
+
+typedef enum
+{
+ LVM_BASS_BOOST,
+ LVM_VIRTUALIZER,
+ LVM_EQUALIZER,
+ LVM_VOLUME
+} lvm_effect_en;
+
+// Preset configuration.
+struct PresetConfig {
+ // Human-readable name.
+ const char * name;
+ // An array of size nBands where each element is a configuration for the
+ // corresponding band.
+ //const BandConfig * bandConfigs;
+};
+
+/* BundledEffectContext : One per session */
+struct BundledEffectContext{
+ LVM_Handle_t hInstance; /* Instance handle */
+ int SessionNo; /* Current session number */
+ bool bVolumeEnabled; /* Flag for Volume */
+ bool bEqualizerEnabled; /* Flag for EQ */
+ bool bBassEnabled; /* Flag for Bass */
+ bool bBassTempDisabled; /* Flag for Bass to be re-enabled */
+ bool bVirtualizerEnabled; /* Flag for Virtualizer */
+ bool bVirtualizerTempDisabled; /* Flag for effect to be re-enabled */
+ int NumberEffectsEnabled; /* Effects in this session */
+ int NumberEffectsCalled; /* Effects called so far */
+ // Saved parameters for each effect */
+ // Bass Boost
+ int BassStrengthSaved; /* Conversion between Get/Set */
+ // Equalizer
+ int CurPreset; /* Current preset being used */
+ // Virtualzer
+ int VirtStrengthSaved; /* Conversion between Get/Set */
+ // Volume
+ int levelSaved; /* for when mute is set, level must be saved */
+ int positionSaved;
+ bool bMuteEnabled; /* Must store as mute = -96dB level */
+ bool bStereoPositionEnabled;
+ int frameCount;
+ LVM_Fs_en SampleRate;
+ #ifdef LVM_PCM
+ FILE *PcmInPtr;
+ FILE *PcmOutPtr;
+ #endif
+};
+
+/* SessionContext : One session */
+struct SessionContext{
+ bool bBundledEffectsEnabled;
+ bool bVolumeInstantiated;
+ bool bEqualizerInstantiated;
+ bool bBassInstantiated;
+ bool bVirtualizerInstantiated;
+ BundledEffectContext *pBundledContext;
+};
+
+struct EffectContext{
+ const struct effect_interface_s *itfe;
+ effect_config_t config;
+ lvm_effect_en EffectType;
+ BundledEffectContext *pBundledContext;
+};
+
+
+/* enumerated parameter settings for Volume effect */
+typedef enum
+{
+ VOLUME_PARAM_LEVEL, // type SLmillibel = typedef SLuint16 (set & get)
+ VOLUME_PARAM_MAXLEVEL, // type SLmillibel = typedef SLuint16 (get)
+ VOLUME_PARAM_MUTE, // type SLboolean = typedef SLuint32 (set & get)
+ VOLUME_PARAM_ENABLESTEREOPOSITION, // type SLboolean = typedef SLuint32 (set & get)
+ VOLUME_PARAM_STEREOPOSITION, // type SLpermille = typedef SLuint16 (set & get)
+} t_volume_params;
+
+static const int PRESET_CUSTOM = -1;
+
+static const uint32_t bandFreqRange[FIVEBAND_NUMBANDS][2] = {
+ {30000, 120000},
+ {120001, 460000},
+ {460001, 1800000},
+ {1800001, 7000000},
+ {7000001, 1}};
+
+static const LVM_UINT16 EQNB_5BandPresetsFrequencies[] = {
+ 60, /* Frequencies in Hz */
+ 230,
+ 910,
+ 3600,
+ 14000};
+
+static const LVM_UINT16 EQNB_5BandPresetsQFactors[] = {
+ 96, /* Q factor multiplied by 100 */
+ 96,
+ 96,
+ 96,
+ 96};
+
+static const LVM_INT16 EQNB_5BandNormalPresets[] = {
+ 3, 0, 0, 0, 3, /* Normal Preset */
+ 8, 5, -3, 5, 6, /* Classical Preset */
+ 15, -6, 7, 13, 10, /* Dance Preset */
+ 0, 0, 0, 0, 0, /* Flat Preset */
+ 6, -2, -2, 6, -3, /* Folk Preset */
+ 8, -8, 13, -1, -4, /* Heavy Metal Preset */
+ 10, 6, -4, 5, 8, /* Hip Hop Preset */
+ 8, 5, -4, 5, 9, /* Jazz Preset */
+ -6, 4, 9, 4, -5, /* Pop Preset */
+ 10, 6, -1, 8, 10}; /* Rock Preset */
+
+static const LVM_INT16 EQNB_5BandSoftPresets[] = {
+ 3, 0, 0, 0, 3, /* Normal Preset */
+ 5, 3, -2, 4, 4, /* Classical Preset */
+ 6, 0, 2, 4, 1, /* Dance Preset */
+ 0, 0, 0, 0, 0, /* Flat Preset */
+ 3, 0, 0, 2, -1, /* Folk Preset */
+ 4, 1, 9, 3, 0, /* Heavy Metal Preset */
+ 5, 3, 0, 1, 3, /* Hip Hop Preset */
+ 4, 2, -2, 2, 5, /* Jazz Preset */
+ -1, 2, 5, 1, -2, /* Pop Preset */
+ 5, 3, -1, 3, 5}; /* Rock Preset */
+
+static const PresetConfig gEqualizerPresets[] = {
+ {"Normal"},
+ {"Classical"},
+ {"Dance"},
+ {"Flat"},
+ {"Folk"},
+ {"Heavy Metal"},
+ {"Hip Hop"},
+ {"Jazz"},
+ {"Pop"},
+ {"Rock"}};
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /*ANDROID_EFFECTBUNDLE_H_*/
diff --git a/media/libeffects/testlibs/Android.mk_ b/media/libeffects/testlibs/Android.mk_
new file mode 100644
index 0000000..9ba71ed
--- /dev/null
+++ b/media/libeffects/testlibs/Android.mk_
@@ -0,0 +1,66 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Test Reverb library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectReverb.c.arm \
+ EffectsMath.c.arm
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libreverbtest
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Test Equalizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectsMath.c.arm \
+ EffectEqualizer.cpp \
+ AudioBiquadFilter.cpp.arm \
+ AudioCoefInterpolator.cpp.arm \
+ AudioPeakingFilter.cpp.arm \
+ AudioShelvingFilter.cpp.arm \
+ AudioEqualizer.cpp.arm
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libequalizertest
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/media/libeffects/testlibs/AudioBiquadFilter.cpp b/media/libeffects/testlibs/AudioBiquadFilter.cpp
new file mode 100644
index 0000000..72917a3
--- /dev/null
+++ b/media/libeffects/testlibs/AudioBiquadFilter.cpp
@@ -0,0 +1,260 @@
+/* //device/servers/AudioFlinger/AudioBiquadFilter.cpp
+**
+** Copyright 2009, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <string.h>
+#include <assert.h>
+
+#include "AudioBiquadFilter.h"
+
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+const audio_coef_t AudioBiquadFilter::IDENTITY_COEFS[AudioBiquadFilter::NUM_COEFS] = { AUDIO_COEF_ONE, 0, 0, 0, 0 };
+
+AudioBiquadFilter::AudioBiquadFilter(int nChannels, int sampleRate) {
+ configure(nChannels, sampleRate);
+ reset();
+}
+
+void AudioBiquadFilter::configure(int nChannels, int sampleRate) {
+ assert(nChannels > 0 && nChannels <= MAX_CHANNELS);
+ assert(sampleRate > 0);
+ mNumChannels = nChannels;
+ mMaxDelta = static_cast<int64_t>(MAX_DELTA_PER_SEC)
+ * AUDIO_COEF_ONE
+ / sampleRate;
+ clear();
+}
+
+void AudioBiquadFilter::reset() {
+ memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs));
+ mCoefDirtyBits = 0;
+ setState(STATE_BYPASS);
+}
+
+void AudioBiquadFilter::clear() {
+ memset(mDelays, 0, sizeof(mDelays));
+}
+
+void AudioBiquadFilter::setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate) {
+ memcpy(mTargetCoefs, coefs, sizeof(mTargetCoefs));
+ if (mState & STATE_ENABLED_MASK) {
+ if (UNLIKELY(immediate)) {
+ memcpy(mCoefs, coefs, sizeof(mCoefs));
+ setState(STATE_NORMAL);
+ } else {
+ setState(STATE_TRANSITION_TO_NORMAL);
+ }
+ }
+}
+
+void AudioBiquadFilter::process(const audio_sample_t in[], audio_sample_t out[],
+ int frameCount) {
+ (this->*mCurProcessFunc)(in, out, frameCount);
+}
+
+void AudioBiquadFilter::enable(bool immediate) {
+ if (UNLIKELY(immediate)) {
+ memcpy(mCoefs, mTargetCoefs, sizeof(mCoefs));
+ setState(STATE_NORMAL);
+ } else {
+ setState(STATE_TRANSITION_TO_NORMAL);
+ }
+}
+
+void AudioBiquadFilter::disable(bool immediate) {
+ if (UNLIKELY(immediate)) {
+ memcpy(mCoefs, IDENTITY_COEFS, sizeof(mCoefs));
+ setState(STATE_BYPASS);
+ } else {
+ setState(STATE_TRANSITION_TO_BYPASS);
+ }
+}
+
+void AudioBiquadFilter::setState(state_t state) {
+ switch (state) {
+ case STATE_BYPASS:
+ mCurProcessFunc = &AudioBiquadFilter::process_bypass;
+ break;
+ case STATE_TRANSITION_TO_BYPASS:
+ if (mNumChannels == 1) {
+ mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_mono;
+ } else {
+ mCurProcessFunc = &AudioBiquadFilter::process_transition_bypass_multi;
+ }
+ mCoefDirtyBits = (1 << NUM_COEFS) - 1;
+ break;
+ case STATE_TRANSITION_TO_NORMAL:
+ if (mNumChannels == 1) {
+ mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_mono;
+ } else {
+ mCurProcessFunc = &AudioBiquadFilter::process_transition_normal_multi;
+ }
+ mCoefDirtyBits = (1 << NUM_COEFS) - 1;
+ break;
+ case STATE_NORMAL:
+ if (mNumChannels == 1) {
+ mCurProcessFunc = &AudioBiquadFilter::process_normal_mono;
+ } else {
+ mCurProcessFunc = &AudioBiquadFilter::process_normal_multi;
+ }
+ break;
+ }
+ mState = state;
+}
+
+bool AudioBiquadFilter::updateCoefs(const audio_coef_t coefs[NUM_COEFS],
+ int frameCount) {
+ int64_t maxDelta = mMaxDelta * frameCount;
+ for (int i = 0; i < NUM_COEFS; ++i) {
+ if (mCoefDirtyBits & (1<<i)) {
+ audio_coef_t diff = coefs[i] - mCoefs[i];
+ if (diff > maxDelta) {
+ mCoefs[i] += maxDelta;
+ } else if (diff < -maxDelta) {
+ mCoefs[i] -= maxDelta;
+ } else {
+ mCoefs[i] = coefs[i];
+ mCoefDirtyBits ^= (1<<i);
+ }
+ }
+ }
+ return mCoefDirtyBits == 0;
+}
+
+void AudioBiquadFilter::process_bypass(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ // The common case is in-place processing, because this is what the EQ does.
+ if (UNLIKELY(in != out)) {
+ memcpy(out, in, frameCount * mNumChannels * sizeof(audio_sample_t));
+ }
+}
+
+void AudioBiquadFilter::process_normal_mono(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ size_t nFrames = frameCount;
+ audio_sample_t x1 = mDelays[0][0];
+ audio_sample_t x2 = mDelays[0][1];
+ audio_sample_t y1 = mDelays[0][2];
+ audio_sample_t y2 = mDelays[0][3];
+ const audio_coef_t b0 = mCoefs[0];
+ const audio_coef_t b1 = mCoefs[1];
+ const audio_coef_t b2 = mCoefs[2];
+ const audio_coef_t a1 = mCoefs[3];
+ const audio_coef_t a2 = mCoefs[4];
+ while (nFrames-- > 0) {
+ audio_sample_t x0 = *(in++);
+ audio_coef_sample_acc_t acc;
+ acc = mul_coef_sample(b0, x0);
+ acc = mac_coef_sample(b1, x1, acc);
+ acc = mac_coef_sample(b2, x2, acc);
+ acc = mac_coef_sample(a1, y1, acc);
+ acc = mac_coef_sample(a2, y2, acc);
+ audio_sample_t y0 = coef_sample_acc_to_sample(acc);
+ y2 = y1;
+ y1 = y0;
+ x2 = x1;
+ x1 = x0;
+ (*out++) = y0;
+ }
+ mDelays[0][0] = x1;
+ mDelays[0][1] = x2;
+ mDelays[0][2] = y1;
+ mDelays[0][3] = y2;
+}
+
+void AudioBiquadFilter::process_transition_normal_mono(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ if (updateCoefs(mTargetCoefs, frameCount)) {
+ setState(STATE_NORMAL);
+ }
+ process_normal_mono(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_transition_bypass_mono(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ if (updateCoefs(IDENTITY_COEFS, frameCount)) {
+ setState(STATE_NORMAL);
+ }
+ process_normal_mono(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_normal_multi(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ const audio_coef_t b0 = mCoefs[0];
+ const audio_coef_t b1 = mCoefs[1];
+ const audio_coef_t b2 = mCoefs[2];
+ const audio_coef_t a1 = mCoefs[3];
+ const audio_coef_t a2 = mCoefs[4];
+ for (int ch = 0; ch < mNumChannels; ++ch) {
+ size_t nFrames = frameCount;
+ audio_sample_t x1 = mDelays[ch][0];
+ audio_sample_t x2 = mDelays[ch][1];
+ audio_sample_t y1 = mDelays[ch][2];
+ audio_sample_t y2 = mDelays[ch][3];
+ while (nFrames-- > 0) {
+ audio_sample_t x0 = *in;
+ audio_coef_sample_acc_t acc;
+ acc = mul_coef_sample(b0, x0);
+ acc = mac_coef_sample(b1, x1, acc);
+ acc = mac_coef_sample(b2, x2, acc);
+ acc = mac_coef_sample(a1, y1, acc);
+ acc = mac_coef_sample(a2, y2, acc);
+ audio_sample_t y0 = coef_sample_acc_to_sample(acc);
+ y2 = y1;
+ y1 = y0;
+ x2 = x1;
+ x1 = x0;
+ *out = y0;
+ in += mNumChannels;
+ out += mNumChannels;
+ }
+ mDelays[ch][0] = x1;
+ mDelays[ch][1] = x2;
+ mDelays[ch][2] = y1;
+ mDelays[ch][3] = y2;
+ in -= frameCount * mNumChannels - 1;
+ out -= frameCount * mNumChannels - 1;
+ }
+}
+
+void AudioBiquadFilter::process_transition_normal_multi(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ if (updateCoefs(mTargetCoefs, frameCount)) {
+ setState(STATE_NORMAL);
+ }
+ process_normal_multi(in, out, frameCount);
+}
+
+void AudioBiquadFilter::process_transition_bypass_multi(const audio_sample_t * in,
+ audio_sample_t * out,
+ int frameCount) {
+ if (updateCoefs(IDENTITY_COEFS, frameCount)) {
+ setState(STATE_NORMAL);
+ }
+ process_normal_multi(in, out, frameCount);
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioBiquadFilter.h b/media/libeffects/testlibs/AudioBiquadFilter.h
new file mode 100644
index 0000000..2b0e2d6
--- /dev/null
+++ b/media/libeffects/testlibs/AudioBiquadFilter.h
@@ -0,0 +1,180 @@
+/* //device/include/server/AudioFlinger/AudioBiquadFilter.h
+**
+** Copyright 2007, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_AUDIO_BIQUAD_FILTER_H
+#define ANDROID_AUDIO_BIQUAD_FILTER_H
+
+#include "AudioCommon.h"
+
+namespace android {
+// A biquad filter.
+// Implements the recursion y[n]=a0*y[n-1]+a1*y[n-2]+b0*x[n]+b1*x[n-1]+b2*x[n-2]
+// (the a0 and a1 coefficients have an opposite sign to the common convention)
+// The filter works on fixed sized blocks of data (frameCount multi-channel
+// samples, as defined during construction). An arbitrary number of interlaced
+// channels is supported.
+// Filter can operate in an enabled (active) or disabled (bypassed) states.
+// A mechanism for suppression of artifacts caused by abrupt coefficient changes
+// is implemented: normally, when the enable(), disable() and setCoefs() methods
+// are called without the immediate flag set, the filter smoothly transitions
+// from its current state to the desired state.
+class AudioBiquadFilter {
+public:
+ // Max number of channels (can be changed here, and everything should work).
+ static const int MAX_CHANNELS = 2;
+ // Number of coefficients.
+ static const int NUM_COEFS = 5;
+
+ // Constructor.
+ // nChannels Number of input/output channels.
+ // sampleRate Sample rate, in Hz.
+ AudioBiquadFilter(int nChannels, int sampleRate);
+
+ // Reconfiguration of the filter. Implies clear().
+ // nChannels Number of input/output channels.
+ // sampleRate Sample rate, in Hz.
+ void configure(int nChannels, int sampleRate);
+
+ // Resets the internal state of the filter.
+ // Coefficients are reset to identity, state becomes disabled. This change
+ // happens immediately and might cause discontinuities in the output.
+ // Delay lines are not cleared.
+ void reset();
+
+ // Clears the delay lines.
+ // This change happens immediately and might cause discontinuities in the
+ // output.
+ void clear();
+
+ // Sets the coefficients.
+ // If called when filter is disabled, will have no immediate effect, but the
+ // new coefficients will be set and used next time the filter is enabled.
+ // coefs The new coefficients.
+ // immediate If true, transitions to new coefficients smoothly, without
+ // introducing discontinuities in the output. Otherwise,
+ // transitions immediately.
+ void setCoefs(const audio_coef_t coefs[NUM_COEFS], bool immediate = false);
+
+ // Process a buffer of data. Always processes frameCount multi-channel
+ // samples. Processing can be done in-place, by passing the same buffer as
+ // both arguments.
+ // in The input buffer. Should be of size frameCount * nChannels.
+ // out The output buffer. Should be of size frameCount * nChannels.
+ // frameCount Number of multi-channel samples to process.
+ void process(const audio_sample_t in[], audio_sample_t out[],
+ int frameCount);
+
+ // Enables (activates) the filter.
+ // immediate If true, transitions to new state smoothly, without
+ // introducing discontinuities in the output. Otherwise,
+ // transitions immediately.
+ void enable(bool immediate = false);
+
+ // Disables (bypasses) the filter.
+ // immediate If true, transitions to new state smoothly, without
+ // introducing discontinuities in the output. Otherwise,
+ // transitions immediately.
+ void disable(bool immediate = false);
+
+private:
+ // A prototype of the actual processing function. Has the same semantics as
+ // the process() method.
+ typedef void (AudioBiquadFilter::*process_func)(const audio_sample_t[],
+ audio_sample_t[],
+ int frameCount);
+
+ // The maximum rate of coefficient change, measured in coefficient units per
+ // second.
+ static const audio_coef_t MAX_DELTA_PER_SEC = 2000;
+
+ // Coefficients of identity transformation.
+ static const audio_coef_t IDENTITY_COEFS[NUM_COEFS];
+
+ // Filter state.
+ enum state_t {
+ // Bypass.
+ STATE_BYPASS = 0x01,
+ // In the process of smooth transition to bypass state.
+ STATE_TRANSITION_TO_BYPASS = 0x02,
+ // In the process of smooth transition to normal (enabled) state.
+ STATE_TRANSITION_TO_NORMAL = 0x04,
+ // In normal (enabled) state.
+ STATE_NORMAL = 0x05,
+ // A bit-mask for determining whether the filter is enabled or disabled
+ // in the eyes of the client.
+ STATE_ENABLED_MASK = 0x04
+ };
+
+ // Number of channels.
+ int mNumChannels;
+ // Current state.
+ state_t mState;
+ // Maximum coefficient delta per sample.
+ audio_coef_t mMaxDelta;
+
+ // A bit-mask designating for which coefficients the current value is not
+ // necessarily identical to the target value (since we're in transition
+ // state).
+ uint32_t mCoefDirtyBits;
+ // The current coefficients.
+ audio_coef_t mCoefs[NUM_COEFS];
+ // The target coefficients. Will not be identical to mCoefs if we are in a
+ // transition state.
+ audio_coef_t mTargetCoefs[NUM_COEFS];
+
+ // The delay lines.
+ audio_sample_t mDelays[MAX_CHANNELS][4];
+
+ // Current processing function (determines according to current state and
+ // number of channels).
+ process_func mCurProcessFunc;
+
+ // Sets a new state. Updates the processing function accordingly, and sets
+ // the dirty bits if changing to a transition state.
+ void setState(state_t state);
+
+ // In a transition state, modifies the current coefs towards the passed
+ // coefs, while keeping a smooth change rate. Whenever a coef reaches its
+ // target value, the dirty bit is cleared. If all are clear, the function
+ // returns true, and we can then change to our target state.
+ bool updateCoefs(const audio_coef_t coefs[NUM_COEFS], int frameCount);
+
+ // Processing function when in disabled state.
+ void process_bypass(const audio_sample_t * in, audio_sample_t * out,
+ int frameCount);
+ // Processing function when in normal state, mono.
+ void process_normal_mono(const audio_sample_t * in, audio_sample_t * out,
+ int frameCount);
+ // Processing function when transitioning to normal state, mono.
+ void process_transition_normal_mono(const audio_sample_t * in,
+ audio_sample_t * out, int frameCount);
+ // Processing function when transitioning to bypass state, mono.
+ void process_transition_bypass_mono(const audio_sample_t * in,
+ audio_sample_t * out, int frameCount);
+ // Processing function when in normal state, multi-channel.
+ void process_normal_multi(const audio_sample_t * in, audio_sample_t * out,
+ int frameCount);
+ // Processing function when transitioning to normal state, multi-channel.
+ void process_transition_normal_multi(const audio_sample_t * in,
+ audio_sample_t * out, int frameCount);
+ // Processing function when transitioning to bypass state, multi-channel.
+ void process_transition_bypass_multi(const audio_sample_t * in,
+ audio_sample_t * out, int frameCount);
+};
+}
+
+#endif // ANDROID_AUDIO_BIQUAD_FILTER_H
diff --git a/media/libeffects/testlibs/AudioCoefInterpolator.cpp b/media/libeffects/testlibs/AudioCoefInterpolator.cpp
new file mode 100644
index 0000000..039ab9f
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCoefInterpolator.cpp
@@ -0,0 +1,84 @@
+/* //device/servers/AudioFlinger/AudioCoefInterpolator.cpp
+ **
+ ** Copyright 2008, 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.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <string.h>
+#include "AudioCoefInterpolator.h"
+
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+
+AudioCoefInterpolator::AudioCoefInterpolator(size_t nInDims,
+ const size_t inDims[],
+ size_t nOutDims,
+ const audio_coef_t * table) {
+ mNumInDims = nInDims;
+ memcpy(mInDims, inDims, nInDims * sizeof(size_t));
+ mNumOutDims = nOutDims;
+ mTable = table;
+ // Initialize offsets array
+ size_t dim = nInDims - 1;
+ mInDimOffsets[nInDims - 1] = nOutDims;
+ while (dim-- > 0) {
+ mInDimOffsets[dim] = mInDimOffsets[dim + 1] * mInDims[dim + 1];
+ }
+}
+
+void AudioCoefInterpolator::getCoef(const int intCoord[], uint32_t fracCoord[],
+ audio_coef_t out[]) {
+ size_t index = 0;
+ size_t dim = mNumInDims;
+ while (dim-- > 0) {
+ if (UNLIKELY(intCoord[dim] < 0)) {
+ fracCoord[dim] = 0;
+ } else if (UNLIKELY(intCoord[dim] >= (int)mInDims[dim] - 1)) {
+ fracCoord[dim] = 0;
+ index += mInDimOffsets[dim] * (mInDims[dim] - 1);
+ } else {
+ index += mInDimOffsets[dim] * intCoord[dim];
+ }
+ }
+ getCoefRecurse(index, fracCoord, out, 0);
+}
+
+void AudioCoefInterpolator::getCoefRecurse(size_t index,
+ const uint32_t fracCoord[],
+ audio_coef_t out[], size_t dim) {
+ if (dim == mNumInDims) {
+ memcpy(out, mTable + index, mNumOutDims * sizeof(audio_coef_t));
+ } else {
+ getCoefRecurse(index, fracCoord, out, dim + 1);
+ if (LIKELY(fracCoord != 0)) {
+ audio_coef_t tempCoef[MAX_OUT_DIMS];
+ getCoefRecurse(index + mInDimOffsets[dim], fracCoord, tempCoef,
+ dim + 1);
+ size_t d = mNumOutDims;
+ while (d-- > 0) {
+ out[d] = interp(out[d], tempCoef[d], fracCoord[dim]);
+ }
+ }
+ }
+}
+
+audio_coef_t AudioCoefInterpolator::interp(audio_coef_t lo, audio_coef_t hi,
+ uint32_t frac) {
+ int64_t delta = static_cast<int64_t>(hi-lo) * frac;
+ return lo + static_cast<audio_coef_t> (delta >> 32);
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioCoefInterpolator.h b/media/libeffects/testlibs/AudioCoefInterpolator.h
new file mode 100644
index 0000000..13e5697
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCoefInterpolator.h
@@ -0,0 +1,98 @@
+/* //device/include/server/AudioFlinger/AudioCoefInterpolator.h
+ **
+ ** Copyright 2007, 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.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_COEF_INTERPOLATOR_H
+#define ANDROID_AUDIO_COEF_INTERPOLATOR_H
+
+#include "AudioCommon.h"
+
+namespace android {
+
+// A helper class for linear interpolation of N-D -> M-D coefficient tables.
+// This class provides support for out-of-range indexes.
+// Details:
+// The purpose is efficient approximation of a N-dimensional vector to
+// M-dimensional function. The approximation is based on a table of output
+// values on a uniform grid of the input values. Values not on the grid are
+// linearly interpolated.
+// Access to values are done by specifying input values in table index units,
+// having an integer and a fractional part, e.g. retrieving a value from index
+// 1.4 will result in linear interpolation between index 1 and index 2.
+class AudioCoefInterpolator {
+public:
+ // Constructor.
+ // nInDims Number of input dimensions (limited to MAX_IN_DIMS).
+ // inDims An array of size nInDims with the size of the table on each
+ // respective dimension.
+ // nOutDims Number of output dimensions (limited to MAX_OUT_DIMS).
+ // table The coefficient table. Should be of size:
+ // inDims[0]*inDims[1]*...*inDims[nInDims-1]*nOutDims, where
+ // func([i,j,k]) = table(i,j,k,:)
+ AudioCoefInterpolator(size_t nInDims, const size_t inDims[],
+ size_t nOutDims, const audio_coef_t * table);
+
+ // Get the value of the approximated function at a given point.
+ // intCoord The integer part of the input value. Should be an array of
+ // size nInDims.
+ // fracCoord The fractional part of the input value. Should be an array
+ // of size nInDims. This value is in 32-bit precision.
+ // out An array for the output value. Should be of size nOutDims.
+ void getCoef(const int intCoord[], uint32_t fracCoord[], audio_coef_t out[]);
+
+private:
+ // Maximum allowed number of input dimensions.
+ static const size_t MAX_IN_DIMS = 8;
+ // Maximum allowed number of output dimensions.
+ static const size_t MAX_OUT_DIMS = 8;
+
+ // Number of input dimensions.
+ size_t mNumInDims;
+ // Number of input dimensions.
+ size_t mInDims[MAX_IN_DIMS];
+ // The offset between two consecutive indexes of each dimension. This is in
+ // fact a cumulative product of mInDims (done in reverse).
+ size_t mInDimOffsets[MAX_IN_DIMS];
+ // Number of output dimensions.
+ size_t mNumOutDims;
+ // The coefficient table.
+ const audio_coef_t * mTable;
+
+ // A recursive function for getting an interpolated coefficient value.
+ // The recursion depth is the number of input dimensions.
+ // At each step, we fetch two interpolated values of the current dimension,
+ // by two recursive calls to this method for the next dimensions. We then
+ // linearly interpolate these values over the current dimension.
+ // index The linear integer index of the value we need to interpolate.
+ // fracCoord A vector of fractional coordinates for each of the input
+ // dimensions.
+ // out Where the output should be written. Needs to be of size
+ // mNumOutDims.
+ // dim The input dimensions we are currently interpolating. This
+ // value will be increased on recursive calls.
+ void getCoefRecurse(size_t index, const uint32_t fracCoord[],
+ audio_coef_t out[], size_t dim);
+
+ // Scalar interpolation of two data points.
+ // lo The first data point.
+ // hi The second data point.
+ // frac A 32-bit fraction designating the weight of the second point.
+ static audio_coef_t interp(audio_coef_t lo, audio_coef_t hi, uint32_t frac);
+};
+
+}
+
+#endif // ANDROID_AUDIO_COEF_INTERPOLATOR_H
diff --git a/media/libeffects/testlibs/AudioCommon.h b/media/libeffects/testlibs/AudioCommon.h
new file mode 100644
index 0000000..444f93a
--- /dev/null
+++ b/media/libeffects/testlibs/AudioCommon.h
@@ -0,0 +1,92 @@
+/*
+**
+** Copyright 2009, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_AUDIO_COMMON_H
+#define ANDROID_AUDIO_COMMON_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+namespace android {
+
+// Audio coefficient type.
+typedef int32_t audio_coef_t;
+// Audio sample type.
+typedef int32_t audio_sample_t;
+// Accumulator type for coef x sample.
+typedef int64_t audio_coef_sample_acc_t;
+
+// Number of fraction bits for audio coefficient.
+static const int AUDIO_COEF_PRECISION = 24;
+// Audio coefficient with the value of 1.0
+static const audio_coef_t AUDIO_COEF_ONE = 1 << AUDIO_COEF_PRECISION;
+// Audio coefficient with the value of 0.5
+static const audio_coef_t AUDIO_COEF_HALF = 1 << (AUDIO_COEF_PRECISION - 1);
+// Number of fraction bits for audio sample.
+static const int AUDIO_SAMPLE_PRECISION = 24;
+// Audio sample with the value of 1.0
+static const audio_sample_t AUDIO_SAMPLE_ONE = 1 << AUDIO_SAMPLE_PRECISION;
+
+// TODO: These are just temporary naive implementations of the necessary
+// arithmetic operations needed for the filter. They should be moved to a more
+// generic location and implemented more efficiently.
+
+// Multiply a sample by a coefficient to return an accumulator.
+inline audio_coef_sample_acc_t mul_coef_sample(audio_coef_t x, audio_sample_t y) {
+ return ((audio_coef_sample_acc_t) (x)) * y;
+}
+
+// Multiply and accumulate sample by a coefficient to return an accumulator.
+inline audio_coef_sample_acc_t mac_coef_sample(audio_coef_t x, audio_sample_t y, audio_coef_sample_acc_t acc) {
+ return acc + ((audio_coef_sample_acc_t) (x)) * y;
+}
+
+// Convert a sample-coefficient accumulator to a sample.
+inline audio_sample_t coef_sample_acc_to_sample(audio_coef_sample_acc_t acc) {
+ if (acc < 0) {
+ acc += AUDIO_COEF_ONE - 1;
+ }
+ return (audio_sample_t) (acc >> AUDIO_COEF_PRECISION);
+}
+
+// Convert a S15 sample to audio_sample_t
+inline audio_sample_t s15_to_audio_sample_t(int16_t s15) {
+ return audio_sample_t(s15) << 9;
+}
+
+// Convert a audio_sample_t sample to S15 (no clipping)
+inline int16_t audio_sample_t_to_s15(audio_sample_t sample) {
+ return int16_t((sample + (1 << 8)) >> 9);
+}
+
+// Convert a audio_sample_t sample to S15 (with clipping)
+inline int16_t audio_sample_t_to_s15_clip(audio_sample_t sample) {
+ // TODO: optimize for targets supporting this as an atomic operation.
+ if (__builtin_expect(sample >= (0x7FFF << 9), 0)) {
+ return 0x7FFF;
+ } else if (__builtin_expect(sample <= -(0x8000 << 9), 0)) {
+ return 0x8000;
+ } else {
+ return audio_sample_t_to_s15(sample);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+}
+
+#endif // ANDROID_AUDIO_COMMON_H
diff --git a/media/libeffects/testlibs/AudioEqualizer.cpp b/media/libeffects/testlibs/AudioEqualizer.cpp
new file mode 100644
index 0000000..44c9476
--- /dev/null
+++ b/media/libeffects/testlibs/AudioEqualizer.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2009, 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioEqualizer"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <new>
+#include <utils/Log.h>
+
+#include "AudioEqualizer.h"
+#include "AudioPeakingFilter.h"
+#include "AudioShelvingFilter.h"
+#include "EffectsMath.h"
+
+namespace android {
+
+size_t AudioEqualizer::GetInstanceSize(int nBands) {
+ assert(nBands >= 2);
+ return sizeof(AudioEqualizer) +
+ sizeof(AudioShelvingFilter) * 2 +
+ sizeof(AudioPeakingFilter) * (nBands - 2);
+}
+
+AudioEqualizer * AudioEqualizer::CreateInstance(void * pMem, int nBands,
+ int nChannels, int sampleRate,
+ const PresetConfig * presets,
+ int nPresets) {
+ LOGV("AudioEqualizer::CreateInstance(pMem=%p, nBands=%d, nChannels=%d, "
+ "sampleRate=%d, nPresets=%d)",
+ pMem, nBands, nChannels, sampleRate, nPresets);
+ assert(nBands >= 2);
+ bool ownMem = false;
+ if (pMem == NULL) {
+ pMem = malloc(GetInstanceSize(nBands));
+ if (pMem == NULL) {
+ return NULL;
+ }
+ ownMem = true;
+ }
+ return new (pMem) AudioEqualizer(pMem, nBands, nChannels, sampleRate,
+ ownMem, presets, nPresets);
+}
+
+void AudioEqualizer::configure(int nChannels, int sampleRate) {
+ LOGV("AudioEqualizer::configure(nChannels=%d, sampleRate=%d)", nChannels,
+ sampleRate);
+ mpLowShelf->configure(nChannels, sampleRate);
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].configure(nChannels, sampleRate);
+ }
+ mpHighShelf->configure(nChannels, sampleRate);
+}
+
+void AudioEqualizer::clear() {
+ LOGV("AudioEqualizer::clear()");
+ mpLowShelf->clear();
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].clear();
+ }
+ mpHighShelf->clear();
+}
+
+void AudioEqualizer::free() {
+ LOGV("AudioEqualizer::free()");
+ if (mpMem != NULL) {
+ ::free(mpMem);
+ }
+}
+
+void AudioEqualizer::reset() {
+ LOGV("AudioEqualizer::reset()");
+ const int32_t bottom = Effects_log2(kMinFreq);
+ const int32_t top = Effects_log2(mSampleRate * 500);
+ const int32_t jump = (top - bottom) / (mNumPeaking + 2);
+ int32_t centerFreq = bottom + jump/2;
+
+ mpLowShelf->reset();
+ mpLowShelf->setFrequency(Effects_exp2(centerFreq));
+ centerFreq += jump;
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].reset();
+ mpPeakingFilters[i].setFrequency(Effects_exp2(centerFreq));
+ centerFreq += jump;
+ }
+ mpHighShelf->reset();
+ mpHighShelf->setFrequency(Effects_exp2(centerFreq));
+ commit(true);
+ mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setGain(int band, int32_t millibel) {
+ LOGV("AudioEqualizer::setGain(band=%d, millibel=%d)", band, millibel);
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band == 0) {
+ mpLowShelf->setGain(millibel);
+ } else if (band == mNumPeaking + 1) {
+ mpHighShelf->setGain(millibel);
+ } else {
+ mpPeakingFilters[band - 1].setGain(millibel);
+ }
+ mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setFrequency(int band, uint32_t millihertz) {
+ LOGV("AudioEqualizer::setFrequency(band=%d, millihertz=%d)", band,
+ millihertz);
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band == 0) {
+ mpLowShelf->setFrequency(millihertz);
+ } else if (band == mNumPeaking + 1) {
+ mpHighShelf->setFrequency(millihertz);
+ } else {
+ mpPeakingFilters[band - 1].setFrequency(millihertz);
+ }
+ mCurPreset = PRESET_CUSTOM;
+}
+
+void AudioEqualizer::setBandwidth(int band, uint32_t cents) {
+ LOGV("AudioEqualizer::setBandwidth(band=%d, cents=%d)", band, cents);
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band > 0 && band < mNumPeaking + 1) {
+ mpPeakingFilters[band - 1].setBandwidth(cents);
+ mCurPreset = PRESET_CUSTOM;
+ }
+}
+
+int32_t AudioEqualizer::getGain(int band) const {
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band == 0) {
+ return mpLowShelf->getGain();
+ } else if (band == mNumPeaking + 1) {
+ return mpHighShelf->getGain();
+ } else {
+ return mpPeakingFilters[band - 1].getGain();
+ }
+}
+
+uint32_t AudioEqualizer::getFrequency(int band) const {
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band == 0) {
+ return mpLowShelf->getFrequency();
+ } else if (band == mNumPeaking + 1) {
+ return mpHighShelf->getFrequency();
+ } else {
+ return mpPeakingFilters[band - 1].getFrequency();
+ }
+}
+
+uint32_t AudioEqualizer::getBandwidth(int band) const {
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band == 0 || band == mNumPeaking + 1) {
+ return 0;
+ } else {
+ return mpPeakingFilters[band - 1].getBandwidth();
+ }
+}
+
+void AudioEqualizer::getBandRange(int band, uint32_t & low,
+ uint32_t & high) const {
+ assert(band >= 0 && band < mNumPeaking + 2);
+ if (band == 0) {
+ low = 0;
+ high = mpLowShelf->getFrequency();
+ } else if (band == mNumPeaking + 1) {
+ low = mpHighShelf->getFrequency();
+ high = mSampleRate * 500;
+ } else {
+ mpPeakingFilters[band - 1].getBandRange(low, high);
+ }
+}
+
+const char * AudioEqualizer::getPresetName(int preset) const {
+ assert(preset < mNumPresets && preset >= PRESET_CUSTOM);
+ if (preset == PRESET_CUSTOM) {
+ return "Custom";
+ } else {
+ return mpPresets[preset].name;
+ }
+}
+
+int AudioEqualizer::getNumPresets() const {
+ return mNumPresets;
+}
+
+int AudioEqualizer::getPreset() const {
+ return mCurPreset;
+}
+
+void AudioEqualizer::setPreset(int preset) {
+ LOGV("AudioEqualizer::setPreset(preset=%d)", preset);
+ assert(preset < mNumPresets && preset >= 0);
+ const PresetConfig &presetCfg = mpPresets[preset];
+ for (int band = 0; band < (mNumPeaking + 2); ++band) {
+ const BandConfig & bandCfg = presetCfg.bandConfigs[band];
+ setGain(band, bandCfg.gain);
+ setFrequency(band, bandCfg.freq);
+ setBandwidth(band, bandCfg.bandwidth);
+ }
+ mCurPreset = preset;
+}
+
+void AudioEqualizer::commit(bool immediate) {
+ LOGV("AudioEqualizer::commit(immediate=%d)", immediate);
+ mpLowShelf->commit(immediate);
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].commit(immediate);
+ }
+ mpHighShelf->commit(immediate);
+}
+
+void AudioEqualizer::process(const audio_sample_t * pIn,
+ audio_sample_t * pOut,
+ int frameCount) {
+// LOGV("AudioEqualizer::process(frameCount=%d)", frameCount);
+ mpLowShelf->process(pIn, pOut, frameCount);
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].process(pIn, pOut, frameCount);
+ }
+ mpHighShelf->process(pIn, pOut, frameCount);
+}
+
+void AudioEqualizer::enable(bool immediate) {
+ LOGV("AudioEqualizer::enable(immediate=%d)", immediate);
+ mpLowShelf->enable(immediate);
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].enable(immediate);
+ }
+ mpHighShelf->enable(immediate);
+}
+
+void AudioEqualizer::disable(bool immediate) {
+ LOGV("AudioEqualizer::disable(immediate=%d)", immediate);
+ mpLowShelf->disable(immediate);
+ for (int i = 0; i < mNumPeaking; ++i) {
+ mpPeakingFilters[i].disable(immediate);
+ }
+ mpHighShelf->disable(immediate);
+}
+
+int AudioEqualizer::getMostRelevantBand(uint32_t targetFreq) const {
+ // First, find the two bands that the target frequency is between.
+ uint32_t low = mpLowShelf->getFrequency();
+ if (targetFreq <= low) {
+ return 0;
+ }
+ uint32_t high = mpHighShelf->getFrequency();
+ if (targetFreq >= high) {
+ return mNumPeaking + 1;
+ }
+ int band = mNumPeaking;
+ for (int i = 0; i < mNumPeaking; ++i) {
+ uint32_t freq = mpPeakingFilters[i].getFrequency();
+ if (freq >= targetFreq) {
+ high = freq;
+ band = i;
+ break;
+ }
+ low = freq;
+ }
+ // Now, low is right below the target and high is right above. See which one
+ // is closer on a log scale.
+ low = Effects_log2(low);
+ high = Effects_log2(high);
+ targetFreq = Effects_log2(targetFreq);
+ if (high - targetFreq < targetFreq - low) {
+ return band + 1;
+ } else {
+ return band;
+ }
+}
+
+
+AudioEqualizer::AudioEqualizer(void * pMem, int nBands, int nChannels,
+ int sampleRate, bool ownMem,
+ const PresetConfig * presets, int nPresets)
+ : mSampleRate(sampleRate)
+ , mpPresets(presets)
+ , mNumPresets(nPresets) {
+ assert(pMem != NULL);
+ assert(nPresets == 0 || nPresets > 0 && presets != NULL);
+ mpMem = ownMem ? pMem : NULL;
+
+ pMem = (char *) pMem + sizeof(AudioEqualizer);
+ mpLowShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kLowShelf,
+ nChannels, sampleRate);
+ pMem = (char *) pMem + sizeof(AudioShelvingFilter);
+ mpHighShelf = new (pMem) AudioShelvingFilter(AudioShelvingFilter::kHighShelf,
+ nChannels, sampleRate);
+ pMem = (char *) pMem + sizeof(AudioShelvingFilter);
+ mNumPeaking = nBands - 2;
+ if (mNumPeaking > 0) {
+ mpPeakingFilters = reinterpret_cast<AudioPeakingFilter *>(pMem);
+ for (int i = 0; i < mNumPeaking; ++i) {
+ new (&mpPeakingFilters[i]) AudioPeakingFilter(nChannels,
+ sampleRate);
+ }
+ }
+ reset();
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioEqualizer.h b/media/libeffects/testlibs/AudioEqualizer.h
new file mode 100644
index 0000000..4028462
--- /dev/null
+++ b/media/libeffects/testlibs/AudioEqualizer.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2009, 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIOEQUALIZER_H_
+#define AUDIOEQUALIZER_H_
+
+#include "AudioCommon.h"
+
+namespace android {
+
+class AudioShelvingFilter;
+class AudioPeakingFilter;
+
+// A parametric audio equalizer. Supports an arbitrary number of bands and
+// presets.
+// The EQ is composed of a low-shelf, zero or more peaking filters and a high
+// shelf, where each band has frequency and gain controls, and the peaking
+// filters have an additional bandwidth control.
+class AudioEqualizer {
+public:
+ // Configuration of a single band.
+ struct BandConfig {
+ // Gain in millibel.
+ int32_t gain;
+ // Frequency in millihertz.
+ uint32_t freq;
+ // Bandwidth in cents (ignored on shelving filters).
+ uint32_t bandwidth;
+ };
+
+ // Preset configuration.
+ struct PresetConfig {
+ // Human-readable name.
+ const char * name;
+ // An array of size nBands where each element is a configuration for the
+ // corresponding band.
+ const BandConfig * bandConfigs;
+ };
+
+ // This value is used when requesting current preset, and EQ is not using a
+ // preset.
+ static const int PRESET_CUSTOM = -1;
+
+ // Get the required memory size for an instance of this class.
+ // nBands Number of bands required in the instance.
+ static size_t GetInstanceSize(int nBands);
+
+ // Create an instance of this class.
+ // If succeeds, a respective call is expected to freeInstance(), regardless
+ // of who owns the context memory.
+ // pMem A memory buffer of at least the size returned by
+ // GetInstanceSize(), where the instance context is to be
+ // stored. If NULL, it will be automatically allocated (using
+ // malloc).
+ // nBands Number of bands. Must be >= 2.
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ // presets The presets configuration. May be NULL, but in that case the
+ // client is required not to call preset-related functions.
+ // This array is owned by the client and is not copied. It
+ // must be kept valid by the client as long as the instance is
+ // alive.
+ // nPresets Number of elements in the presets array.
+ // returns The instance if success. NULL if pMem is NULL and allocation
+ // failed.
+ static AudioEqualizer * CreateInstance(void * pMem, int nBands,
+ int nChannels,
+ int sampleRate,
+ const PresetConfig * presets,
+ int nPresets);
+
+ // Reconfiguration of the filter. Changes input/output format, but does not
+ // alter current parameter values. Causes reset of the delay lines.
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ void configure(int nChannels, int sampleRate);
+
+ // Resets the filter parameters to the following values:
+ // frequency: 0
+ // gain: 0
+ // bandwidth: 1200 cents.
+ // It also disables the filter. Does not clear the delay lines.
+ void reset();
+
+ // Clears delay lines. Does not alter parameter values.
+ void clear();
+
+ // Frees the object. Will free the memory if the object owned it, i.e. if
+ // a NULL pointer was passed to CreateInstance as pMem.
+ void free();
+
+ // Sets gain value. Actual change will only take place upon commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // band The band to set the gain for.
+ // millibel Gain value in millibel (1/100 of decibel).
+ void setGain(int band, int32_t millibel);
+
+ // Gets gain of a certain band. This is always the last value set (or
+ // default value after reset).
+ // band The band to get the gain for.
+ // returns Gain value in millibel (1/100 of decibel).
+ int32_t getGain(int band) const;
+
+ // Sets cutoff frequency value. Actual change will only take place upon
+ // commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // band The band to set the frequency for.
+ // millihertz Frequency value in mHz.
+ void setFrequency(int band, uint32_t millihertz);
+
+ // Gets frequency of a certain band. This is always the last value set (or
+ // default value after reset).
+ // band The band to get the frequency for.
+ // returns Frequency value in mHz.
+ uint32_t getFrequency(int band) const;
+
+ // Sets bandwidth value. Actual change will only take place upon commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // If called on the first or last band, this call is ignored.
+ // band The band to set the frequency for.
+ // cents Bandwidth value in cents (1/1200 octave).
+ void setBandwidth(int band, uint32_t cents);
+
+ // Gets bandwidth of a certain band. This is always the last value set (or
+ // default value after reset). For the first and last bands, 0 is always
+ // returned.
+ // band The band to get the bandwidth for.
+ // returns Bandwidth value in cents (1/1200 octave).
+ uint32_t getBandwidth(int band) const;
+
+ // Gets lower and upper boundaries of a band.
+ // For the low shelf, the low bound is 0 and the high bound is the band
+ // frequency.
+ // For the high shelf, the low bound is the band frequency and the high
+ // bound is Nyquist.
+ // For the peaking filters, they are the gain[dB]/2 points.
+ void getBandRange(int band, uint32_t & low, uint32_t & high) const;
+
+ // Gets a human-readable name for a preset ID. Will return "Custom" if
+ // PRESET_CUSTOM is passed.
+ // preset The preset ID. Must be less than number of presets.
+ const char * getPresetName(int preset) const;
+
+ // Gets the number of presets.
+ int getNumPresets() const;
+
+ // Gets the currently set preset ID.
+ // Will return PRESET_CUSTOM in case the EQ parameters have been modified
+ // manually since a preset was set.
+ int getPreset() const;
+
+ // Sets the current preset by ID.
+ // All the band parameters will be overridden.
+ // Change will not be applied until commit() is called.
+ // preset The preset ID. Must be less than number of presets.
+ // PRESET_CUSTOM is NOT a valid value here.
+ void setPreset(int preset);
+
+ // Applies all parameter changes done to this point in time.
+ // If the filter is disabled, the new parameters will take place when it is
+ // enabled again. Does not introduce artifacts, unless immediate is set.
+ // immediate Whether to apply change abruptly (ignored if filter is
+ // disabled).
+ void commit(bool immediate = false);
+
+ // Process a buffer of input data. The input and output should contain
+ // frameCount * nChannels interlaced samples. Processing can be done
+ // in-place, by passing the same buffer as both arguments.
+ // pIn Input buffer.
+ // pOut Output buffer.
+ // frameCount Number of frames to produce on each call to process().
+ void process(const audio_sample_t * pIn, audio_sample_t * pOut,
+ int frameCount);
+
+ // Enables the filter, so it would start processing input. Does not
+ // introduce artifacts, unless immediate is set.
+ // immediate Whether to apply change abruptly.
+ void enable(bool immediate = false);
+
+ // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+ // immediate is set.
+ // immediate Whether to apply change abruptly.
+ void disable(bool immediate = false);
+
+ // Returns the band with the maximum influence on a given frequency.
+ // Result is unaffected by whether EQ is enabled or not, or by whether
+ // changes have been committed or not.
+ // targetFreq The target frequency, in millihertz.
+ int getMostRelevantBand(uint32_t targetFreq) const;
+
+private:
+ // Bottom frequency, in mHz.
+ static const int kMinFreq = 20000;
+ // Sample rate, in Hz.
+ int mSampleRate;
+ // Number of peaking filters. Total number of bands is +2.
+ int mNumPeaking;
+ // Preset configurations.
+ const PresetConfig * mpPresets;
+ // Number of elements in mpPresets;
+ int mNumPresets;
+ // Current preset.
+ int mCurPreset;
+
+ // Memory space to free when instance is deleted, or NULL if no memory is
+ // owned.
+ void * mpMem;
+ // The low-shelving filter.
+ AudioShelvingFilter * mpLowShelf;
+ // The high-shelving filter.
+ AudioShelvingFilter * mpHighShelf;
+ // An array of size mNumPeaking of peaking filters.
+ AudioPeakingFilter * mpPeakingFilters;
+
+ // Constructor. Resets the filter (see reset()). Must call init() doing
+ // anything else.
+ // pMem Memory buffer for bands.
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ // ownMem Whether pMem is owned by me.
+ // presets The presets configuration. May be NULL, but in that case the
+ // client is required not to call preset-related functions.
+ // This array is owned by the client and is not copied. It
+ // must be kept valid by the client as long as the instance is
+ // alive.
+ // nPresets Number of elements in the presets array.
+ AudioEqualizer(void * pMem, int nBands, int nChannels, int sampleRate,
+ bool ownMem, const PresetConfig * presets, int nPresets);
+};
+
+}
+
+#endif // AUDIOEQUALIZER_H_
diff --git a/media/libeffects/testlibs/AudioFormatAdapter.h b/media/libeffects/testlibs/AudioFormatAdapter.h
new file mode 100644
index 0000000..d93ebe9
--- /dev/null
+++ b/media/libeffects/testlibs/AudioFormatAdapter.h
@@ -0,0 +1,184 @@
+/* /android/src/frameworks/base/media/libeffects/AudioFormatAdapter.h
+**
+** Copyright 2009, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef AUDIOFORMATADAPTER_H_
+#define AUDIOFORMATADAPTER_H_
+
+#include <media/EffectApi.h>
+
+
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+
+namespace android {
+
+// An adapter for an audio processor working on audio_sample_t samples with a
+// buffer override behavior to arbitrary sample formats and buffer behaviors.
+// The adapter may work on any processing class which has a processing function
+// with the following signature:
+// void process(const audio_sample_t * pIn,
+// audio_sample_t * pOut,
+// int frameCount);
+// It is assumed that the underlying processor works in S7.24 format and an
+// overwrite behavior.
+//
+// Usage is simple: just work with the processor normally, but instead of
+// calling its process() function directly, work with the process() function of
+// the adapter.
+// The adapter supports re-configuration to a different format on the fly.
+//
+// T The processor class.
+// bufSize The maximum number of samples (single channel) to process on a
+// single call to the underlying processor. Setting this to a small
+// number will save a little memory, but will cost function call
+// overhead, resulting from multiple calls to the underlying process()
+// per a single call to this class's process().
+template<class T, size_t bufSize>
+class AudioFormatAdapter {
+public:
+ // Configure the adapter.
+ // processor The underlying audio processor.
+ // nChannels Number of input and output channels. The adapter does not do
+ // channel conversion - this parameter must be in sync with the
+ // actual processor.
+ // pcmFormat The desired input/output sample format.
+ // behavior The desired behavior (overwrite or accumulate).
+ void configure(T & processor, int nChannels, uint8_t pcmFormat,
+ uint32_t behavior) {
+ mpProcessor = &processor;
+ mNumChannels = nChannels;
+ mPcmFormat = pcmFormat;
+ mBehavior = behavior;
+ mMaxSamplesPerCall = bufSize / nChannels;
+ }
+
+ // Process a block of samples.
+ // pIn A buffer of samples with the format specified on
+ // configure().
+ // pOut A buffer of samples with the format specified on
+ // configure(). May be the same as pIn.
+ // numSamples The number of multi-channel samples to process.
+ void process(const void * pIn, void * pOut, uint32_t numSamples) {
+ while (numSamples > 0) {
+ uint32_t numSamplesIter = min(numSamples, mMaxSamplesPerCall);
+ uint32_t nSamplesChannels = numSamplesIter * mNumChannels;
+ if (mPcmFormat == SAMPLE_FORMAT_PCM_S7_24) {
+ if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
+ mpProcessor->process(
+ reinterpret_cast<const audio_sample_t *> (pIn),
+ reinterpret_cast<audio_sample_t *> (pOut),
+ numSamplesIter);
+ } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ mpProcessor->process(
+ reinterpret_cast<const audio_sample_t *> (pIn),
+ mBuffer, numSamplesIter);
+ MixOutput(pOut, numSamplesIter);
+ } else {
+ assert(false);
+ }
+ pIn = reinterpret_cast<const audio_sample_t *> (pIn)
+ + nSamplesChannels;
+ pOut = reinterpret_cast<audio_sample_t *> (pOut)
+ + nSamplesChannels;
+ } else {
+ ConvertInput(pIn, nSamplesChannels);
+ mpProcessor->process(mBuffer, mBuffer, numSamplesIter);
+ ConvertOutput(pOut, nSamplesChannels);
+ }
+ numSamples -= numSamplesIter;
+ }
+ }
+
+private:
+ // The underlying processor.
+ T * mpProcessor;
+ // The number of input/output channels.
+ int mNumChannels;
+ // The desired PCM format.
+ uint8_t mPcmFormat;
+ // The desired buffer behavior.
+ uint32_t mBehavior;
+ // An intermediate buffer for processing.
+ audio_sample_t mBuffer[bufSize];
+ // The buffer size, divided by the number of channels - represents the
+ // maximum number of multi-channel samples that can be stored in the
+ // intermediate buffer.
+ size_t mMaxSamplesPerCall;
+
+ // Converts a buffer of input samples to audio_sample_t format.
+ // Output is written to the intermediate buffer.
+ // pIn The input buffer with the format designated in configure().
+ // When function exist will point to the next unread input
+ // sample.
+ // numSamples The number of single-channel samples to process.
+ void ConvertInput(const void *& pIn, uint32_t numSamples) {
+ if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) {
+ const int16_t * pIn16 = reinterpret_cast<const int16_t *>(pIn);
+ audio_sample_t * pOut = mBuffer;
+ while (numSamples-- > 0) {
+ *(pOut++) = s15_to_audio_sample_t(*(pIn16++));
+ }
+ pIn = pIn16;
+ } else {
+ assert(false);
+ }
+ }
+
+ // Converts audio_sample_t samples from the intermediate buffer to the
+ // output buffer, converting to the desired format and buffer behavior.
+ // pOut The buffer to write the output to.
+ // When function exist will point to the next output sample.
+ // numSamples The number of single-channel samples to process.
+ void ConvertOutput(void *& pOut, uint32_t numSamples) {
+ if (mPcmFormat == SAMPLE_FORMAT_PCM_S15) {
+ const audio_sample_t * pIn = mBuffer;
+ int16_t * pOut16 = reinterpret_cast<int16_t *>(pOut);
+ if (mBehavior == EFFECT_BUFFER_ACCESS_WRITE) {
+ while (numSamples-- > 0) {
+ *(pOut16++) = audio_sample_t_to_s15_clip(*(pIn++));
+ }
+ } else if (mBehavior == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ while (numSamples-- > 0) {
+ *(pOut16++) += audio_sample_t_to_s15_clip(*(pIn++));
+ }
+ } else {
+ assert(false);
+ }
+ pOut = pOut16;
+ } else {
+ assert(false);
+ }
+ }
+
+ // Accumulate data from the intermediate buffer to the output. Output is
+ // assumed to be of audio_sample_t type.
+ // pOut The buffer to mix the output to.
+ // When function exist will point to the next output sample.
+ // numSamples The number of single-channel samples to process.
+ void MixOutput(void *& pOut, uint32_t numSamples) {
+ const audio_sample_t * pIn = mBuffer;
+ audio_sample_t * pOut24 = reinterpret_cast<audio_sample_t *>(pOut);
+ numSamples *= mNumChannels;
+ while (numSamples-- > 0) {
+ *(pOut24++) += *(pIn++);
+ }
+ pOut = pOut24;
+ }
+};
+
+}
+
+#endif // AUDIOFORMATADAPTER_H_
diff --git a/media/libeffects/testlibs/AudioHighShelfFilterCoef.inl b/media/libeffects/testlibs/AudioHighShelfFilterCoef.inl
new file mode 100644
index 0000000..ebba139
--- /dev/null
+++ b/media/libeffects/testlibs/AudioHighShelfFilterCoef.inl
@@ -0,0 +1,225 @@
+13679,
+21575,
+8921,
+32315056,
+-15582015,
+26172,
+37678,
+14797,
+31891096,
+-15192527,
+51020,
+64449,
+23945,
+31322988,
+-14685186,
+101817,
+106144,
+37744,
+30562882,
+-14031372,
+208996,
+162163,
+58536,
+29548538,
+-13201017,
+442996,
+207459,
+93300,
+28200792,
+-12167331,
+971423,
+128786,
+169690,
+26422744,
+-10915428,
+2200461,
+-465686,
+394986,
+24103317,
+-9455862,
+5119991,
+-2777199,
+1147245,
+21129473,
+-7842294,
+12120379,
+-10198160,
+3631544,
+17411837,
+-6188384,
+28834234,
+-31647135,
+11337795,
+12924960,
+-4672638,
+68037766,
+-88974388,
+33477255,
+7752680,
+-3516098,
+157369944,
+-232063160,
+92282129,
+2113926,
+-2925624,
+353720112,
+-567427144,
+237164112,
+-3659993,
+-3019871,
+769091151,
+-1309871949,
+570539430,
+-9202114,
+-3779302,
+66791,
+121706,
+55888,
+30571245,
+-14038415,
+120426,
+212178,
+94820,
+29559679,
+-13209886,
+217130,
+365165,
+157610,
+28215554,
+-12178243,
+391489,
+617016,
+255010,
+26442131,
+-10928431,
+705862,
+1015147,
+398457,
+24128430,
+-9470680,
+1272682,
+1605251,
+596102,
+21161334,
+-7858153,
+2294668,
+2386833,
+848523,
+17451072,
+-6203880,
+4137327,
+3198789,
+1155536,
+12971362,
+-4685798,
+7459675,
+3470266,
+1567219,
+7804818,
+-3524761,
+13449926,
+1738911,
+2347406,
+2169089,
+-2928116,
+24250455,
+-5211241,
+4358971,
+-3605298,
+-3015671,
+43724001,
+-23849570,
+9823315,
+-9151253,
+-3769277,
+78835150,
+-66542375,
+23686373,
+-14161143,
+-5040790,
+142141173,
+-156324261,
+56024234,
+-18451275,
+-6612656,
+256283057,
+-335606326,
+126341244,
+-21970004,
+-8270755,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
+16777216,
+33554432,
+16777216,
+-33554432,
+-16777216,
diff --git a/media/libeffects/testlibs/AudioLowShelfFilterCoef.inl b/media/libeffects/testlibs/AudioLowShelfFilterCoef.inl
new file mode 100644
index 0000000..b57deb4
--- /dev/null
+++ b/media/libeffects/testlibs/AudioLowShelfFilterCoef.inl
@@ -0,0 +1,375 @@
+16212506,
+-32420574,
+16208068,
+32401411,
+-15662521,
+16356129,
+-32706246,
+16350118,
+32695525,
+-15939752,
+16464399,
+-32920670,
+16456274,
+32914686,
+-16149441,
+16546128,
+-33081289,
+16535165,
+33077955,
+-16307411,
+16608101,
+-33201422,
+16593328,
+33199569,
+-16426067,
+16655539,
+-33291174,
+16635647,
+33290147,
+-16514997,
+16692478,
+-33358171,
+16665715,
+33357608,
+-16581540,
+16722089,
+-33408149,
+16686099,
+33407850,
+-16631271,
+16746930,
+-33445409,
+16698549,
+33445267,
+-16668405,
+16769156,
+-33473168,
+16704138,
+33473133,
+-16696114,
+16790706,
+-33493827,
+16703348,
+33493886,
+-16716779,
+16813466,
+-33509166,
+16696111,
+33509342,
+-16732186,
+16839437,
+-33520498,
+16681802,
+33520852,
+-16743669,
+16870911,
+-33528765,
+16659191,
+33529424,
+-16752226,
+16910681,
+-33534607,
+16626337,
+33535807,
+-16758602,
+15667401,
+-31326224,
+15658825,
+31252161,
+-14623074,
+15945865,
+-31880007,
+15934146,
+31838205,
+-15144597,
+16157521,
+-32299091,
+16141578,
+32275604,
+-15545369,
+16318267,
+-32614903,
+16296651,
+32601755,
+-15850850,
+16440710,
+-32852157,
+16411473,
+32844820,
+-16082303,
+16534751,
+-33029985,
+16495281,
+33025910,
+-16256891,
+16608171,
+-33163043,
+16554957,
+33160803,
+-16388152,
+16667145,
+-33262468,
+16595477,
+33261275,
+-16486599,
+16716699,
+-33336671,
+16620252,
+33336105,
+-16560301,
+16761100,
+-33391976,
+16631379,
+33391836,
+-16615404,
+16804207,
+-33433103,
+16629806,
+33433341,
+-16656560,
+16849794,
+-33463551,
+16615399,
+33464251,
+-16687277,
+16901887,
+-33485857,
+16586933,
+33487271,
+-16710189,
+16965125,
+-33501781,
+16542000,
+33504415,
+-16727274,
+17045198,
+-33512384,
+16476824,
+33517183,
+-16740008,
+14635201,
+-29254376,
+14619184,
+28977711,
+-12753834,
+15157556,
+-30292825,
+15135285,
+30133938,
+-13674513,
+15561511,
+-31092298,
+15530817,
+31001860,
+-14405551,
+15872211,
+-31702342,
+15830187,
+31651218,
+-14976306,
+16111094,
+-32164834,
+16053843,
+32136101,
+-15416453,
+16295848,
+-32513802,
+16218140,
+32497757,
+-15752817,
+16440852,
+-32776179,
+16335665,
+32767326,
+-16008155,
+16557804,
+-32972907,
+16415715,
+32968179,
+-16201031,
+16656403,
+-33120052,
+16464758,
+33117802,
+-16346195,
+16745001,
+-33229805,
+16486810,
+33229247,
+-16455153,
+16831240,
+-33311306,
+16483692,
+33312252,
+-16536771,
+16922682,
+-33371278,
+16455145,
+33374070,
+-16597819,
+17027472,
+-33414465,
+16398818,
+33420110,
+-16643430,
+17155108,
+-33443875,
+16310110,
+33454398,
+-16677479,
+17317384,
+-33460760,
+16181887,
+33479933,
+-16702882,
+12792703,
+-25557388,
+12764716,
+24590507,
+-9747085,
+13706465,
+-27372621,
+13666215,
+26798296,
+-11169790,
+14439425,
+-28821830,
+14382518,
+28486469,
+-12380088,
+15018453,
+-29957273,
+14939030,
+29764018,
+-13373522,
+15472460,
+-30834757,
+15362688,
+30724568,
+-14168120,
+15828725,
+-31506123,
+15678118,
+31443928,
+-14791822,
+16111406,
+-32015988,
+15905901,
+31981391,
+-15274688,
+16341329,
+-32400984,
+16062061,
+32382398,
+-15644761,
+16536484,
+-32690238,
+16158133,
+32681354,
+-15926286,
+16712853,
+-32906337,
+16201432,
+32904128,
+-16139278,
+16885430,
+-33066336,
+16195306,
+33070090,
+-16299767,
+17069377,
+-33182599,
+16139282,
+33193711,
+-16420332,
+17281371,
+-33263294,
+16029039,
+33285785,
+-16510702,
+17541271,
+-33312390,
+15856243,
+33354359,
+-16578329,
+17874330,
+-33328902,
+15608287,
+33405430,
+-16628873,
+9881279,
+-19719268,
+9838084,
+16734303,
+-5927111,
+11264857,
+-22463447,
+11198784,
+20577584,
+-7572288,
+12460736,
+-24823046,
+12362697,
+23667359,
+-9201903,
+13459805,
+-26776851,
+13317799,
+26085683,
+-10691555,
+14276287,
+-28349256,
+14074406,
+27943899,
+-11978834,
+14936943,
+-29588248,
+14654011,
+29354533,
+-13047453,
+15473300,
+-30549299,
+15081036,
+30417203,
+-13909216,
+15917271,
+-31285788,
+15377817,
+31213972,
+-14589687,
+16299384,
+-31844320,
+15562006,
+31809683,
+-15118811,
+16648774,
+-32262999,
+15645414,
+32254329,
+-15525641,
+16994277,
+-32571090,
+15633607,
+32585895,
+-15835862,
+17366374,
+-32789019,
+15525801,
+32833003,
+-16070975,
+17799955,
+-32927834,
+15314895,
+33017107,
+-16248361,
+18338206,
+-32987318,
+14987686,
+33154246,
+-16381747,
+19038270,
+-32951545,
+14525592,
+33256392,
+-16481800,
diff --git a/media/libeffects/testlibs/AudioPeakingFilter.cpp b/media/libeffects/testlibs/AudioPeakingFilter.cpp
new file mode 100644
index 0000000..60fefe6
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilter.cpp
@@ -0,0 +1,121 @@
+/* //device/include/server/AudioFlinger/AudioPeakingFilter.cpp
+ **
+ ** Copyright 2007, 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.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "AudioPeakingFilter.h"
+#include "AudioCommon.h"
+#include "EffectsMath.h"
+
+#include <new>
+#include <assert.h>
+
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+// Format of the coefficient table:
+// kCoefTable[freq][gain][bw][coef]
+// freq - peak frequency, in octaves below Nyquist,from -9 to -1.
+// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
+// bw - bandwidth, starting at 1 cent, jumps of 1024, to 3073 cents.
+// coef - 0: b0
+// 1: b1
+// 2: b2
+// 3: -a1
+// 4: -a2
+static const size_t kInDims[3] = {9, 15, 4};
+static const audio_coef_t kCoefTable[9*15*4*5] = {
+#include "AudioPeakingFilterCoef.inl"
+};
+
+AudioCoefInterpolator AudioPeakingFilter::mCoefInterp(3, kInDims, 5, (const audio_coef_t*) kCoefTable);
+
+AudioPeakingFilter::AudioPeakingFilter(int nChannels, int sampleRate)
+ : mBiquad(nChannels, sampleRate) {
+ configure(nChannels, sampleRate);
+ reset();
+}
+
+void AudioPeakingFilter::configure(int nChannels, int sampleRate) {
+ mNiquistFreq = sampleRate * 500;
+ mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
+ mBiquad.configure(nChannels, sampleRate);
+ setFrequency(mNominalFrequency);
+ commit(true);
+}
+
+void AudioPeakingFilter::reset() {
+ setGain(0);
+ setFrequency(0);
+ setBandwidth(2400);
+ commit(true);
+}
+
+void AudioPeakingFilter::setFrequency(uint32_t millihertz) {
+ mNominalFrequency = millihertz;
+ if (UNLIKELY(millihertz > mNiquistFreq / 2)) {
+ millihertz = mNiquistFreq / 2;
+ }
+ uint32_t normFreq = static_cast<uint32_t>(
+ (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+ if (LIKELY(normFreq > (1 << 23))) {
+ mFrequency = (Effects_log2(normFreq) - ((32-9) << 15)) << (FREQ_PRECISION_BITS - 15);
+ } else {
+ mFrequency = 0;
+ }
+}
+
+void AudioPeakingFilter::setGain(int32_t millibel) {
+ mGain = millibel + 9600;
+}
+
+void AudioPeakingFilter::setBandwidth(uint32_t cents) {
+ mBandwidth = cents - 1;
+}
+
+void AudioPeakingFilter::commit(bool immediate) {
+ audio_coef_t coefs[5];
+ int intCoord[3] = {
+ mFrequency >> FREQ_PRECISION_BITS,
+ mGain >> GAIN_PRECISION_BITS,
+ mBandwidth >> BANDWIDTH_PRECISION_BITS
+ };
+ uint32_t fracCoord[3] = {
+ mFrequency << (32 - FREQ_PRECISION_BITS),
+ static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS),
+ mBandwidth << (32 - BANDWIDTH_PRECISION_BITS)
+ };
+ mCoefInterp.getCoef(intCoord, fracCoord, coefs);
+ mBiquad.setCoefs(coefs, immediate);
+}
+
+void AudioPeakingFilter::getBandRange(uint32_t & low, uint32_t & high) const {
+ // Half bandwidth, in octaves, 15-bit precision
+ int32_t halfBW = (((mBandwidth + 1) / 2) << 15) / 1200;
+
+ low = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(-halfBW + (16 << 15))) >> 16);
+ if (UNLIKELY(halfBW >= (16 << 15))) {
+ high = mNiquistFreq;
+ } else {
+ high = static_cast<uint32_t>((static_cast<uint64_t>(mNominalFrequency) * Effects_exp2(halfBW + (16 << 15))) >> 16);
+ if (UNLIKELY(high > mNiquistFreq)) {
+ high = mNiquistFreq;
+ }
+ }
+}
+
+}
+
diff --git a/media/libeffects/testlibs/AudioPeakingFilter.h b/media/libeffects/testlibs/AudioPeakingFilter.h
new file mode 100644
index 0000000..d0f49c9
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilter.h
@@ -0,0 +1,151 @@
+/* //device/include/server/AudioFlinger/AudioPeakingFilter.h
+**
+** Copyright 2009, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_AUDIO_PEAKING_FILTER_H
+#define ANDROID_AUDIO_PEAKING_FILTER_H
+
+#include "AudioBiquadFilter.h"
+#include "AudioCoefInterpolator.h"
+
+namespace android {
+
+// A peaking audio filter, with unity skirt gain, and controllable peak
+// frequency, gain and bandwidth.
+// This filter is able to suppress introduce discontinuities and other artifacts
+// in the output, even when changing parameters abruptly.
+// Parameters can be set to any value - this class will make sure to clip them
+// when they are out of supported range.
+//
+// Implementation notes:
+// This class uses an underlying biquad filter whose parameters are determined
+// using a linear interpolation from a coefficient table, using a
+// AudioCoefInterpolator.
+// All is left for this class to do is mapping between high-level parameters to
+// fractional indices into the coefficient table.
+class AudioPeakingFilter {
+public:
+ // Constructor. Resets the filter (see reset()).
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ AudioPeakingFilter(int nChannels, int sampleRate);
+
+ // Reconfiguration of the filter. Changes input/output format, but does not
+ // alter current parameter values. Clears delay lines.
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ void configure(int nChannels, int sampleRate);
+
+ // Resets the filter parameters to the following values:
+ // frequency: 0
+ // gain: 0
+ // bandwidth: 1200 cents.
+ // It also disables the filter. Does not clear the delay lines.
+ void reset();
+
+ // Clears delay lines. Does not alter parameter values.
+ void clear() { mBiquad.clear(); }
+
+ // Sets gain value. Actual change will only take place upon commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // millibel Gain value in millibel (1/100 of decibel).
+ void setGain(int32_t millibel);
+
+ // Gets the gain, in millibel, as set.
+ int32_t getGain() const { return mGain - 9600; }
+
+ // Sets bandwidth value. Actual change will only take place upon commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // cents Bandwidth value in cents (1/1200 octave).
+ void setBandwidth(uint32_t cents);
+
+ // Gets the gain, in cents, as set.
+ uint32_t getBandwidth() const { return mBandwidth + 1; }
+
+ // Sets frequency value. Actual change will only take place upon commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // millihertz Frequency value in mHz.
+ void setFrequency(uint32_t millihertz);
+
+ // Gets the frequency, in mHz, as set.
+ uint32_t getFrequency() const { return mNominalFrequency; }
+
+ // Gets gain[dB]/2 points.
+ // Results in mHz, and are computed based on the nominal values set, not on
+ // possibly rounded or truncated actual values.
+ void getBandRange(uint32_t & low, uint32_t & high) const;
+
+ // Applies all parameter changes done to this point in time.
+ // If the filter is disabled, the new parameters will take place when it is
+ // enabled again. Does not introduce artifacts, unless immediate is set.
+ // immediate Whether to apply change abruptly (ignored if filter is
+ // disabled).
+ void commit(bool immediate = false);
+
+ // Process a buffer of input data. The input and output should contain
+ // frameCount * nChannels interlaced samples. Processing can be done
+ // in-place, by passing the same buffer as both arguments.
+ // in Input buffer.
+ // out Output buffer.
+ // frameCount Number of frames to produce.
+ void process(const audio_sample_t in[], audio_sample_t out[],
+ int frameCount) { mBiquad.process(in, out, frameCount); }
+
+ // Enables the filter, so it would start processing input. Does not
+ // introduce artifacts, unless immediate is set.
+ // immediate Whether to apply change abruptly.
+ void enable(bool immediate = false) { mBiquad.enable(immediate); }
+
+ // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+ // immediate is set.
+ // immediate Whether to apply change abruptly.
+ void disable(bool immediate = false) { mBiquad.disable(immediate); }
+
+private:
+ // Precision for the mFrequency member.
+ static const int FREQ_PRECISION_BITS = 26;
+ // Precision for the mGain member.
+ static const int GAIN_PRECISION_BITS = 10;
+ // Precision for the mBandwidth member.
+ static const int BANDWIDTH_PRECISION_BITS = 10;
+
+ // Nyquist, in mHz.
+ uint32_t mNiquistFreq;
+ // Fractional index into the gain dimension of the coef table in
+ // GAIN_PRECISION_BITS precision.
+ int32_t mGain;
+ // Fractional index into the bandwidth dimension of the coef table in
+ // BANDWIDTH_PRECISION_BITS precision.
+ uint32_t mBandwidth;
+ // Fractional index into the frequency dimension of the coef table in
+ // FREQ_PRECISION_BITS precision.
+ uint32_t mFrequency;
+ // Nominal value of frequency, as set.
+ uint32_t mNominalFrequency;
+ // 1/Nyquist[mHz], in 42-bit precision (very small).
+ // Used for scaling the frequency.
+ uint32_t mFrequencyFactor;
+
+ // A biquad filter, used for the actual processing.
+ AudioBiquadFilter mBiquad;
+ // A coefficient interpolator, used for mapping the high level parameters to
+ // the low-level biquad coefficients.
+ static AudioCoefInterpolator mCoefInterp;
+};
+
+}
+
+#endif // ANDROID_AUDIO_PEAKING_FILTER_H
diff --git a/media/libeffects/testlibs/AudioPeakingFilterCoef.inl b/media/libeffects/testlibs/AudioPeakingFilterCoef.inl
new file mode 100644
index 0000000..374c6e1
--- /dev/null
+++ b/media/libeffects/testlibs/AudioPeakingFilterCoef.inl
@@ -0,0 +1,2700 @@
+16769751,
+-33538871,
+16769751,
+33538871,
+-16762286,
+11468083,
+-22935566,
+11467915,
+22935566,
+-6158781,
+8532673,
+-17064763,
+8532412,
+17064763,
+-287869,
+6567366,
+-13134160,
+6567042,
+13134160,
+3642808,
+16773075,
+-33545518,
+16773075,
+33545518,
+-16768934,
+13349658,
+-26698459,
+13349304,
+26698459,
+-9921746,
+10923581,
+-21846147,
+10922977,
+21846147,
+-5069342,
+9009390,
+-18017641,
+9008590,
+18017641,
+-1240764,
+16774919,
+-33549207,
+16774919,
+33549207,
+-16772622,
+14686150,
+-29371047,
+14685450,
+29371047,
+-12594384,
+12933736,
+-25865697,
+12932448,
+25865697,
+-9088968,
+11350364,
+-22698482,
+11348545,
+22698482,
+-5921693,
+16775943,
+-33551252,
+16775941,
+33551252,
+-16774668,
+15549746,
+-31097569,
+15548408,
+31097569,
+-14320938,
+14404163,
+-28805197,
+14401577,
+28805197,
+-12028524,
+13261978,
+-26519626,
+13258147,
+26519626,
+-9742909,
+16776511,
+-33552387,
+16776508,
+33552387,
+-16775803,
+16074349,
+-32145600,
+16071856,
+32145600,
+-15368989,
+15374244,
+-30742933,
+15369268,
+30742933,
+-13966296,
+14629431,
+-29250695,
+14621814,
+29250695,
+-12474030,
+16776826,
+-33553017,
+16776822,
+33553017,
+-16776432,
+16381548,
+-32757900,
+16376968,
+32757900,
+-15981300,
+15972161,
+-31934402,
+15962842,
+31934402,
+-15157787,
+15518882,
+-31022614,
+15504316,
+31022614,
+-14245982,
+16777003,
+-33553366,
+16776995,
+33553366,
+-16776781,
+16558315,
+-33107660,
+16549969,
+33107660,
+-16331067,
+16326848,
+-32635910,
+16309677,
+32635910,
+-15859308,
+16064456,
+-32101133,
+16037281,
+32101133,
+-15324521,
+16777103,
+-33553559,
+16777088,
+33553559,
+-16776975,
+16660325,
+-33304885,
+16645187,
+33304885,
+-16528296,
+16535200,
+-33038436,
+16503858,
+33038436,
+-16261842,
+16391425,
+-32732273,
+16341464,
+32732273,
+-15955673,
+16777162,
+-33553667,
+16777136,
+33553667,
+-16777082,
+16721651,
+-33415288,
+16694267,
+33415288,
+-16638701,
+16661761,
+-33265997,
+16604862,
+33265997,
+-16489407,
+16592417,
+-33093137,
+16501343,
+33093137,
+-16316544,
+16777203,
+-33553726,
+16777155,
+33553726,
+-16777142,
+16763466,
+-33476836,
+16714001,
+33476836,
+-16700251,
+16748588,
+-33393565,
+16645605,
+33393565,
+-16616978,
+16731288,
+-33296733,
+16566071,
+33296733,
+-16520144,
+16777238,
+-33553759,
+16777152,
+33553759,
+-16777175,
+16800489,
+-33511071,
+16711212,
+33511071,
+-16734485,
+16825723,
+-33464740,
+16639647,
+33464740,
+-16688154,
+16855137,
+-33410736,
+16556228,
+33410736,
+-16634149,
+16777282,
+-33553778,
+16777127,
+33553778,
+-16777193,
+16845889,
+-33530088,
+16684830,
+33530088,
+-16753503,
+16920437,
+-33504347,
+16584541,
+33504347,
+-16727762,
+17007449,
+-33474302,
+16467484,
+33474302,
+-16697716,
+16777349,
+-33553788,
+16777070,
+33553788,
+-16777203,
+16915880,
+-33540645,
+16625396,
+33540645,
+-16764060,
+17066504,
+-33526354,
+16460481,
+33526354,
+-16749769,
+17242444,
+-33509662,
+16267849,
+33509662,
+-16733077,
+16777464,
+-33553793,
+16776961,
+33553793,
+-16777209,
+17035487,
+-33546503,
+16511647,
+33546503,
+-16769918,
+17316137,
+-33538572,
+16223067,
+33538572,
+-16761988,
+17644089,
+-33529306,
+15885848,
+33529306,
+-16752721,
+16777668,
+-33553796,
+16776760,
+33553796,
+-16777212,
+17247484,
+-33549752,
+16302900,
+33549752,
+-16773168,
+17758603,
+-33545353,
+15787381,
+33545353,
+-16768768,
+18356007,
+-33540211,
+15184835,
+33540211,
+-16763626,
+16762293,
+-33522062,
+16762293,
+33522062,
+-16747370,
+8711405,
+-17421242,
+8711149,
+17421242,
+-645338,
+5721250,
+-11441288,
+5720900,
+11441288,
+5335066,
+4082836,
+-8164655,
+4082434,
+8164655,
+8611946,
+16768936,
+-33535347,
+16768936,
+33535347,
+-16760656,
+11085056,
+-22167856,
+11084469,
+22167856,
+-5392309,
+8098223,
+-16194333,
+8097329,
+16194333,
+581664,
+6158323,
+-12314623,
+6157228,
+12314623,
+4461665,
+16772623,
+-33542719,
+16772622,
+33542719,
+-16768029,
+13058634,
+-26114055,
+13057388,
+26114055,
+-9338806,
+10523211,
+-21042742,
+10521116,
+21042742,
+-4267110,
+8576560,
+-17149081,
+8573812,
+17149081,
+-373156,
+16774670,
+-33546810,
+16774667,
+33546810,
+-16772120,
+14489725,
+-28974776,
+14487233,
+28974776,
+-12199742,
+12619509,
+-25232587,
+12614979,
+25232587,
+-8457271,
+10965151,
+-21922319,
+10958818,
+21922319,
+-5146753,
+16775805,
+-33549079,
+16775800,
+33549079,
+-16774390,
+15428102,
+-30849095,
+15423317,
+30849095,
+-14074202,
+14188157,
+-28364996,
+14178975,
+28364996,
+-11589916,
+12969900,
+-25924346,
+12956398,
+25924346,
+-9149082,
+16776437,
+-33550338,
+16776428,
+33550338,
+-16775648,
+16004216,
+-31997074,
+15995268,
+31997074,
+-15222267,
+15241233,
+-30462393,
+15223454,
+30462393,
+-13687471,
+14437070,
+-28844880,
+14409982,
+28844880,
+-12069836,
+16776789,
+-33551036,
+16776773,
+33551036,
+-16776347,
+16345158,
+-32671383,
+16328685,
+32671383,
+-15896627,
+15900462,
+-31765104,
+15867034,
+31765104,
+-14990280,
+15410846,
+-30767279,
+15358750,
+30767279,
+-13992380,
+16776990,
+-33551423,
+16776960,
+33551423,
+-16776734,
+16545156,
+-33057769,
+16515103,
+33057769,
+-16283043,
+16300504,
+-32536823,
+16238769,
+32536823,
+-15762058,
+16024071,
+-31948201,
+15926537,
+31948201,
+-15173391,
+16777109,
+-33551638,
+16777056,
+33551638,
+-16776949,
+16666542,
+-33276035,
+16611999,
+33276035,
+-16501325,
+16548270,
+-32981225,
+16435439,
+32981225,
+-16206493,
+16412621,
+-32643103,
+16232940,
+32643103,
+-15868346,
+16777189,
+-33551757,
+16777094,
+33551757,
+-16777068,
+16749778,
+-33398338,
+16651075,
+33398338,
+-16623637,
+16720233,
+-33232976,
+16515245,
+33232976,
+-16458262,
+16686059,
+-33041706,
+16358135,
+33041706,
+-16266978,
+16777261,
+-33551823,
+16777089,
+33551823,
+-16777134,
+16823703,
+-33466559,
+16645376,
+33466559,
+-16691863,
+16873974,
+-33374267,
+16502806,
+33374267,
+-16599564,
+16932398,
+-33267006,
+16337114,
+33267006,
+-16492295,
+16777348,
+-33551860,
+16777038,
+33551860,
+-16777170,
+16914465,
+-33504517,
+16592574,
+33504517,
+-16729824,
+17063236,
+-33453150,
+16392432,
+33453150,
+-16678453,
+17236595,
+-33393293,
+16159213,
+33393293,
+-16618592,
+16777483,
+-33551880,
+16776924,
+33551880,
+-16777191,
+17054436,
+-33525606,
+16473695,
+33525606,
+-16750914,
+17355321,
+-33497061,
+16144262,
+33497061,
+-16722367,
+17706453,
+-33463749,
+15759816,
+33463749,
+-16689053,
+16777713,
+-33551891,
+16776705,
+33551891,
+-16777202,
+17293646,
+-33537314,
+16246194,
+33537314,
+-16762623,
+17854571,
+-33521465,
+15669419,
+33521465,
+-16746773,
+18509706,
+-33502954,
+14995772,
+33502954,
+-16728261,
+16778120,
+-33551898,
+16776304,
+33551898,
+-16777208,
+17717639,
+-33543811,
+15828698,
+33543811,
+-16769121,
+18739501,
+-33535016,
+14798040,
+33535016,
+-16760325,
+19933534,
+-33524738,
+13593729,
+33524738,
+-16750047,
+16747397,
+-33484705,
+16747396,
+33484705,
+-16717577,
+5883112,
+-11762335,
+5882767,
+11762335,
+5011337,
+3448701,
+-6894903,
+3448279,
+6894903,
+9880236,
+2324286,
+-4646714,
+2323828,
+4646714,
+12129102,
+16760665,
+-33511232,
+16760663,
+33511232,
+-16744112,
+8276984,
+-16548106,
+8276108,
+16548106,
+224124,
+5337400,
+-10670406,
+5336221,
+10670406,
+6103596,
+3771525,
+-7539439,
+3770185,
+7539439,
+9235506,
+16768033,
+-33525963,
+16768030,
+33525963,
+-16758848,
+10689564,
+-21370649,
+10687524,
+21370649,
+-4599872,
+7666068,
+-15324466,
+7663015,
+15324466,
+1448133,
+5761266,
+-11515371,
+5757575,
+11515371,
+5258376,
+16772124,
+-33534139,
+16772118,
+33534139,
+-16767026,
+12751423,
+-25490780,
+12747036,
+25490780,
+-8721243,
+10113942,
+-20214533,
+10106682,
+20214533,
+-3443407,
+8145025,
+-16275741,
+8135620,
+16275741,
+496571,
+16774395,
+-33538675,
+16774385,
+33538675,
+-16771564,
+14280137,
+-28542819,
+14271281,
+28542819,
+-11774202,
+12292391,
+-24561476,
+12276485,
+24561476,
+-7791660,
+10572949,
+-21117532,
+10550945,
+21117532,
+-4346678,
+16775657,
+-33541192,
+16775639,
+33541192,
+-16774081,
+15299683,
+-30573051,
+15282579,
+30573051,
+-13805046,
+13964251,
+-27887539,
+13931690,
+27887539,
+-11118724,
+12672686,
+-25290241,
+12625174,
+25290241,
+-8520644,
+16776363,
+-33542588,
+16776330,
+33542588,
+-16775477,
+15935196,
+-31828699,
+15903092,
+31828699,
+-15061072,
+15112356,
+-30152153,
+15048881,
+30152153,
+-13384021,
+14253857,
+-28402950,
+14157649,
+28402950,
+-11634291,
+16776763,
+-33543362,
+16776704,
+33543362,
+-16776252,
+16319830,
+-32570615,
+16260598,
+32570615,
+-15803212,
+15851783,
+-31574208,
+15731938,
+31574208,
+-14806505,
+15339614,
+-30483871,
+15153441,
+30483871,
+-13715838,
+16777001,
+-33543791,
+16776896,
+33543791,
+-16776681,
+16557673,
+-32997208,
+16449476,
+32997208,
+-16229933,
+16326977,
+-32422299,
+16105089,
+32422299,
+-15654851,
+16067244,
+-31775024,
+15717353,
+31775024,
+-15007381,
+16777163,
+-33544029,
+16776972,
+33544029,
+-16776919,
+16722590,
+-33238660,
+16526083,
+33238660,
+-16471458,
+16664322,
+-32912610,
+16258203,
+32912610,
+-16145310,
+16597629,
+-32539419,
+15951593,
+32539419,
+-15772007,
+16777306,
+-33544162,
+16776962,
+33544162,
+-16777051,
+16869955,
+-33374105,
+16514205,
+33374105,
+-16606944,
+16969714,
+-33190996,
+16231282,
+33190996,
+-16423780,
+17084972,
+-32979442,
+15904406,
+32979442,
+-16212162,
+16777480,
+-33544235,
+16776860,
+33544235,
+-16777125,
+17051328,
+-33449703,
+16408452,
+33449703,
+-16682565,
+17347583,
+-33347437,
+16009901,
+33347437,
+-16580267,
+17691668,
+-33228659,
+15547002,
+33228659,
+-16461454,
+16777750,
+-33544275,
+16776632,
+33544275,
+-16777165,
+17331222,
+-33491780,
+16170648,
+33491780,
+-16724654,
+17931550,
+-33434840,
+15513363,
+33434840,
+-16667697,
+18630855,
+-33368512,
+14747710,
+33368512,
+-16601349,
+16778210,
+-33544298,
+16776194,
+33544298,
+-16777188,
+17809628,
+-33515162,
+15715631,
+33515162,
+-16748043,
+18929991,
+-33483514,
+14563611,
+33483514,
+-16716385,
+20237212,
+-33446587,
+13219451,
+33446587,
+-16679448,
+16779025,
+-33544310,
+16775392,
+33544310,
+-16777200,
+18657612,
+-33528145,
+14880634,
+33528145,
+-16761030,
+20699844,
+-33510571,
+12820822,
+33510571,
+-16743451,
+23084863,
+-33490047,
+10415274,
+33490047,
+-16722921,
+16717684,
+-33395091,
+16717682,
+33395091,
+-16658149,
+3567009,
+-7125006,
+3566590,
+7125006,
+9643617,
+1921926,
+-3838751,
+1921455,
+3838751,
+12933835,
+1248662,
+-2493824,
+1248170,
+2493824,
+14280384,
+16744147,
+-33447952,
+16744143,
+33447952,
+-16711074,
+5493785,
+-10973174,
+5492622,
+10973174,
+5790808,
+3173694,
+-6338342,
+3172292,
+6338342,
+10431230,
+2124754,
+-4242881,
+2123244,
+4242881,
+12529218,
+16758861,
+-33477342,
+16758855,
+33477342,
+-16740500,
+7843885,
+-15665884,
+7840892,
+15665884,
+1092439,
+4968649,
+-9921376,
+4964692,
+9921376,
+6843875,
+3478437,
+-6944043,
+3473981,
+6944043,
+9824798,
+16767035,
+-33493665,
+16767024,
+33493665,
+-16756842,
+10284421,
+-20536999,
+10277346,
+20536999,
+-3784550,
+7240254,
+-14452686,
+7229862,
+14452686,
+2307100,
+5379798,
+-10734231,
+5367379,
+10734231,
+6030039,
+16771575,
+-33502725,
+16771555,
+33502725,
+-16765913,
+12431046,
+-24816749,
+12415632,
+24816749,
+-8069462,
+9702049,
+-19355664,
+9676957,
+19355664,
+-2601790,
+7722611,
+-15394544,
+7690499,
+15394544,
+1364106,
+16774099,
+-33507752,
+16774063,
+33507752,
+-16770946,
+14062583,
+-28059903,
+14031160,
+28059903,
+-11316527,
+11962999,
+-23841519,
+11907273,
+23841519,
+-7093056,
+10188929,
+-20277142,
+10112667,
+20277142,
+-3524380,
+16775510,
+-33510541,
+16775445,
+33510541,
+-16773738,
+15175102,
+-30252637,
+15114019,
+30252637,
+-13511905,
+13753207,
+-27358123,
+13637911,
+27358123,
+-10613901,
+12400971,
+-24605416,
+12234119,
+24605416,
+-7857874,
+16776310,
+-33512088,
+16776193,
+33512088,
+-16775287,
+15888242,
+-31623221,
+15773117,
+31623221,
+-14884143,
+15028972,
+-29795608,
+14802570,
+29795608,
+-13054325,
+14142237,
+-27909578,
+13801000,
+27909578,
+-11166021,
+16776787,
+-33512946,
+16776575,
+33512946,
+-16776146,
+16345172,
+-32438302,
+16132251,
+32438302,
+-15700207,
+15905856,
+-31344484,
+15476429,
+31344484,
+-14605069,
+15428324,
+-30155514,
+14763558,
+30155514,
+-13414665,
+16777110,
+-33513422,
+16776729,
+33513422,
+-16776623,
+16668950,
+-32908744,
+16279482,
+32908744,
+-16171216,
+16555594,
+-32275015,
+15758344,
+32275015,
+-15536722,
+16428465,
+-31564284,
+15173886,
+31564284,
+-14825134,
+16777395,
+-33513686,
+16776708,
+33513686,
+-16776887,
+16961758,
+-33175594,
+16253845,
+33175594,
+-16438387,
+17158212,
+-32815329,
+15696692,
+32815329,
+-16077688,
+17382578,
+-32403880,
+15060381,
+32403880,
+-15665743,
+16777745,
+-33513832,
+16776505,
+33513832,
+-16777033,
+17323903,
+-33325470,
+16041757,
+33325470,
+-16588444,
+17911332,
+-33122874,
+15251488,
+33122874,
+-16385604,
+18589203,
+-32889086,
+14339546,
+32889086,
+-16151534,
+16778283,
+-33513913,
+16776048,
+33513913,
+-16777115,
+17883505,
+-33409180,
+15565966,
+33409180,
+-16672255,
+19078451,
+-33295944,
+14257648,
+33295944,
+-16558883,
+20465440,
+-33164510,
+12739067,
+33164510,
+-16427290,
+16779203,
+-33513958,
+16775173,
+33513958,
+-16777160,
+18840265,
+-33455789,
+14655871,
+33455789,
+-16718921,
+21075121,
+-33392715,
+12357866,
+33392715,
+-16655771,
+23677621,
+-33319266,
+9681828,
+33319266,
+-16582233,
+16780834,
+-33513983,
+16773567,
+33513983,
+-16777185,
+20536227,
+-33481696,
+12985848,
+33481696,
+-16744859,
+24614855,
+-33446630,
+8872112,
+33446630,
+-16709751,
+29373075,
+-33405721,
+4072934,
+33405721,
+-16668793,
+16658572,
+-33156710,
+16658568,
+33156710,
+-16539925,
+1995694,
+-3971702,
+1995225,
+3971702,
+12786296,
+1019334,
+-2028355,
+1018835,
+2028355,
+14739047,
+648397,
+-1290041,
+647886,
+1290041,
+15480933,
+16711208,
+-33261470,
+16711201,
+33261470,
+-16645192,
+3284873,
+-6536727,
+3283483,
+6536727,
+10208860,
+1752746,
+-3487071,
+1751198,
+3487071,
+13273272,
+1134254,
+-2255981,
+1132642,
+2255981,
+14510319,
+16740546,
+-33319859,
+16740534,
+33319859,
+-16703864,
+5119019,
+-10184853,
+5115113,
+10184853,
+6543083,
+2916766,
+-5800820,
+2912122,
+5800820,
+10948329,
+1940950,
+-3858260,
+1935979,
+3858260,
+12900288,
+16756866,
+-33352332,
+16756844,
+33352332,
+-16736493,
+7416141,
+-14750709,
+7405941,
+14750709,
+1955134,
+4618132,
+-9178604,
+4604884,
+9178604,
+7554200,
+3205731,
+-6365873,
+3190944,
+6365873,
+10380541,
+16765937,
+-33370369,
+16765897,
+33370369,
+-16754618,
+9875714,
+-19631961,
+9851238,
+19631961,
+-2949736,
+6828874,
+-13556870,
+6793592,
+13556870,
+3154751,
+5021920,
+-9953987,
+4980230,
+9953987,
+6775066,
+16770983,
+-33380381,
+16770911,
+33380381,
+-16764679,
+12107731,
+-24045066,
+12053679,
+24045066,
+-7384194,
+9304697,
+-18433704,
+9218200,
+18433704,
+-1745681,
+7330173,
+-14480925,
+7220819,
+14480925,
+2226224,
+16773804,
+-33385937,
+16773674,
+33385937,
+-16770261,
+13857067,
+-27469883,
+13745731,
+27469883,
+-10825583,
+11667230,
+-23028209,
+11472403,
+23028209,
+-6362417,
+9861509,
+-19365642,
+9597835,
+19365642,
+-2682128,
+16775405,
+-33389019,
+16775170,
+33389019,
+-16773358,
+15094166,
+-29826057,
+14876207,
+29826057,
+-13193157,
+13629575,
+-26722225,
+13221948,
+26722225,
+-10074307,
+12261304,
+-23822520,
+11676482,
+23822520,
+-7160571,
+16776358,
+-33390729,
+16775935,
+33390729,
+-16775076,
+15939973,
+-31315809,
+15527360,
+31315809,
+-14690117,
+15140254,
+-29331850,
+14333520,
+29331850,
+-12696558,
+14324552,
+-27308240,
+13115821,
+27308240,
+-10663157,
+16777004,
+-33391677,
+16776241,
+33391677,
+-16776029,
+16564519,
+-32208051,
+15799374,
+32208051,
+-15586676,
+16349720,
+-31011538,
+14811870,
+31011538,
+-14384374,
+16117884,
+-29720119,
+13746038,
+29720119,
+-13086705,
+16777574,
+-33392203,
+16776199,
+33392203,
+-16776558,
+17142623,
+-32725183,
+15740903,
+32725183,
+-16106310,
+17523746,
+-32028793,
+14660021,
+32028793,
+-15406551,
+17949452,
+-31250941,
+13452699,
+31250941,
+-14624935,
+16778273,
+-33392495,
+16775794,
+33392495,
+-16776851,
+17864511,
+-33019221,
+15314476,
+33019221,
+-16401771,
+19019582,
+-32622294,
+13760557,
+32622294,
+-16002923,
+20335886,
+-32169961,
+11989731,
+32169961,
+-15548401,
+16779350,
+-33392657,
+16774879,
+33392657,
+-16777014,
+18982972,
+-33184592,
+14362186,
+33184592,
+-16567942,
+21350554,
+-32961046,
+11769976,
+32961046,
+-16343314,
+24079688,
+-32703362,
+8781912,
+32703362,
+-16084383,
+16781190,
+-33392746,
+16773130,
+33392746,
+-16777104,
+20896303,
+-33277026,
+12541737,
+33277026,
+-16660824,
+25343199,
+-33151977,
+7969185,
+33151977,
+-16535169,
+30502384,
+-33006896,
+2664219,
+33006896,
+-16389387,
+16784451,
+-33392796,
+16769918,
+33392796,
+-16777154,
+24288258,
+-33328516,
+9201520,
+33328516,
+-16712562,
+32423187,
+-33258828,
+996567,
+33258828,
+-16642538,
+41895320,
+-33177686,
+-8557101,
+33177686,
+-16561003,
+16541595,
+-32447498,
+16541587,
+32447498,
+-16305966,
+1060925,
+-2080590,
+1060426,
+2080590,
+14655865,
+525478,
+-1030256,
+524962,
+1030256,
+15726776,
+330321,
+-647437,
+329800,
+647437,
+16117095,
+16645717,
+-32651734,
+16645703,
+32651734,
+-16514203,
+1820789,
+-3570095,
+1819248,
+3570095,
+13137179,
+924575,
+-1812018,
+922942,
+1812018,
+14929699,
+586684,
+-1149186,
+585016,
+1149186,
+15605516,
+16704036,
+-32766121,
+16704011,
+32766121,
+-16630831,
+3020875,
+-5921138,
+3016266,
+5921138,
+10740076,
+1597573,
+-3128764,
+1592487,
+3128764,
+13587156,
+1030124,
+-2015487,
+1024848,
+2015487,
+14722244,
+16736565,
+-32829909,
+16736521,
+32829909,
+-16695869,
+4762013,
+-9328185,
+4748922,
+9328185,
+7266281,
+2679566,
+-5241091,
+2664205,
+5241091,
+11433446,
+1773912,
+-3463620,
+1757564,
+3463620,
+13245740,
+16754673,
+-32865395,
+16754593,
+32865395,
+-16732050,
+7001772,
+-13700468,
+6967104,
+13700468,
+2808340,
+4293363,
+-8378312,
+4249089,
+8378312,
+8234764,
+2960061,
+-5758307,
+2911058,
+5758307,
+10906097,
+16764756,
+-32885110,
+16764611,
+32885110,
+-16752151,
+9480188,
+-18513215,
+9395722,
+18513215,
+-2098694,
+6453693,
+-12542171,
+6334194,
+12542171,
+3989330,
+4710641,
+-9103264,
+4570966,
+9103264,
+7495609,
+16770393,
+-32896054,
+16770133,
+32896054,
+-16763310,
+11816276,
+-22992949,
+11627131,
+22992949,
+-6666191,
+8975726,
+-17314789,
+8678280,
+17314789,
+-876790,
+7032408,
+-13430164,
+6660869,
+13430164,
+3083940,
+16773593,
+-32902127,
+16773124,
+32902127,
+-16769502,
+13735615,
+-26557052,
+13341720,
+26557052,
+-10300120,
+11528165,
+-21946606,
+10848400,
+21946606,
+-5599349,
+9752563,
+-18238110,
+8842853,
+18238110,
+-1818200,
+16775499,
+-32905496,
+16774654,
+32905496,
+-16772937,
+15200588,
+-29054957,
+14423589,
+29054957,
+-12846961,
+13857004,
+-25769995,
+12417855,
+25769995,
+-9497643,
+12624453,
+-22756500,
+10577873,
+22756500,
+-6425111,
+16776792,
+-32907365,
+16775267,
+32907365,
+-16774843,
+16366344,
+-30654089,
+14888294,
+30654089,
+-14477422,
+15978753,
+-28526295,
+13106406,
+28526295,
+-12307942,
+15588057,
+-26381456,
+11310242,
+26381456,
+-10121083,
+16777933,
+-32908402,
+16775183,
+32908402,
+-16775900,
+17493802,
+-31619287,
+14744943,
+31619287,
+-15461529,
+18212414,
+-30325234,
+12706927,
+30325234,
+-14142124,
+18982725,
+-28938081,
+10522286,
+28938081,
+-12727795,
+16779330,
+-32908977,
+16774372,
+32908977,
+-16776486,
+18928041,
+-32181280,
+13883707,
+32181280,
+-16034532,
+21163118,
+-31424334,
+10876855,
+31424334,
+-15262757,
+23650871,
+-30581814,
+7530076,
+30581814,
+-14403731,
+16781484,
+-32909296,
+16772543,
+32909296,
+-16776811,
+21161996,
+-32501674,
+11976424,
+32501674,
+-16361204,
+25812009,
+-32068975,
+6885234,
+32068975,
+-15920027,
+31103385,
+-31576594,
+1091831,
+31576594,
+-15418000,
+16785164,
+-32909473,
+16769043,
+32909473,
+-16776991,
+24988064,
+-32682139,
+8334356,
+32682139,
+-16545204,
+33795794,
+-32438043,
+-722252,
+32438043,
+-16296325,
+43946128,
+-32156738,
+-11159403,
+32156738,
+-16009510,
+16791687,
+-32909571,
+16762620,
+32909571,
+-16777091,
+31772521,
+-32783096,
+1652834,
+32783096,
+-16648139,
+47961229,
+-32646423,
+-14675225,
+32646423,
+-16508788,
+66751682,
+-32487785,
+-33627423,
+32487785,
+-16347043,
+16312500,
+-30141556,
+16312485,
+30141556,
+-15847769,
+547598,
+-1011354,
+547084,
+1011354,
+15682534,
+266448,
+-491849,
+265925,
+491849,
+16244843,
+166111,
+-306446,
+165584,
+306446,
+16445521,
+16516262,
+-30518049,
+16516236,
+30518049,
+-16255282,
+962487,
+-1776938,
+960857,
+1776938,
+14853872,
+474742,
+-875656,
+473062,
+875656,
+15829413,
+297520,
+-548176,
+295821,
+548176,
+16183875,
+16631492,
+-30730944,
+16631443,
+30730944,
+-16485719,
+1660146,
+-3062870,
+1655081,
+3062870,
+13461989,
+838172,
+-1543806,
+832831,
+1543806,
+15106213,
+530135,
+-974532,
+524691,
+974532,
+15722390,
+16696110,
+-30850307,
+16696022,
+30850307,
+-16614916,
+2776642,
+-5116472,
+2761387,
+5116472,
+11239187,
+1456845,
+-2676477,
+1440152,
+2676477,
+13880219,
+936151,
+-1713835,
+918891,
+1713835,
+14922174,
+16732191,
+-30916910,
+16732031,
+30916910,
+-16687006,
+4430219,
+-8145523,
+4386431,
+8145523,
+7960566,
+2467715,
+-4512857,
+2416966,
+4512857,
+11892535,
+1628113,
+-2958725,
+1574387,
+2958725,
+13574716,
+16752314,
+-30953973,
+16752025,
+30953973,
+-16727123,
+6622193,
+-12127616,
+6504644,
+12127616,
+3650379,
+4016541,
+-7285135,
+3868831,
+7285135,
+8891843,
+2762675,
+-4954883,
+2600451,
+4954883,
+11414089,
+16763575,
+-30974568,
+16763055,
+30974568,
+-16749415,
+9150431,
+-16639142,
+8859646,
+16639142,
+-1232861,
+6182181,
+-11049974,
+5778225,
+11049974,
+4816810,
+4518629,
+-7917532,
+4051247,
+7917532,
+8207341,
+16769973,
+-30986002,
+16769034,
+30986002,
+-16761791,
+11676269,
+-20964630,
+11015683,
+20964630,
+-5914736,
+8893418,
+-15489638,
+7872446,
+15489638,
+11352,
+7041383,
+-11845939,
+5780568,
+11845939,
+3955265,
+16773783,
+-30992347,
+16772092,
+30992347,
+-16768659,
+13953280,
+-24496534,
+12561577,
+24496534,
+-9737641,
+11970921,
+-19931025,
+9602265,
+19931025,
+-4795970,
+10413172,
+-16343421,
+7276820,
+16343421,
+-912775,
+16776368,
+-30995868,
+16773318,
+30995868,
+-16772470,
+16007790,
+-27021343,
+13239901,
+27021343,
+-12470475,
+15365527,
+-23700024,
+10287194,
+23700024,
+-8875505,
+14785947,
+-20702857,
+7622664,
+20702857,
+-5631395,
+16778650,
+-30997821,
+16773150,
+30997821,
+-16774583,
+18157056,
+-28659649,
+12863925,
+28659649,
+-14243764,
+19443806,
+-26476950,
+9214638,
+26476950,
+-11881228,
+20728681,
+-24297433,
+5570671,
+24297433,
+-9522136,
+16781445,
+-30998904,
+16771527,
+30998904,
+-16775756,
+20988060,
+-29656921,
+11112361,
+29656921,
+-15323204,
+25187743,
+-28317150,
+5462520,
+28317150,
+-13873047,
+29672124,
+-26886556,
+-570326,
+26886556,
+-12324582,
+16785752,
+-30999505,
+16767870,
+30999505,
+-16776406,
+25444300,
+-30240545,
+7287830,
+30240545,
+-15954914,
+34434980,
+-29452472,
+-2555854,
+29452472,
+-15101910,
+44441242,
+-28575379,
+-13511474,
+28575379,
+-14152552,
+16793112,
+-30999838,
+16760871,
+30999838,
+-16776767,
+33095506,
+-30574250,
+-2177,
+30574250,
+-16316113,
+50408034,
+-30122291,
+-17803902,
+30122291,
+-15826917,
+70153765,
+-29606811,
+-38107583,
+29606811,
+-15268966,
+16806158,
+-31000023,
+16748025,
+31000023,
+-16776967,
+46670155,
+-30762526,
+-13373037,
+30762526,
+-16519902,
+78789544,
+-30507092,
+-45768905,
+30507092,
+-16243423,
+115942747,
+-30211627,
+-83241918,
+30211627,
+-15923613,
+15872835,
+-22447559,
+15872807,
+22447559,
+-14968426,
+277754,
+-392434,
+277231,
+392434,
+16222231,
+133061,
+-187804,
+132533,
+187804,
+16511622,
+81763,
+-115256,
+81233,
+115256,
+16614220,
+16263303,
+-22999746,
+16263250,
+22999746,
+-15749337,
+494605,
+-698290,
+492927,
+698290,
+15789685,
+238776,
+-336475,
+237071,
+336475,
+16301369,
+147228,
+-207000,
+145514,
+207000,
+16484473,
+16488278,
+-23317877,
+16488181,
+23317877,
+-16199242,
+872378,
+-1229961,
+867049,
+1229961,
+15037788,
+426889,
+-599839,
+421411,
+599839,
+15928916,
+264840,
+-370629,
+259308,
+370629,
+16253068,
+16615785,
+-23498145,
+16615609,
+23498145,
+-16454179,
+1513757,
+-2129016,
+1497126,
+2129016,
+13766333,
+758261,
+-1060001,
+740806,
+1060001,
+15278149,
+475551,
+-659971,
+457789,
+659971,
+15843875,
+16687407,
+-23599332,
+16687089,
+23599332,
+-16597280,
+2557116,
+-3580647,
+2506684,
+3580647,
+11713416,
+1332007,
+-1845009,
+1277230,
+1845009,
+14167979,
+851272,
+-1163942,
+794791,
+1163942,
+15131154,
+16727486,
+-23655830,
+16726910,
+23655830,
+-16677180,
+4144749,
+-5758163,
+3998523,
+5758163,
+8633944,
+2297803,
+-3131069,
+2130198,
+3131069,
+12349216,
+1516025,
+-2019070,
+1339371,
+2019070,
+13921820,
+16749957,
+-23687282,
+16748918,
+23687282,
+-16721660,
+6342807,
+-8688774,
+5944975,
+8688774,
+4489434,
+3855722,
+-5104454,
+3363066,
+5104454,
+9558428,
+2678286,
+-3407564,
+2140738,
+3407564,
+11958192,
+16762736,
+-23704762,
+16760861,
+23704762,
+-16746380,
+9059948,
+-12106014,
+8060542,
+12106014,
+-343274,
+6231959,
+-7847669,
+4866322,
+7847669,
+5678936,
+4678573,
+-5508603,
+3111768,
+5508603,
+8986875,
+16770353,
+-23714468,
+16766970,
+23714468,
+-16760107,
+12100768,
+-15483427,
+9796104,
+15483427,
+-5119656,
+9659401,
+-11180047,
+6151573,
+11180047,
+966242,
+8066003,
+-8371376,
+3772911,
+8371376,
+4938302,
+16775520,
+-23719855,
+16769420,
+23719855,
+-16767725,
+15410647,
+-18317794,
+10494626,
+18317794,
+-9128056,
+14477439,
+-14624233,
+6204350,
+14624233,
+-3904573,
+13754127,
+-11761419,
+2879032,
+11761419,
+144058,
+16780083,
+-23722844,
+16769084,
+23722844,
+-16771951,
+19348947,
+-20387735,
+9483664,
+20387735,
+-12055395,
+21467038,
+-17637855,
+3476656,
+17637855,
+-8166478,
+23369301,
+-15168181,
+-1918253,
+15168181,
+-4673832,
+16785673,
+-23724501,
+16765839,
+23724501,
+-16774296,
+24868547,
+-21750945,
+5891934,
+21750945,
+-13983265,
+32392543,
+-19913847,
+-4230110,
+19913847,
+-11385217,
+39938641,
+-18071353,
+-14381888,
+18071353,
+-8779537,
+16794288,
+-23725421,
+16758525,
+23725421,
+-16775596,
+33739025,
+-22588636,
+-1793870,
+22588636,
+-15167940,
+50727371,
+-21448926,
+-20394010,
+21448926,
+-13556146,
+69082218,
+-20217540,
+-40490298,
+20217540,
+-11814703,
+16809008,
+-23725931,
+16744526,
+23725931,
+-16776318,
+49053594,
+-23081666,
+-16411189,
+23081666,
+-15865189,
+82824296,
+-22406908,
+-51136143,
+22406908,
+-14910937,
+121049915,
+-21643138,
+-90441895,
+21643138,
+-13830803,
+16835099,
+-23726214,
+16718835,
+23726214,
+-16776718,
+76261468,
+-23364505,
+-43219068,
+23364505,
+-16265184,
+140080603,
+-22976059,
+-107587549,
+22976059,
+-15715838,
+214348557,
+-22524014,
+-182494791,
+22524014,
+-15076550,
+15060971,
+0,
+15060916,
+0,
+-13344671,
+137715,
+0,
+137188,
+0,
+16502313,
+62494,
+0,
+61964,
+0,
+16652757,
+35499,
+0,
+34969,
+0,
+16706748,
+15779939,
+0,
+15779837,
+0,
+-14782560,
+247059,
+0,
+245356,
+0,
+16284801,
+112726,
+0,
+111009,
+0,
+16553481,
+64282,
+0,
+62560,
+0,
+16650375,
+16209124,
+0,
+16208934,
+0,
+-15640842,
+441483,
+0,
+436010,
+0,
+15899723,
+203401,
+0,
+197848,
+0,
+16375967,
+116794,
+0,
+111212,
+0,
+16549211,
+16457433,
+0,
+16457085,
+0,
+-16137302,
+783510,
+0,
+766083,
+0,
+15227623,
+367229,
+0,
+349349,
+0,
+16060638,
+213457,
+0,
+195409,
+0,
+16368349,
+16598556,
+0,
+16597923,
+0,
+-16419263,
+1374332,
+0,
+1319705,
+0,
+14083179,
+663683,
+0,
+606536,
+0,
+15506996,
+394077,
+0,
+335974,
+0,
+16047166,
+16678051,
+0,
+16676903,
+0,
+-16577738,
+2365010,
+0,
+2198183,
+0,
+12214023,
+1201479,
+0,
+1021183,
+0,
+14554554,
+739666,
+0,
+554025,
+0,
+15483525,
+16722789,
+0,
+16720714,
+0,
+-16666287,
+3953214,
+0,
+3464275,
+0,
+9359728,
+2180807,
+0,
+1624291,
+0,
+12972118,
+1423936,
+0,
+838564,
+0,
+14514716,
+16748282,
+0,
+16744535,
+0,
+-16715601,
+6353786,
+0,
+5003926,
+0,
+5419504,
+3973108,
+0,
+2314944,
+0,
+10489165,
+2837511,
+0,
+1032284,
+0,
+12907421,
+16763496,
+0,
+16756735,
+0,
+-16743015,
+9775978,
+0,
+6325602,
+0,
+675636,
+7269959,
+0,
+2584558,
+0,
+6922698,
+5878520,
+0,
+507384,
+0,
+10391313,
+16773826,
+0,
+16761629,
+0,
+-16758239,
+14526462,
+0,
+6429723,
+0,
+-4178968,
+13351086,
+0,
+1026117,
+0,
+2400012,
+12566846,
+0,
+-2579306,
+0,
+6789676,
+16782950,
+0,
+16760954,
+0,
+-16766688,
+21346996,
+0,
+3817102,
+0,
+-8386881,
+24548257,
+0,
+-5261828,
+0,
+-2509212,
+27136746,
+0,
+-12602908,
+0,
+2243378,
+16794129,
+0,
+16754463,
+0,
+-16771376,
+31942756,
+0,
+-3625011,
+0,
+-11540529,
+45048673,
+0,
+-21256423,
+0,
+-7015034,
+57646140,
+0,
+-38203817,
+0,
+-2665107,
+16811358,
+0,
+16739835,
+0,
+-16773977,
+49676415,
+0,
+-19243342,
+0,
+-13655857,
+82339984,
+0,
+-55005915,
+0,
+-10556853,
+118287496,
+0,
+-94363999,
+0,
+-7146281,
+16840799,
+0,
+16711837,
+0,
+-16775419,
+80691383,
+0,
+-48942961,
+0,
+-14971206,
+149858505,
+0,
+-120064524,
+0,
+-13016765,
+233520652,
+0,
+-206090695,
+0,
+-10652741,
+16892981,
+0,
+16660455,
+0,
+-16776220,
+136000868,
+0,
+-103472696,
+0,
+-15750956,
+271801469,
+0,
+-240442250,
+0,
+-14582003,
+446309601,
+0,
+-416452524,
+0,
+-13079862,
diff --git a/media/libeffects/testlibs/AudioShelvingFilter.cpp b/media/libeffects/testlibs/AudioShelvingFilter.cpp
new file mode 100644
index 0000000..b8650ba
--- /dev/null
+++ b/media/libeffects/testlibs/AudioShelvingFilter.cpp
@@ -0,0 +1,109 @@
+/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.cpp
+**
+** Copyright 2009, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include "AudioShelvingFilter.h"
+#include "AudioCommon.h"
+#include "EffectsMath.h"
+
+#include <new>
+#include <assert.h>
+
+#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
+#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
+
+namespace android {
+// Format of the coefficient tables:
+// kCoefTable[freq][gain][coef]
+// freq - cutoff frequency, in octaves below Nyquist,from -10 to -6 in low
+// shelf, -2 to 0 in high shelf.
+// gain - gain, in millibel, starting at -9600, jumps of 1024, to 4736 millibel.
+// coef - 0: b0
+// 1: b1
+// 2: b2
+// 3: -a1
+// 4: -a2
+static const size_t kHiInDims[2] = {3, 15};
+static const audio_coef_t kHiCoefTable[3*15*5] = {
+#include "AudioHighShelfFilterCoef.inl"
+};
+static const size_t kLoInDims[2] = {5, 15};
+static const audio_coef_t kLoCoefTable[5*15*5] = {
+#include "AudioLowShelfFilterCoef.inl"
+};
+
+AudioCoefInterpolator AudioShelvingFilter::mHiCoefInterp(2, kHiInDims, 5, (const audio_coef_t*) kHiCoefTable);
+AudioCoefInterpolator AudioShelvingFilter::mLoCoefInterp(2, kLoInDims, 5, (const audio_coef_t*) kLoCoefTable);
+
+AudioShelvingFilter::AudioShelvingFilter(ShelfType type, int nChannels,
+ int sampleRate)
+ : mType(type),
+ mBiquad(nChannels, sampleRate) {
+ configure(nChannels, sampleRate);
+}
+
+void AudioShelvingFilter::configure(int nChannels, int sampleRate) {
+ mNiquistFreq = sampleRate * 500;
+ mFrequencyFactor = ((1ull) << 42) / mNiquistFreq;
+ mBiquad.configure(nChannels, sampleRate);
+ setFrequency(mNominalFrequency);
+ commit(true);
+}
+
+void AudioShelvingFilter::reset() {
+ setGain(0);
+ setFrequency(mType == kLowShelf ? 0 : mNiquistFreq);
+ commit(true);
+}
+
+void AudioShelvingFilter::setFrequency(uint32_t millihertz) {
+ mNominalFrequency = millihertz;
+ if (UNLIKELY(millihertz > mNiquistFreq / 2)) {
+ millihertz = mNiquistFreq / 2;
+ }
+ uint32_t normFreq = static_cast<uint32_t>(
+ (static_cast<uint64_t>(millihertz) * mFrequencyFactor) >> 10);
+ uint32_t log2minFreq = (mType == kLowShelf ? (32-10) : (32-2));
+ if (LIKELY(normFreq > (1U << log2minFreq))) {
+ mFrequency = (Effects_log2(normFreq) - (log2minFreq << 15)) << (FREQ_PRECISION_BITS - 15);
+ } else {
+ mFrequency = 0;
+ }
+}
+
+void AudioShelvingFilter::setGain(int32_t millibel) {
+ mGain = millibel + 9600;
+}
+
+void AudioShelvingFilter::commit(bool immediate) {
+ audio_coef_t coefs[5];
+ int intCoord[2] = {
+ mFrequency >> FREQ_PRECISION_BITS,
+ mGain >> GAIN_PRECISION_BITS
+ };
+ uint32_t fracCoord[2] = {
+ mFrequency << (32 - FREQ_PRECISION_BITS),
+ static_cast<uint32_t>(mGain) << (32 - GAIN_PRECISION_BITS)
+ };
+ if (mType == kHighShelf) {
+ mHiCoefInterp.getCoef(intCoord, fracCoord, coefs);
+ } else {
+ mLoCoefInterp.getCoef(intCoord, fracCoord, coefs);
+ }
+ mBiquad.setCoefs(coefs, immediate);
+}
+
+}
diff --git a/media/libeffects/testlibs/AudioShelvingFilter.h b/media/libeffects/testlibs/AudioShelvingFilter.h
new file mode 100644
index 0000000..f72d793
--- /dev/null
+++ b/media/libeffects/testlibs/AudioShelvingFilter.h
@@ -0,0 +1,146 @@
+/* /android/src/frameworks/base/libs/audioflinger/AudioShelvingFilter.h
+**
+** Copyright 2009, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef AUDIO_SHELVING_FILTER_H
+#define AUDIO_SHELVING_FILTER_H
+
+#include "AudioBiquadFilter.h"
+#include "AudioCoefInterpolator.h"
+
+namespace android {
+
+// A shelving audio filter, with unity skirt gain, and controllable cutoff
+// frequency and gain.
+// This filter is able to suppress introduce discontinuities and other artifacts
+// in the output, even when changing parameters abruptly.
+// Parameters can be set to any value - this class will make sure to clip them
+// when they are out of supported range.
+//
+// Implementation notes:
+// This class uses an underlying biquad filter whose parameters are determined
+// using a linear interpolation from a coefficient table, using a
+// AudioCoefInterpolator.
+// All is left for this class to do is mapping between high-level parameters to
+// fractional indices into the coefficient table.
+class AudioShelvingFilter {
+public:
+ // Shelf type
+ enum ShelfType {
+ kLowShelf,
+ kHighShelf
+ };
+
+ // Constructor. Resets the filter (see reset()).
+ // type Type of the filter (high shelf or low shelf).
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ AudioShelvingFilter(ShelfType type, int nChannels, int sampleRate);
+
+ // Reconfiguration of the filter. Changes input/output format, but does not
+ // alter current parameter values. Clears delay lines.
+ // nChannels Number of input/output channels (interlaced).
+ // sampleRate The input/output sample rate, in Hz.
+ void configure(int nChannels, int sampleRate);
+
+ // Resets the filter parameters to the following values:
+ // frequency: 0
+ // gain: 0
+ // It also disables the filter. Does not clear the delay lines.
+ void reset();
+
+ // Clears delay lines. Does not alter parameter values.
+ void clear() { mBiquad.clear(); }
+
+ // Sets gain value. Actual change will only take place upon commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // millibel Gain value in millibel (1/100 of decibel).
+ void setGain(int32_t millibel);
+
+ // Gets the gain, in millibel, as set.
+ int32_t getGain() const { return mGain - 9600; }
+
+ // Sets cutoff frequency value. Actual change will only take place upon
+ // commit().
+ // This value will be remembered even if the filter is in disabled() state.
+ // millihertz Frequency value in mHz.
+ void setFrequency(uint32_t millihertz);
+
+ // Gets the frequency, in mHz, as set.
+ uint32_t getFrequency() const { return mNominalFrequency; }
+
+ // Applies all parameter changes done to this point in time.
+ // If the filter is disabled, the new parameters will take place when it is
+ // enabled again. Does not introduce artifacts, unless immediate is set.
+ // immediate Whether to apply change abruptly (ignored if filter is
+ // disabled).
+ void commit(bool immediate = false);
+
+ // Process a buffer of input data. The input and output should contain
+ // frameCount * nChannels interlaced samples. Processing can be done
+ // in-place, by passing the same buffer as both arguments.
+ // in Input buffer.
+ // out Output buffer.
+ // frameCount Number of frames to produce.
+ void process(const audio_sample_t in[], audio_sample_t out[],
+ int frameCount) { mBiquad.process(in, out, frameCount); }
+
+ // Enables the filter, so it would start processing input. Does not
+ // introduce artifacts, unless immediate is set.
+ // immediate Whether to apply change abruptly.
+ void enable(bool immediate = false) { mBiquad.enable(immediate); }
+
+ // Disabled (bypasses) the filter. Does not introduce artifacts, unless
+ // immediate is set.
+ // immediate Whether to apply change abruptly.
+ void disable(bool immediate = false) { mBiquad.disable(immediate); }
+
+private:
+ // Precision for the mFrequency member.
+ static const int FREQ_PRECISION_BITS = 26;
+ // Precision for the mGain member.
+ static const int GAIN_PRECISION_BITS = 10;
+
+ // Shelf type.
+ ShelfType mType;
+ // Nyquist, in mHz.
+ uint32_t mNiquistFreq;
+ // Fractional index into the gain dimension of the coef table in
+ // GAIN_PRECISION_BITS precision.
+ int32_t mGain;
+ // Fractional index into the frequency dimension of the coef table in
+ // FREQ_PRECISION_BITS precision.
+ uint32_t mFrequency;
+ // Nominal value of frequency, as set.
+ uint32_t mNominalFrequency;
+ // 1/Nyquist[mHz], in 42-bit precision (very small).
+ // Used for scaling the frequency.
+ uint32_t mFrequencyFactor;
+
+ // A biquad filter, used for the actual processing.
+ AudioBiquadFilter mBiquad;
+ // A coefficient interpolator, used for mapping the high level parameters to
+ // the low-level biquad coefficients. This one is used for the high shelf.
+ static AudioCoefInterpolator mHiCoefInterp;
+ // A coefficient interpolator, used for mapping the high level parameters to
+ // the low-level biquad coefficients. This one is used for the low shelf.
+ static AudioCoefInterpolator mLoCoefInterp;
+};
+
+}
+
+
+#endif // AUDIO_SHELVING_FILTER_H
diff --git a/media/libeffects/testlibs/EffectEqualizer.cpp b/media/libeffects/testlibs/EffectEqualizer.cpp
new file mode 100644
index 0000000..a71f236
--- /dev/null
+++ b/media/libeffects/testlibs/EffectEqualizer.cpp
@@ -0,0 +1,654 @@
+/*
+ * Copyright (C) 2009 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Equalizer"
+#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
+//
+#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include "AudioEqualizer.h"
+#include "AudioBiquadFilter.h"
+#include "AudioFormatAdapter.h"
+#include <media/EffectEqualizerApi.h>
+
+// effect_interface_t interface implementation for equalizer effect
+extern "C" const struct effect_interface_s gEqualizerInterface;
+
+enum equalizer_state_e {
+ EQUALIZER_STATE_UNINITIALIZED,
+ EQUALIZER_STATE_INITIALIZED,
+ EQUALIZER_STATE_ACTIVE,
+};
+
+namespace android {
+namespace {
+
+// Google Graphic Equalizer UUID: e25aa840-543b-11df-98a5-0002a5d5c51b
+const effect_descriptor_t gEqualizerDescriptor = {
+ {0x0bed4300, 0xddd6, 0x11db, 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xe25aa840, 0x543b, 0x11df, 0x98a5, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_LAST),
+ 0, // TODO
+ 1,
+ "Graphic Equalizer",
+ "Google Inc.",
+};
+
+/////////////////// BEGIN EQ PRESETS ///////////////////////////////////////////
+const int kNumBands = 5;
+const uint32_t gFreqs[kNumBands] = { 50000, 125000, 900000, 3200000, 6300000 };
+const uint32_t gBandwidths[kNumBands] = { 0, 3600, 3600, 2400, 0 };
+
+const AudioEqualizer::BandConfig gBandsClassic[kNumBands] = {
+ { 300, gFreqs[0], gBandwidths[0] },
+ { 400, gFreqs[1], gBandwidths[1] },
+ { 0, gFreqs[2], gBandwidths[2] },
+ { 200, gFreqs[3], gBandwidths[3] },
+ { -300, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsJazz[kNumBands] = {
+ { -600, gFreqs[0], gBandwidths[0] },
+ { 200, gFreqs[1], gBandwidths[1] },
+ { 400, gFreqs[2], gBandwidths[2] },
+ { -400, gFreqs[3], gBandwidths[3] },
+ { -600, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsPop[kNumBands] = {
+ { 400, gFreqs[0], gBandwidths[0] },
+ { -400, gFreqs[1], gBandwidths[1] },
+ { 300, gFreqs[2], gBandwidths[2] },
+ { -400, gFreqs[3], gBandwidths[3] },
+ { 600, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::BandConfig gBandsRock[kNumBands] = {
+ { 700, gFreqs[0], gBandwidths[0] },
+ { 400, gFreqs[1], gBandwidths[1] },
+ { -400, gFreqs[2], gBandwidths[2] },
+ { 400, gFreqs[3], gBandwidths[3] },
+ { 200, gFreqs[4], gBandwidths[4] }
+};
+
+const AudioEqualizer::PresetConfig gEqualizerPresets[] = {
+ { "Classic", gBandsClassic },
+ { "Jazz", gBandsJazz },
+ { "Pop", gBandsPop },
+ { "Rock", gBandsRock }
+};
+
+/////////////////// END EQ PRESETS /////////////////////////////////////////////
+
+static const size_t kBufferSize = 32;
+
+typedef AudioFormatAdapter<AudioEqualizer, kBufferSize> FormatAdapter;
+
+struct EqualizerContext {
+ const struct effect_interface_s *itfe;
+ effect_config_t config;
+ FormatAdapter adapter;
+ AudioEqualizer * pEqualizer;
+ uint32_t state;
+};
+
+//--- local function prototypes
+
+int Equalizer_init(EqualizerContext *pContext);
+int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig);
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue);
+int Equalizer_setParameter(AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue);
+
+
+//
+//--- Effect Library Interface Implementation
+//
+
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+ *pNumEffects = 1;
+ return 0;
+} /* end EffectQueryNumberEffects */
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+ if (pDescriptor == NULL) {
+ return -EINVAL;
+ }
+ if (index > 0) {
+ return -EINVAL;
+ }
+ memcpy(pDescriptor, &gEqualizerDescriptor, sizeof(effect_descriptor_t));
+ return 0;
+} /* end EffectQueryNext */
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface) {
+ int ret;
+ int i;
+
+ LOGV("EffectLibCreateEffect start");
+
+ if (pInterface == NULL || uuid == NULL) {
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gEqualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
+ return -EINVAL;
+ }
+
+ EqualizerContext *pContext = new EqualizerContext;
+
+ pContext->itfe = &gEqualizerInterface;
+ pContext->pEqualizer = NULL;
+ pContext->state = EQUALIZER_STATE_UNINITIALIZED;
+
+ ret = Equalizer_init(pContext);
+ if (ret < 0) {
+ LOGW("EffectLibCreateEffect() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pInterface = (effect_interface_t)pContext;
+ pContext->state = EQUALIZER_STATE_INITIALIZED;
+
+ LOGV("EffectLibCreateEffect %p, size %d", pContext, AudioEqualizer::GetInstanceSize(kNumBands)+sizeof(EqualizerContext));
+
+ return 0;
+
+} /* end EffectCreate */
+
+extern "C" int EffectRelease(effect_interface_t interface) {
+ EqualizerContext * pContext = (EqualizerContext *)interface;
+
+ LOGV("EffectLibReleaseEffect %p", interface);
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+
+ pContext->state = EQUALIZER_STATE_UNINITIALIZED;
+ pContext->pEqualizer->free();
+ delete pContext;
+
+ return 0;
+} /* end EffectRelease */
+
+
+//
+//--- local functions
+//
+
+#define CHECK_ARG(cond) { \
+ if (!(cond)) { \
+ LOGV("Invalid argument: "#cond); \
+ return -EINVAL; \
+ } \
+}
+
+//----------------------------------------------------------------------------
+// Equalizer_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_configure(EqualizerContext *pContext, effect_config_t *pConfig)
+{
+ LOGV("Equalizer_configure start");
+
+ CHECK_ARG(pContext != NULL);
+ CHECK_ARG(pConfig != NULL);
+
+ CHECK_ARG(pConfig->inputCfg.samplingRate == pConfig->outputCfg.samplingRate);
+ CHECK_ARG(pConfig->inputCfg.channels == pConfig->outputCfg.channels);
+ CHECK_ARG(pConfig->inputCfg.format == pConfig->outputCfg.format);
+ CHECK_ARG((pConfig->inputCfg.channels == CHANNEL_MONO) || (pConfig->inputCfg.channels == CHANNEL_STEREO));
+ CHECK_ARG(pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE
+ || pConfig->outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+ CHECK_ARG(pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S7_24
+ || pConfig->inputCfg.format == SAMPLE_FORMAT_PCM_S15);
+
+ int channelCount;
+ if (pConfig->inputCfg.channels == CHANNEL_MONO) {
+ channelCount = 1;
+ } else {
+ channelCount = 2;
+ }
+ CHECK_ARG(channelCount <= AudioBiquadFilter::MAX_CHANNELS);
+
+ memcpy(&pContext->config, pConfig, sizeof(effect_config_t));
+
+ pContext->pEqualizer->configure(channelCount,
+ pConfig->inputCfg.samplingRate);
+
+ pContext->adapter.configure(*pContext->pEqualizer, channelCount,
+ pConfig->inputCfg.format,
+ pConfig->outputCfg.accessMode);
+
+ return 0;
+} // end Equalizer_configure
+
+
+//----------------------------------------------------------------------------
+// Equalizer_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration and creates
+// AudioEqualizer instance.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_init(EqualizerContext *pContext)
+{
+ int status;
+
+ LOGV("Equalizer_init start");
+
+ CHECK_ARG(pContext != NULL);
+
+ if (pContext->pEqualizer != NULL) {
+ pContext->pEqualizer->free();
+ }
+
+ pContext->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pContext->config.inputCfg.channels = CHANNEL_STEREO;
+ pContext->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->config.inputCfg.samplingRate = 44100;
+ pContext->config.inputCfg.bufferProvider.getBuffer = NULL;
+ pContext->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->config.inputCfg.bufferProvider.cookie = NULL;
+ pContext->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+ pContext->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pContext->config.outputCfg.channels = CHANNEL_STEREO;
+ pContext->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->config.outputCfg.samplingRate = 44100;
+ pContext->config.outputCfg.bufferProvider.getBuffer = NULL;
+ pContext->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->config.outputCfg.bufferProvider.cookie = NULL;
+ pContext->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ pContext->pEqualizer = AudioEqualizer::CreateInstance(
+ NULL,
+ kNumBands,
+ AudioBiquadFilter::MAX_CHANNELS,
+ 44100,
+ gEqualizerPresets,
+ ARRAY_SIZE(gEqualizerPresets));
+
+ for (int i = 0; i < kNumBands; ++i) {
+ pContext->pEqualizer->setFrequency(i, gFreqs[i]);
+ pContext->pEqualizer->setBandwidth(i, gBandwidths[i]);
+ }
+
+ pContext->pEqualizer->enable(true);
+
+ Equalizer_configure(pContext, &pContext->config);
+
+ return 0;
+} // end Equalizer_init
+
+
+//----------------------------------------------------------------------------
+// Equalizer_getParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Get a Equalizer parameter
+//
+// Inputs:
+// pEqualizer - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to variable to hold retrieved value
+// pValueSize - pointer to value size: maximum size as input
+//
+// Outputs:
+// *pValue updated with parameter value
+// *pValueSize updated with actual value size
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_getParameter(AudioEqualizer * pEqualizer, int32_t *pParam, size_t *pValueSize, void *pValue)
+{
+ int status = 0;
+ int32_t param = *pParam++;
+ int32_t param2;
+ char *name;
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ case EQ_PARAM_CUR_PRESET:
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ if (*pValueSize < sizeof(int16_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int16_t);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ if (*pValueSize < 2 * sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = 2 * sizeof(int32_t);
+ break;
+ case EQ_PARAM_BAND_LEVEL:
+ case EQ_PARAM_GET_BAND:
+ case EQ_PARAM_CENTER_FREQ:
+ if (*pValueSize < sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ *pValueSize = sizeof(int32_t);
+ break;
+
+ case EQ_PARAM_GET_PRESET_NAME:
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ switch (param) {
+ case EQ_PARAM_NUM_BANDS:
+ *(int16_t *)pValue = kNumBands;
+ LOGV("Equalizer_getParameter() EQ_PARAM_NUM_BANDS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_LEVEL_RANGE:
+ *(int32_t *)pValue = -9600;
+ *((int32_t *)pValue + 1) = 4800;
+ LOGV("Equalizer_getParameter() EQ_PARAM_LEVEL_RANGE min %d, max %d", *(int32_t *)pValue, *((int32_t *)pValue + 1));
+ break;
+
+ case EQ_PARAM_BAND_LEVEL:
+ param2 = *pParam;
+ if (param2 >= kNumBands) {
+ status = -EINVAL;
+ break;
+ }
+ *(int32_t *)pValue = pEqualizer->getGain(param2);
+ LOGV("Equalizer_getParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_CENTER_FREQ:
+ param2 = *pParam;
+ if (param2 >= kNumBands) {
+ status = -EINVAL;
+ break;
+ }
+ *(int32_t *)pValue = pEqualizer->getFrequency(param2);
+ LOGV("Equalizer_getParameter() EQ_PARAM_CENTER_FREQ band %d, frequency %d", param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_BAND_FREQ_RANGE:
+ param2 = *pParam;
+ if (param2 >= kNumBands) {
+ status = -EINVAL;
+ break;
+ }
+ pEqualizer->getBandRange(param2, *(uint32_t *)pValue, *((uint32_t *)pValue + 1));
+ LOGV("Equalizer_getParameter() EQ_PARAM_BAND_FREQ_RANGE band %d, min %d, max %d", param2, *(int32_t *)pValue, *((int32_t *)pValue + 1));
+ break;
+
+ case EQ_PARAM_GET_BAND:
+ param2 = *pParam;
+ *(int32_t *)pValue = pEqualizer->getMostRelevantBand(param2);
+ LOGV("Equalizer_getParameter() EQ_PARAM_GET_BAND frequency %d, band %d", param2, *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_CUR_PRESET:
+ *(int16_t *)pValue = pEqualizer->getPreset();
+ LOGV("Equalizer_getParameter() EQ_PARAM_CUR_PRESET %d", *(int32_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_NUM_OF_PRESETS:
+ *(int16_t *)pValue = pEqualizer->getNumPresets();
+ LOGV("Equalizer_getParameter() EQ_PARAM_GET_NUM_OF_PRESETS %d", *(int16_t *)pValue);
+ break;
+
+ case EQ_PARAM_GET_PRESET_NAME:
+ param2 = *pParam;
+ if (param2 >= pEqualizer->getNumPresets()) {
+ status = -EINVAL;
+ break;
+ }
+ name = (char *)pValue;
+ strncpy(name, pEqualizer->getPresetName(param2), *pValueSize - 1);
+ name[*pValueSize - 1] = 0;
+ *pValueSize = strlen(name) + 1;
+ LOGV("Equalizer_getParameter() EQ_PARAM_GET_PRESET_NAME preset %d, name %s len %d", param2, gEqualizerPresets[param2].name, *pValueSize);
+ break;
+
+ default:
+ LOGV("Equalizer_getParameter() invalid param %d", param);
+ status = -EINVAL;
+ break;
+ }
+
+ return status;
+} // end Equalizer_getParameter
+
+
+//----------------------------------------------------------------------------
+// Equalizer_setParameter()
+//----------------------------------------------------------------------------
+// Purpose:
+// Set a Equalizer parameter
+//
+// Inputs:
+// pEqualizer - handle to instance data
+// pParam - pointer to parameter
+// pValue - pointer to value
+//
+// Outputs:
+//
+//
+// Side Effects:
+//
+//----------------------------------------------------------------------------
+
+int Equalizer_setParameter (AudioEqualizer * pEqualizer, int32_t *pParam, void *pValue)
+{
+ int status = 0;
+ int32_t preset;
+ int32_t band;
+ int32_t level;
+ int32_t param = *pParam++;
+
+
+ switch (param) {
+ case EQ_PARAM_CUR_PRESET:
+ preset = *(int16_t *)pValue;
+
+ LOGV("setParameter() EQ_PARAM_CUR_PRESET %d", preset);
+ if (preset >= pEqualizer->getNumPresets()) {
+ status = -EINVAL;
+ break;
+ }
+ pEqualizer->setPreset(preset);
+ pEqualizer->commit(true);
+ break;
+ case EQ_PARAM_BAND_LEVEL:
+ band = *pParam;
+ level = *(int32_t *)pValue;
+ LOGV("setParameter() EQ_PARAM_BAND_LEVEL band %d, level %d", band, level);
+ if (band >= kNumBands) {
+ status = -EINVAL;
+ break;
+ }
+ pEqualizer->setGain(band, level);
+ pEqualizer->commit(true);
+ break;
+ default:
+ LOGV("setParameter() invalid param %d", param);
+ break;
+ }
+
+ return status;
+} // end Equalizer_setParameter
+
+} // namespace
+} // namespace
+
+
+//
+//--- Effect Control Interface Implementation
+//
+
+extern "C" int Equalizer_process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+ android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount) {
+ return -EINVAL;
+ }
+
+ if (pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+ if (pContext->state == EQUALIZER_STATE_INITIALIZED) {
+ return -ENODATA;
+ }
+
+ pContext->adapter.process(inBuffer->raw, outBuffer->raw, outBuffer->frameCount);
+
+ return 0;
+} // end Equalizer_process
+
+extern "C" int Equalizer_command(effect_interface_t self, uint32_t cmdCode, uint32_t cmdSize,
+ void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+ android::EqualizerContext * pContext = (android::EqualizerContext *) self;
+ int retsize;
+
+ if (pContext == NULL || pContext->state == EQUALIZER_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+ android::AudioEqualizer * pEqualizer = pContext->pEqualizer;
+
+ LOGV("Equalizer_command command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode) {
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Equalizer_init(pContext);
+ break;
+ case EFFECT_CMD_CONFIGURE:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Equalizer_configure(pContext,
+ (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_RESET:
+ Equalizer_configure(pContext, &pContext->config);
+ break;
+ case EFFECT_CMD_GET_PARAM: {
+ if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL || *replySize < (int) (sizeof(effect_param_t) + sizeof(int32_t))) {
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *)pCmdData;
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + p->psize);
+ p = (effect_param_t *)pReplyData;
+ int voffset = ((p->psize - 1) / sizeof(int32_t) + 1) * sizeof(int32_t);
+ p->status = android::Equalizer_getParameter(pEqualizer, (int32_t *)p->data, &p->vsize,
+ p->data + voffset);
+ *replySize = sizeof(effect_param_t) + voffset + p->vsize;
+ LOGV("Equalizer_command EFFECT_CMD_GET_PARAM *pCmdData %d, *replySize %d, *pReplyData %08x %08x",
+ *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)), *replySize,
+ *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset),
+ *(int32_t *)((char *)pReplyData + sizeof(effect_param_t) + voffset + sizeof(int32_t)));
+
+ } break;
+ case EFFECT_CMD_SET_PARAM: {
+ LOGV("Equalizer_command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
+ if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL || *replySize != sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ effect_param_t *p = (effect_param_t *) pCmdData;
+ *(int *)pReplyData = android::Equalizer_setParameter(pEqualizer, (int32_t *)p->data,
+ p->data + p->psize);
+ } break;
+ case EFFECT_CMD_ENABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pContext->state != EQUALIZER_STATE_INITIALIZED) {
+ return -ENOSYS;
+ }
+ pContext->state = EQUALIZER_STATE_ACTIVE;
+ LOGV("EFFECT_CMD_ENABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pContext->state != EQUALIZER_STATE_ACTIVE) {
+ return -ENOSYS;
+ }
+ pContext->state = EQUALIZER_STATE_INITIALIZED;
+ LOGV("EFFECT_CMD_DISABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+ default:
+ LOGW("Equalizer_command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+// effect_interface_t interface implementation for equalizer effect
+const struct effect_interface_s gEqualizerInterface = {
+ Equalizer_process,
+ Equalizer_command
+};
+
+
diff --git a/media/libeffects/testlibs/EffectReverb.c b/media/libeffects/testlibs/EffectReverb.c
new file mode 100644
index 0000000..3eb8b2c
--- /dev/null
+++ b/media/libeffects/testlibs/EffectReverb.c
@@ -0,0 +1,2135 @@
+/*
+ * Copyright (C) 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectReverb"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "EffectReverb.h"
+#include "EffectsMath.h"
+
+// effect_interface_t interface implementation for reverb effect
+const struct effect_interface_s gReverbInterface = {
+ Reverb_Process,
+ Reverb_Command
+};
+
+// Google auxiliary environmental reverb UUID: 1f0ae2e0-4ef7-11df-bc09-0002a5d5c51b
+static const effect_descriptor_t gAuxEnvReverbDescriptor = {
+ {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+ {0x1f0ae2e0, 0x4ef7, 0x11df, 0xbc09, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ // flags other than EFFECT_FLAG_TYPE_AUXILIARY set for test purpose
+ EFFECT_FLAG_TYPE_AUXILIARY | EFFECT_FLAG_DEVICE_IND | EFFECT_FLAG_AUDIO_MODE_IND,
+ 0, // TODO
+ 33,
+ "Aux Environmental Reverb",
+ "Google Inc."
+};
+
+// Google insert environmental reverb UUID: aa476040-6342-11df-91a4-0002a5d5c51b
+static const effect_descriptor_t gInsertEnvReverbDescriptor = {
+ {0xc2e5d5f0, 0x94bd, 0x4763, 0x9cac, {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}},
+ {0xaa476040, 0x6342, 0x11df, 0x91a4, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 33,
+ "Insert Environmental reverb",
+ "Google Inc."
+};
+
+// Google auxiliary preset reverb UUID: 63909320-53a6-11df-bdbd-0002a5d5c51b
+static const effect_descriptor_t gAuxPresetReverbDescriptor = {
+ {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0x63909320, 0x53a6, 0x11df, 0xbdbd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ EFFECT_FLAG_TYPE_AUXILIARY,
+ 0, // TODO
+ 33,
+ "Aux Preset Reverb",
+ "Google Inc."
+};
+
+// Google insert preset reverb UUID: d93dc6a0-6342-11df-b128-0002a5d5c51b
+static const effect_descriptor_t gInsertPresetReverbDescriptor = {
+ {0x47382d60, 0xddd8, 0x11db, 0xbf3a, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ {0xd93dc6a0, 0x6342, 0x11df, 0xb128, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
+ EFFECT_API_VERSION,
+ EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+ 0, // TODO
+ 33,
+ "Insert Preset Reverb",
+ "Google Inc."
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+ &gAuxEnvReverbDescriptor,
+ &gInsertEnvReverbDescriptor,
+ &gAuxPresetReverbDescriptor,
+ &gInsertPresetReverbDescriptor
+};
+
+/*----------------------------------------------------------------------------
+ * Effect API implementation
+ *--------------------------------------------------------------------------*/
+
+/*--- Effect Library Interface Implementation ---*/
+
+int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+ *pNumEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+ return 0;
+}
+
+int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+ if (pDescriptor == NULL) {
+ return -EINVAL;
+ }
+ if (index >= sizeof(gDescriptors) / sizeof(const effect_descriptor_t *)) {
+ return -EINVAL;
+ }
+ memcpy(pDescriptor, gDescriptors[index],
+ sizeof(effect_descriptor_t));
+ return 0;
+}
+
+int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface) {
+ int ret;
+ int i;
+ reverb_module_t *module;
+ const effect_descriptor_t *desc;
+ int aux = 0;
+ int preset = 0;
+
+ LOGV("EffectLibCreateEffect start");
+
+ if (pInterface == NULL || uuid == NULL) {
+ return -EINVAL;
+ }
+
+ for (i = 0; gDescriptors[i] != NULL; i++) {
+ desc = gDescriptors[i];
+ if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t))
+ == 0) {
+ break;
+ }
+ }
+
+ if (gDescriptors[i] == NULL) {
+ return -ENOENT;
+ }
+
+ module = malloc(sizeof(reverb_module_t));
+
+ module->itfe = &gReverbInterface;
+
+ module->context.mState = REVERB_STATE_UNINITIALIZED;
+
+ if (memcmp(&desc->type, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+ preset = 1;
+ }
+ if ((desc->flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ aux = 1;
+ }
+ ret = Reverb_Init(module, aux, preset);
+ if (ret < 0) {
+ LOGW("EffectLibCreateEffect() init failed");
+ free(module);
+ return ret;
+ }
+
+ *pInterface = (effect_interface_t) module;
+
+ module->context.mState = REVERB_STATE_INITIALIZED;
+
+ LOGV("EffectLibCreateEffect %p ,size %d", module, sizeof(reverb_module_t));
+
+ return 0;
+}
+
+int EffectRelease(effect_interface_t interface) {
+ reverb_module_t *pRvbModule = (reverb_module_t *)interface;
+
+ LOGV("EffectLibReleaseEffect %p", interface);
+ if (interface == NULL) {
+ return -EINVAL;
+ }
+
+ pRvbModule->context.mState = REVERB_STATE_UNINITIALIZED;
+
+ free(pRvbModule);
+ return 0;
+}
+
+
+/*--- Effect Control Interface Implementation ---*/
+
+static int Reverb_Process(effect_interface_t self, audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+ reverb_object_t *pReverb;
+ int16_t *pSrc, *pDst;
+ reverb_module_t *pRvbModule = (reverb_module_t *)self;
+
+ if (pRvbModule == NULL) {
+ return -EINVAL;
+ }
+
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount) {
+ return -EINVAL;
+ }
+
+ pReverb = (reverb_object_t*) &pRvbModule->context;
+
+ if (pReverb->mState == REVERB_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+ if (pReverb->mState == REVERB_STATE_INITIALIZED) {
+ return -ENODATA;
+ }
+
+ //if bypassed or the preset forces the signal to be completely dry
+ if (pReverb->m_bBypass != 0) {
+ if (inBuffer->raw != outBuffer->raw) {
+ int16_t smp;
+ pSrc = inBuffer->s16;
+ pDst = outBuffer->s16;
+ size_t count = inBuffer->frameCount;
+ if (pRvbModule->config.inputCfg.channels == pRvbModule->config.outputCfg.channels) {
+ count *= 2;
+ while (count--) {
+ *pDst++ = *pSrc++;
+ }
+ } else {
+ while (count--) {
+ smp = *pSrc++;
+ *pDst++ = smp;
+ *pDst++ = smp;
+ }
+ }
+ }
+ return 0;
+ }
+
+ if (pReverb->m_nNextRoom != pReverb->m_nCurrentRoom) {
+ ReverbUpdateRoom(pReverb, true);
+ }
+
+ pSrc = inBuffer->s16;
+ pDst = outBuffer->s16;
+ size_t numSamples = outBuffer->frameCount;
+ while (numSamples) {
+ uint32_t processedSamples;
+ if (numSamples > (uint32_t) pReverb->m_nUpdatePeriodInSamples) {
+ processedSamples = (uint32_t) pReverb->m_nUpdatePeriodInSamples;
+ } else {
+ processedSamples = numSamples;
+ }
+
+ /* increment update counter */
+ pReverb->m_nUpdateCounter += (int16_t) processedSamples;
+ /* check if update counter needs to be reset */
+ if (pReverb->m_nUpdateCounter >= pReverb->m_nUpdatePeriodInSamples) {
+ /* update interval has elapsed, so reset counter */
+ pReverb->m_nUpdateCounter -= pReverb->m_nUpdatePeriodInSamples;
+ ReverbUpdateXfade(pReverb, pReverb->m_nUpdatePeriodInSamples);
+
+ } /* end if m_nUpdateCounter >= update interval */
+
+ Reverb(pReverb, processedSamples, pDst, pSrc);
+
+ numSamples -= processedSamples;
+ if (pReverb->m_Aux) {
+ pSrc += processedSamples;
+ } else {
+ pSrc += processedSamples * NUM_OUTPUT_CHANNELS;
+ }
+ pDst += processedSamples * NUM_OUTPUT_CHANNELS;
+ }
+
+ return 0;
+}
+
+
+static int Reverb_Command(effect_interface_t self, uint32_t cmdCode, uint32_t cmdSize,
+ void *pCmdData, uint32_t *replySize, void *pReplyData) {
+ reverb_module_t *pRvbModule = (reverb_module_t *) self;
+ reverb_object_t *pReverb;
+ int retsize;
+
+ if (pRvbModule == NULL ||
+ pRvbModule->context.mState == REVERB_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+ pReverb = (reverb_object_t*) &pRvbModule->context;
+
+ LOGV("Reverb_Command command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode) {
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Reverb_Init(pRvbModule, pReverb->m_Aux, pReverb->m_Preset);
+ if (*(int *) pReplyData == 0) {
+ pRvbModule->context.mState = REVERB_STATE_INITIALIZED;
+ }
+ break;
+ case EFFECT_CMD_CONFIGURE:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Reverb_Configure(pRvbModule,
+ (effect_config_t *)pCmdData, false);
+ break;
+ case EFFECT_CMD_RESET:
+ Reverb_Reset(pReverb, false);
+ break;
+ case EFFECT_CMD_GET_PARAM:
+ LOGV("Reverb_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",pCmdData, *replySize, pReplyData);
+
+ if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+ pReplyData == NULL || *replySize < (int) sizeof(effect_param_t)) {
+ return -EINVAL;
+ }
+ effect_param_t *rep = (effect_param_t *) pReplyData;
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
+ LOGV("Reverb_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",*(int32_t *)rep->data, rep->vsize);
+ rep->status = Reverb_getParameter(pReverb, *(int32_t *)rep->data, &rep->vsize,
+ rep->data + sizeof(int32_t));
+ *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
+ break;
+ case EFFECT_CMD_SET_PARAM:
+ LOGV("Reverb_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, pReplyData %p",
+ cmdSize, pCmdData, *replySize, pReplyData);
+ if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
+ || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ effect_param_t *cmd = (effect_param_t *) pCmdData;
+ *(int *)pReplyData = Reverb_setParameter(pReverb, *(int32_t *)cmd->data,
+ cmd->vsize, cmd->data + sizeof(int32_t));
+ break;
+ case EFFECT_CMD_ENABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pReverb->mState != REVERB_STATE_INITIALIZED) {
+ return -ENOSYS;
+ }
+ pReverb->mState = REVERB_STATE_ACTIVE;
+ LOGV("EFFECT_CMD_ENABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pReverb->mState != REVERB_STATE_ACTIVE) {
+ return -ENOSYS;
+ }
+ pReverb->mState = REVERB_STATE_INITIALIZED;
+ LOGV("EFFECT_CMD_DISABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_SET_DEVICE:
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ LOGV("Reverb_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
+ break;
+ case EFFECT_CMD_SET_VOLUME: {
+ // audio output is always stereo => 2 channel volumes
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
+ return -EINVAL;
+ }
+ float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
+ float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
+ LOGV("Reverb_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
+ break;
+ }
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+ return -EINVAL;
+ }
+ LOGV("Reverb_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+ break;
+ default:
+ LOGW("Reverb_Command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Reverb internal functions
+ *--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Reverb_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize reverb context and apply default parameters
+ *
+ * Inputs:
+ * pRvbModule - pointer to reverb effect module
+ * aux - indicates if the reverb is used as auxiliary (1) or insert (0)
+ * preset - indicates if the reverb is used in preset (1) or environmental (0) mode
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset) {
+ int ret;
+
+ LOGV("Reverb_Init module %p, aux: %d, preset: %d", pRvbModule,aux, preset);
+
+ memset(&pRvbModule->context, 0, sizeof(reverb_object_t));
+
+ pRvbModule->context.m_Aux = (uint16_t)aux;
+ pRvbModule->context.m_Preset = (uint16_t)preset;
+
+ pRvbModule->config.inputCfg.samplingRate = 44100;
+ if (aux) {
+ pRvbModule->config.inputCfg.channels = CHANNEL_MONO;
+ } else {
+ pRvbModule->config.inputCfg.channels = CHANNEL_STEREO;
+ }
+ pRvbModule->config.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pRvbModule->config.inputCfg.bufferProvider.getBuffer = NULL;
+ pRvbModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pRvbModule->config.inputCfg.bufferProvider.cookie = NULL;
+ pRvbModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pRvbModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+ pRvbModule->config.outputCfg.samplingRate = 44100;
+ pRvbModule->config.outputCfg.channels = CHANNEL_STEREO;
+ pRvbModule->config.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pRvbModule->config.outputCfg.bufferProvider.getBuffer = NULL;
+ pRvbModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pRvbModule->config.outputCfg.bufferProvider.cookie = NULL;
+ pRvbModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pRvbModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ ret = Reverb_Configure(pRvbModule, &pRvbModule->config, true);
+ if (ret < 0) {
+ LOGV("Reverb_Init error %d on module %p", ret, pRvbModule);
+ }
+
+ return ret;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set input and output audio configuration.
+ *
+ * Inputs:
+ * pRvbModule - pointer to reverb effect module
+ * pConfig - pointer to effect_config_t structure containing input
+ * and output audio parameters configuration
+ * init - true if called from init function
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig,
+ bool init) {
+ reverb_object_t *pReverb = &pRvbModule->context;
+ int bufferSizeInSamples;
+ int updatePeriodInSamples;
+ int xfadePeriodInSamples;
+
+ // Check configuration compatibility with build options
+ if (pConfig->inputCfg.samplingRate
+ != pConfig->outputCfg.samplingRate
+ || pConfig->outputCfg.channels != OUTPUT_CHANNELS
+ || pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15
+ || pConfig->outputCfg.format != SAMPLE_FORMAT_PCM_S15) {
+ LOGV("Reverb_Configure invalid config");
+ return -EINVAL;
+ }
+ if ((pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_MONO)) ||
+ (!pReverb->m_Aux && (pConfig->inputCfg.channels != CHANNEL_STEREO))) {
+ LOGV("Reverb_Configure invalid config");
+ return -EINVAL;
+ }
+
+ memcpy(&pRvbModule->config, pConfig, sizeof(effect_config_t));
+
+ pReverb->m_nSamplingRate = pRvbModule->config.outputCfg.samplingRate;
+
+ switch (pReverb->m_nSamplingRate) {
+ case 8000:
+ pReverb->m_nUpdatePeriodInBits = 5;
+ bufferSizeInSamples = 4096;
+ pReverb->m_nCosWT_5KHz = -23170;
+ break;
+ case 16000:
+ pReverb->m_nUpdatePeriodInBits = 6;
+ bufferSizeInSamples = 8192;
+ pReverb->m_nCosWT_5KHz = -12540;
+ break;
+ case 22050:
+ pReverb->m_nUpdatePeriodInBits = 7;
+ bufferSizeInSamples = 8192;
+ pReverb->m_nCosWT_5KHz = 4768;
+ break;
+ case 32000:
+ pReverb->m_nUpdatePeriodInBits = 7;
+ bufferSizeInSamples = 16384;
+ pReverb->m_nCosWT_5KHz = 18205;
+ break;
+ case 44100:
+ pReverb->m_nUpdatePeriodInBits = 8;
+ bufferSizeInSamples = 16384;
+ pReverb->m_nCosWT_5KHz = 24799;
+ break;
+ case 48000:
+ pReverb->m_nUpdatePeriodInBits = 8;
+ bufferSizeInSamples = 16384;
+ pReverb->m_nCosWT_5KHz = 25997;
+ break;
+ default:
+ LOGV("Reverb_Configure invalid sampling rate %d", pReverb->m_nSamplingRate);
+ return -EINVAL;
+ }
+
+ // Define a mask for circular addressing, so that array index
+ // can wraparound and stay in array boundary of 0, 1, ..., (buffer size -1)
+ // The buffer size MUST be a power of two
+ pReverb->m_nBufferMask = (int32_t) (bufferSizeInSamples - 1);
+ /* reverb parameters are updated every 2^(pReverb->m_nUpdatePeriodInBits) samples */
+ updatePeriodInSamples = (int32_t) (0x1L << pReverb->m_nUpdatePeriodInBits);
+ /*
+ calculate the update counter by bitwise ANDING with this value to
+ generate a 2^n modulo value
+ */
+ pReverb->m_nUpdatePeriodInSamples = (int32_t) updatePeriodInSamples;
+
+ xfadePeriodInSamples = (int32_t) (REVERB_XFADE_PERIOD_IN_SECONDS
+ * (double) pReverb->m_nSamplingRate);
+
+ // set xfade parameters
+ pReverb->m_nPhaseIncrement
+ = (int16_t) (65536 / ((int16_t) xfadePeriodInSamples
+ / (int16_t) updatePeriodInSamples));
+
+ if (init) {
+ ReverbReadInPresets(pReverb);
+
+ // for debugging purposes, allow noise generator
+ pReverb->m_bUseNoise = true;
+
+ // for debugging purposes, allow bypass
+ pReverb->m_bBypass = 0;
+
+ pReverb->m_nNextRoom = 1;
+
+ pReverb->m_nNoise = (int16_t) 0xABCD;
+ }
+
+ Reverb_Reset(pReverb, init);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Reset internal states and clear delay lines.
+ *
+ * Inputs:
+ * pReverb - pointer to reverb context
+ * init - true if called from init function
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+void Reverb_Reset(reverb_object_t *pReverb, bool init) {
+ int bufferSizeInSamples = (int32_t) (pReverb->m_nBufferMask + 1);
+ int maxApSamples;
+ int maxDelaySamples;
+ int maxEarlySamples;
+ int ap1In;
+ int delay0In;
+ int delay1In;
+ int32_t i;
+ uint16_t nOffset;
+
+ maxApSamples = ((int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16);
+ maxDelaySamples = ((int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+ >> 16);
+ maxEarlySamples = ((int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+ >> 16);
+
+ ap1In = (AP0_IN + maxApSamples + GUARD);
+ delay0In = (ap1In + maxApSamples + GUARD);
+ delay1In = (delay0In + maxDelaySamples + GUARD);
+ // Define the max offsets for the end points of each section
+ // i.e., we don't expect a given section's taps to go beyond
+ // the following limits
+
+ pReverb->m_nEarly0in = (delay1In + maxDelaySamples + GUARD);
+ pReverb->m_nEarly1in = (pReverb->m_nEarly0in + maxEarlySamples + GUARD);
+
+ pReverb->m_sAp0.m_zApIn = AP0_IN;
+
+ pReverb->m_zD0In = delay0In;
+
+ pReverb->m_sAp1.m_zApIn = ap1In;
+
+ pReverb->m_zD1In = delay1In;
+
+ pReverb->m_zOutLpfL = 0;
+ pReverb->m_zOutLpfR = 0;
+
+ pReverb->m_nRevFbkR = 0;
+ pReverb->m_nRevFbkL = 0;
+
+ // set base index into circular buffer
+ pReverb->m_nBaseIndex = 0;
+
+ // clear the reverb delay line
+ for (i = 0; i < bufferSizeInSamples; i++) {
+ pReverb->m_nDelayLine[i] = 0;
+ }
+
+ ReverbUpdateRoom(pReverb, init);
+
+ pReverb->m_nUpdateCounter = 0;
+
+ pReverb->m_nPhase = -32768;
+
+ pReverb->m_nSin = 0;
+ pReverb->m_nCos = 0;
+ pReverb->m_nSinIncrement = 0;
+ pReverb->m_nCosIncrement = 0;
+
+ // set delay tap lengths
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD1Cross = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+ + nOffset;
+
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD0Cross = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
+ - nOffset;
+
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD0Self = pReverb->m_nDelay0Out - pReverb->m_nMaxExcursion
+ - nOffset;
+
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD1Self = pReverb->m_nDelay1Out - pReverb->m_nMaxExcursion
+ + nOffset;
+}
+
+/*----------------------------------------------------------------------------
+ * Reverb_getParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Reverb parameter
+ *
+ * Inputs:
+ * pReverb - handle to instance data
+ * param - parameter
+ * pValue - pointer to variable to hold retrieved value
+ * pSize - pointer to value size: maximum size as input
+ *
+ * Outputs:
+ * *pValue updated with parameter value
+ * *pSize updated with actual value size
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize,
+ void *pValue) {
+ int32_t *pValue32;
+ int16_t *pValue16;
+ t_reverb_settings *pProperties;
+ int32_t i;
+ int32_t temp;
+ int32_t temp2;
+ size_t size;
+
+ if (pReverb->m_Preset) {
+ if (param != REVERB_PARAM_PRESET || *pSize < sizeof(int16_t)) {
+ return -EINVAL;
+ }
+ size = sizeof(int16_t);
+ pValue16 = (int16_t *)pValue;
+ // REVERB_PRESET_NONE is mapped to bypass
+ if (pReverb->m_bBypass != 0) {
+ *pValue16 = (int16_t)REVERB_PRESET_NONE;
+ } else {
+ *pValue16 = (int16_t)(pReverb->m_nNextRoom + 1);
+ }
+ LOGV("get REVERB_PARAM_PRESET, preset %d", *pValue16);
+ } else {
+ switch (param) {
+ case REVERB_PARAM_ROOM_LEVEL:
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ case REVERB_PARAM_REVERB_LEVEL:
+ case REVERB_PARAM_DIFFUSION:
+ case REVERB_PARAM_DENSITY:
+ size = sizeof(int16_t);
+ break;
+
+ case REVERB_PARAM_BYPASS:
+ case REVERB_PARAM_DECAY_TIME:
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ case REVERB_PARAM_REVERB_DELAY:
+ size = sizeof(int32_t);
+ break;
+
+ case REVERB_PARAM_PROPERTIES:
+ size = sizeof(t_reverb_settings);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (*pSize < size) {
+ return -EINVAL;
+ }
+
+ pValue32 = (int32_t *) pValue;
+ pValue16 = (int16_t *) pValue;
+ pProperties = (t_reverb_settings *) pValue;
+
+ switch (param) {
+ case REVERB_PARAM_BYPASS:
+ *pValue32 = (int32_t) pReverb->m_bBypass;
+ break;
+
+ case REVERB_PARAM_PROPERTIES:
+ pValue16 = &pProperties->roomLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_ROOM_LEVEL:
+ // Convert m_nRoomLpfFwd to millibels
+ temp = (pReverb->m_nRoomLpfFwd << 15)
+ / (32767 - pReverb->m_nRoomLpfFbk);
+ *pValue16 = Effects_Linear16ToMillibels(temp);
+
+ LOGV("get REVERB_PARAM_ROOM_LEVEL %d, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", *pValue16, temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+
+ if (param == REVERB_PARAM_ROOM_LEVEL) {
+ break;
+ }
+ pValue16 = &pProperties->roomHFLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ // The ratio between linear gain at 0Hz and at 5000Hz for the room low pass is:
+ // (1 + a1) / sqrt(a1^2 + 2*C*a1 + 1) where:
+ // - a1 is minus the LP feedback gain: -pReverb->m_nRoomLpfFbk
+ // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
+
+ temp = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFbk);
+ LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 %d", temp);
+ temp2 = MULT_EG1_EG1(pReverb->m_nRoomLpfFbk, pReverb->m_nCosWT_5KHz)
+ << 1;
+ LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, 2 Cos a1 %d", temp2);
+ temp = 32767 + temp - temp2;
+ LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, a1^2 + 2 Cos a1 + 1 %d", temp);
+ temp = Effects_Sqrt(temp) * 181;
+ LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, SQRT(a1^2 + 2 Cos a1 + 1) %d", temp);
+ temp = ((32767 - pReverb->m_nRoomLpfFbk) << 15) / temp;
+
+ LOGV("get REVERB_PARAM_ROOM_HF_LEVEL, gain %d, m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+
+ *pValue16 = Effects_Linear16ToMillibels(temp);
+
+ if (param == REVERB_PARAM_ROOM_HF_LEVEL) {
+ break;
+ }
+ pValue32 = &pProperties->decayTime;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DECAY_TIME:
+ // Calculate reverb feedback path gain
+ temp = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
+ temp = Effects_Linear16ToMillibels(temp);
+
+ // Calculate decay time: g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
+ temp = (-6000 * pReverb->m_nLateDelay) / temp;
+
+ // Convert samples to ms
+ *pValue32 = (temp * 1000) / pReverb->m_nSamplingRate;
+
+ LOGV("get REVERB_PARAM_DECAY_TIME, samples %d, ms %d", temp, *pValue32);
+
+ if (param == REVERB_PARAM_DECAY_TIME) {
+ break;
+ }
+ pValue16 = &pProperties->decayHFRatio;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ // If r is the decay HF ratio (r = REVERB_PARAM_DECAY_HF_RATIO/1000) we have:
+ // DT_5000Hz = DT_0Hz * r
+ // and G_5000Hz = -6000 * d / DT_5000Hz and G_0Hz = -6000 * d / DT_0Hz in millibels so :
+ // r = G_0Hz/G_5000Hz in millibels
+ // The linear gain at 5000Hz is b0 / sqrt(a1^2 + 2*C*a1 + 1) where:
+ // - a1 is minus the LP feedback gain: -pReverb->m_nRvbLpfFbk
+ // - b0 is the LP forward gain: pReverb->m_nRvbLpfFwd
+ // - C is cos(2piWT) @ 5000Hz: pReverb->m_nCosWT_5KHz
+ if (pReverb->m_nRvbLpfFbk == 0) {
+ *pValue16 = 1000;
+ LOGV("get REVERB_PARAM_DECAY_HF_RATIO, pReverb->m_nRvbLpfFbk == 0, ratio %d", *pValue16);
+ } else {
+ temp = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFbk);
+ temp2 = MULT_EG1_EG1(pReverb->m_nRvbLpfFbk, pReverb->m_nCosWT_5KHz)
+ << 1;
+ temp = 32767 + temp - temp2;
+ temp = Effects_Sqrt(temp) * 181;
+ temp = (pReverb->m_nRvbLpfFwd << 15) / temp;
+ // The linear gain at 0Hz is b0 / (a1 + 1)
+ temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767
+ - pReverb->m_nRvbLpfFbk);
+
+ temp = Effects_Linear16ToMillibels(temp);
+ temp2 = Effects_Linear16ToMillibels(temp2);
+ LOGV("get REVERB_PARAM_DECAY_HF_RATIO, gain 5KHz %d mB, gain DC %d mB", temp, temp2);
+
+ if (temp == 0)
+ temp = 1;
+ temp = (int16_t) ((1000 * temp2) / temp);
+ if (temp > 1000)
+ temp = 1000;
+
+ *pValue16 = temp;
+ LOGV("get REVERB_PARAM_DECAY_HF_RATIO, ratio %d", *pValue16);
+ }
+
+ if (param == REVERB_PARAM_DECAY_HF_RATIO) {
+ break;
+ }
+ pValue16 = &pProperties->reflectionsLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nEarlyGain);
+
+ LOGV("get REVERB_PARAM_REFLECTIONS_LEVEL, %d", *pValue16);
+ if (param == REVERB_PARAM_REFLECTIONS_LEVEL) {
+ break;
+ }
+ pValue32 = &pProperties->reflectionsDelay;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ // convert samples to ms
+ *pValue32 = (pReverb->m_nEarlyDelay * 1000) / pReverb->m_nSamplingRate;
+
+ LOGV("get REVERB_PARAM_REFLECTIONS_DELAY, samples %d, ms %d", pReverb->m_nEarlyDelay, *pValue32);
+
+ if (param == REVERB_PARAM_REFLECTIONS_DELAY) {
+ break;
+ }
+ pValue16 = &pProperties->reverbLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REVERB_LEVEL:
+ // Convert linear gain to millibels
+ *pValue16 = Effects_Linear16ToMillibels(pReverb->m_nLateGain << 2);
+
+ LOGV("get REVERB_PARAM_REVERB_LEVEL %d", *pValue16);
+
+ if (param == REVERB_PARAM_REVERB_LEVEL) {
+ break;
+ }
+ pValue32 = &pProperties->reverbDelay;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REVERB_DELAY:
+ // convert samples to ms
+ *pValue32 = (pReverb->m_nLateDelay * 1000) / pReverb->m_nSamplingRate;
+
+ LOGV("get REVERB_PARAM_REVERB_DELAY, samples %d, ms %d", pReverb->m_nLateDelay, *pValue32);
+
+ if (param == REVERB_PARAM_REVERB_DELAY) {
+ break;
+ }
+ pValue16 = &pProperties->diffusion;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DIFFUSION:
+ temp = (int16_t) ((1000 * (pReverb->m_sAp0.m_nApGain - AP0_GAIN_BASE))
+ / AP0_GAIN_RANGE);
+
+ if (temp < 0)
+ temp = 0;
+ if (temp > 1000)
+ temp = 1000;
+
+ *pValue16 = temp;
+ LOGV("get REVERB_PARAM_DIFFUSION, %d, AP0 gain %d", *pValue16, pReverb->m_sAp0.m_nApGain);
+
+ if (param == REVERB_PARAM_DIFFUSION) {
+ break;
+ }
+ pValue16 = &pProperties->density;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DENSITY:
+ // Calculate AP delay in time units
+ temp = ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn) << 16)
+ / pReverb->m_nSamplingRate;
+
+ temp = (int16_t) ((1000 * (temp - AP0_TIME_BASE)) / AP0_TIME_RANGE);
+
+ if (temp < 0)
+ temp = 0;
+ if (temp > 1000)
+ temp = 1000;
+
+ *pValue16 = temp;
+
+ LOGV("get REVERB_PARAM_DENSITY, %d, AP0 delay smps %d", *pValue16, pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ *pSize = size;
+
+ LOGV("Reverb_getParameter, context %p, param %d, value %d",
+ pReverb, param, *(int *)pValue);
+
+ return 0;
+} /* end Reverb_getParameter */
+
+/*----------------------------------------------------------------------------
+ * Reverb_setParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Reverb parameter
+ *
+ * Inputs:
+ * pReverb - handle to instance data
+ * param - parameter
+ * pValue - pointer to parameter value
+ * size - value size
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Reverb_setParameter(reverb_object_t *pReverb, int32_t param, size_t size,
+ void *pValue) {
+ int32_t value32;
+ int16_t value16;
+ t_reverb_settings *pProperties;
+ int32_t i;
+ int32_t temp;
+ int32_t temp2;
+ reverb_preset_t *pPreset;
+ int maxSamples;
+ int32_t averageDelay;
+ size_t paramSize;
+
+ LOGV("Reverb_setParameter, context %p, param %d, value16 %d, value32 %d",
+ pReverb, param, *(int16_t *)pValue, *(int32_t *)pValue);
+
+ if (pReverb->m_Preset) {
+ if (param != REVERB_PARAM_PRESET || size != sizeof(int16_t)) {
+ return -EINVAL;
+ }
+ value16 = *(int16_t *)pValue;
+ LOGV("set REVERB_PARAM_PRESET, preset %d", value16);
+ if (value16 < REVERB_PRESET_NONE || value16 > REVERB_PRESET_PLATE) {
+ return -EINVAL;
+ }
+ // REVERB_PRESET_NONE is mapped to bypass
+ if (value16 == REVERB_PRESET_NONE) {
+ pReverb->m_bBypass = 1;
+ } else {
+ pReverb->m_bBypass = 0;
+ pReverb->m_nNextRoom = value16 - 1;
+ }
+ } else {
+ switch (param) {
+ case REVERB_PARAM_ROOM_LEVEL:
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+ case REVERB_PARAM_DECAY_HF_RATIO:
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ case REVERB_PARAM_REVERB_LEVEL:
+ case REVERB_PARAM_DIFFUSION:
+ case REVERB_PARAM_DENSITY:
+ paramSize = sizeof(int16_t);
+ break;
+
+ case REVERB_PARAM_BYPASS:
+ case REVERB_PARAM_DECAY_TIME:
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ case REVERB_PARAM_REVERB_DELAY:
+ paramSize = sizeof(int32_t);
+ break;
+
+ case REVERB_PARAM_PROPERTIES:
+ paramSize = sizeof(t_reverb_settings);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (size != paramSize) {
+ return -EINVAL;
+ }
+
+ if (paramSize == sizeof(int16_t)) {
+ value16 = *(int16_t *) pValue;
+ } else if (paramSize == sizeof(int32_t)) {
+ value32 = *(int32_t *) pValue;
+ } else {
+ pProperties = (t_reverb_settings *) pValue;
+ }
+
+ pPreset = &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
+
+ switch (param) {
+ case REVERB_PARAM_BYPASS:
+ pReverb->m_bBypass = (uint16_t)value32;
+ break;
+
+ case REVERB_PARAM_PROPERTIES:
+ value16 = pProperties->roomLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_ROOM_LEVEL:
+ // Convert millibels to linear 16 bit signed => m_nRoomLpfFwd
+ if (value16 > 0)
+ return -EINVAL;
+
+ temp = Effects_MillibelsToLinear16(value16);
+
+ pReverb->m_nRoomLpfFwd
+ = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRoomLpfFbk));
+
+ LOGV("REVERB_PARAM_ROOM_LEVEL, gain %d, new m_nRoomLpfFwd %d, m_nRoomLpfFbk %d", temp, pReverb->m_nRoomLpfFwd, pReverb->m_nRoomLpfFbk);
+ if (param == REVERB_PARAM_ROOM_LEVEL)
+ break;
+ value16 = pProperties->roomHFLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_ROOM_HF_LEVEL:
+
+ // Limit to 0 , -40dB range because of low pass implementation
+ if (value16 > 0 || value16 < -4000)
+ return -EINVAL;
+ // Convert attenuation @ 5000H expressed in millibels to => m_nRoomLpfFbk
+ // m_nRoomLpfFbk is -a1 where a1 is the solution of:
+ // a1^2 + 2*(C-dG^2)/(1-dG^2)*a1 + 1 = 0 where:
+ // - C is cos(2*pi*5000/Fs) (pReverb->m_nCosWT_5KHz)
+ // - dG is G0/Gf (G0 is the linear gain at DC and Gf is the wanted gain at 5000Hz)
+
+ // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
+ // while changing HF level
+ temp2 = (pReverb->m_nRoomLpfFwd << 15) / (32767
+ - pReverb->m_nRoomLpfFbk);
+ if (value16 == 0) {
+ pReverb->m_nRoomLpfFbk = 0;
+ } else {
+ int32_t dG2, b, delta;
+
+ // dG^2
+ temp = Effects_MillibelsToLinear16(value16);
+ LOGV("REVERB_PARAM_ROOM_HF_LEVEL, HF gain %d", temp);
+ temp = (1 << 30) / temp;
+ LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain %d", temp);
+ dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+ LOGV("REVERB_PARAM_ROOM_HF_LEVEL, 1/ HF gain ^ 2 %d", dG2);
+ // b = 2*(C-dG^2)/(1-dG^2)
+ b = (int32_t) ((((int64_t) 1 << (15 + 1))
+ * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
+ / ((int64_t) 32767 - (int64_t) dG2));
+
+ // delta = b^2 - 4
+ delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
+ + 2)));
+
+ LOGV_IF(delta > (1<<30), " delta overflow %d", delta);
+
+ LOGV("REVERB_PARAM_ROOM_HF_LEVEL, dG2 %d, b %d, delta %d, m_nCosWT_5KHz %d", dG2, b, delta, pReverb->m_nCosWT_5KHz);
+ // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
+ pReverb->m_nRoomLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
+ }
+ LOGV("REVERB_PARAM_ROOM_HF_LEVEL, olg DC gain %d new m_nRoomLpfFbk %d, old m_nRoomLpfFwd %d",
+ temp2, pReverb->m_nRoomLpfFbk, pReverb->m_nRoomLpfFwd);
+
+ pReverb->m_nRoomLpfFwd
+ = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRoomLpfFbk));
+ LOGV("REVERB_PARAM_ROOM_HF_LEVEL, new m_nRoomLpfFwd %d", pReverb->m_nRoomLpfFwd);
+
+ if (param == REVERB_PARAM_ROOM_HF_LEVEL)
+ break;
+ value32 = pProperties->decayTime;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DECAY_TIME:
+
+ // Convert milliseconds to => m_nRvbLpfFwd (function of m_nRvbLpfFbk)
+ // convert ms to samples
+ value32 = (value32 * pReverb->m_nSamplingRate) / 1000;
+
+ // calculate valid decay time range as a function of current reverb delay and
+ // max feed back gain. Min value <=> -40dB in one pass, Max value <=> feedback gain = -1 dB
+ // Calculate attenuation for each round in late reverb given a total attenuation of -6000 millibels.
+ // g = -6000 d/DT , g gain in millibels, d reverb delay, DT decay time
+ averageDelay = pReverb->m_nLateDelay - pReverb->m_nMaxExcursion;
+ averageDelay += ((pReverb->m_sAp0.m_zApOut - pReverb->m_sAp0.m_zApIn)
+ + (pReverb->m_sAp1.m_zApOut - pReverb->m_sAp1.m_zApIn)) >> 1;
+
+ temp = (-6000 * averageDelay) / value32;
+ LOGV("REVERB_PARAM_DECAY_TIME, delay smps %d, DT smps %d, gain mB %d",averageDelay, value32, temp);
+ if (temp < -4000 || temp > -100)
+ return -EINVAL;
+
+ // calculate low pass gain by adding reverb input attenuation (pReverb->m_nLateGain) and substrating output
+ // xfade and sum gain (max +9dB)
+ temp -= Effects_Linear16ToMillibels(pReverb->m_nLateGain) + 900;
+ temp = Effects_MillibelsToLinear16(temp);
+
+ // DC gain (temp) = b0 / (1 + a1) = pReverb->m_nRvbLpfFwd / (32767 - pReverb->m_nRvbLpfFbk)
+ pReverb->m_nRvbLpfFwd
+ = MULT_EG1_EG1(temp, (32767 - pReverb->m_nRvbLpfFbk));
+
+ LOGV("REVERB_PARAM_DECAY_TIME, gain %d, new m_nRvbLpfFwd %d, old m_nRvbLpfFbk %d, reverb gain %d", temp, pReverb->m_nRvbLpfFwd, pReverb->m_nRvbLpfFbk, Effects_Linear16ToMillibels(pReverb->m_nLateGain));
+
+ if (param == REVERB_PARAM_DECAY_TIME)
+ break;
+ value16 = pProperties->decayHFRatio;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DECAY_HF_RATIO:
+
+ // We limit max value to 1000 because reverb filter is lowpass only
+ if (value16 < 100 || value16 > 1000)
+ return -EINVAL;
+ // Convert per mille to => m_nLpfFwd, m_nLpfFbk
+
+ // Save current DC gain m_nRoomLpfFwd / (32767 - m_nRoomLpfFbk) to keep it unchanged
+ // while changing HF level
+ temp2 = (pReverb->m_nRvbLpfFwd << 15) / (32767 - pReverb->m_nRvbLpfFbk);
+
+ if (value16 == 1000) {
+ pReverb->m_nRvbLpfFbk = 0;
+ } else {
+ int32_t dG2, b, delta;
+
+ temp = Effects_Linear16ToMillibels(temp2);
+ // G_5000Hz = G_DC * (1000/REVERB_PARAM_DECAY_HF_RATIO) in millibels
+
+ value32 = ((int32_t) 1000 << 15) / (int32_t) value16;
+ LOGV("REVERB_PARAM_DECAY_HF_RATIO, DC gain %d, DC gain mB %d, 1000/R %d", temp2, temp, value32);
+
+ temp = (int32_t) (((int64_t) temp * (int64_t) value32) >> 15);
+
+ if (temp < -4000) {
+ LOGV("REVERB_PARAM_DECAY_HF_RATIO HF gain overflow %d mB", temp);
+ temp = -4000;
+ }
+
+ temp = Effects_MillibelsToLinear16(temp);
+ LOGV("REVERB_PARAM_DECAY_HF_RATIO, HF gain %d", temp);
+ // dG^2
+ temp = (temp2 << 15) / temp;
+ dG2 = (int32_t) (((int64_t) temp * (int64_t) temp) >> 15);
+
+ // b = 2*(C-dG^2)/(1-dG^2)
+ b = (int32_t) ((((int64_t) 1 << (15 + 1))
+ * ((int64_t) pReverb->m_nCosWT_5KHz - (int64_t) dG2))
+ / ((int64_t) 32767 - (int64_t) dG2));
+
+ // delta = b^2 - 4
+ delta = (int32_t) ((((int64_t) b * (int64_t) b) >> 15) - (1 << (15
+ + 2)));
+
+ // m_nRoomLpfFbk = -a1 = - (- b + sqrt(delta)) / 2
+ pReverb->m_nRvbLpfFbk = (b - Effects_Sqrt(delta) * 181) >> 1;
+
+ LOGV("REVERB_PARAM_DECAY_HF_RATIO, dG2 %d, b %d, delta %d", dG2, b, delta);
+
+ }
+
+ LOGV("REVERB_PARAM_DECAY_HF_RATIO, gain %d, m_nRvbLpfFbk %d, m_nRvbLpfFwd %d", temp2, pReverb->m_nRvbLpfFbk, pReverb->m_nRvbLpfFwd);
+
+ pReverb->m_nRvbLpfFwd
+ = MULT_EG1_EG1(temp2, (32767 - pReverb->m_nRvbLpfFbk));
+
+ if (param == REVERB_PARAM_DECAY_HF_RATIO)
+ break;
+ value16 = pProperties->reflectionsLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REFLECTIONS_LEVEL:
+ // We limit max value to 0 because gain is limited to 0dB
+ if (value16 > 0 || value16 < -6000)
+ return -EINVAL;
+
+ // Convert millibels to linear 16 bit signed and recompute m_sEarlyL.m_nGain[i] and m_sEarlyR.m_nGain[i].
+ value16 = Effects_MillibelsToLinear16(value16);
+ for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+ pReverb->m_sEarlyL.m_nGain[i]
+ = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],value16);
+ pReverb->m_sEarlyR.m_nGain[i]
+ = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],value16);
+ }
+ pReverb->m_nEarlyGain = value16;
+ LOGV("REVERB_PARAM_REFLECTIONS_LEVEL, m_nEarlyGain %d", pReverb->m_nEarlyGain);
+
+ if (param == REVERB_PARAM_REFLECTIONS_LEVEL)
+ break;
+ value32 = pProperties->reflectionsDelay;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REFLECTIONS_DELAY:
+ // We limit max value MAX_EARLY_TIME
+ // convert ms to time units
+ temp = (value32 * 65536) / 1000;
+ if (temp < 0 || temp > MAX_EARLY_TIME)
+ return -EINVAL;
+
+ maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+ >> 16;
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+ temp2 = temp + (((int32_t) pPreset->m_sEarlyL.m_zDelay[i]
+ * pReverb->m_nSamplingRate) >> 16);
+ if (temp2 > maxSamples)
+ temp2 = maxSamples;
+ pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp2;
+ temp2 = temp + (((int32_t) pPreset->m_sEarlyR.m_zDelay[i]
+ * pReverb->m_nSamplingRate) >> 16);
+ if (temp2 > maxSamples)
+ temp2 = maxSamples;
+ pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp2;
+ }
+ pReverb->m_nEarlyDelay = temp;
+
+ LOGV("REVERB_PARAM_REFLECTIONS_DELAY, m_nEarlyDelay smps %d max smp delay %d", pReverb->m_nEarlyDelay, maxSamples);
+
+ // Convert milliseconds to sample count => m_nEarlyDelay
+ if (param == REVERB_PARAM_REFLECTIONS_DELAY)
+ break;
+ value16 = pProperties->reverbLevel;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REVERB_LEVEL:
+ // We limit max value to 0 because gain is limited to 0dB
+ if (value16 > 0 || value16 < -6000)
+ return -EINVAL;
+ // Convert millibels to linear 16 bits (gange 0 - 8191) => m_nLateGain.
+ pReverb->m_nLateGain = Effects_MillibelsToLinear16(value16) >> 2;
+
+ LOGV("REVERB_PARAM_REVERB_LEVEL, m_nLateGain %d", pReverb->m_nLateGain);
+
+ if (param == REVERB_PARAM_REVERB_LEVEL)
+ break;
+ value32 = pProperties->reverbDelay;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_REVERB_DELAY:
+ // We limit max value to MAX_DELAY_TIME
+ // convert ms to time units
+ temp = (value32 * 65536) / 1000;
+ if (temp < 0 || temp > MAX_DELAY_TIME)
+ return -EINVAL;
+
+ maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+ >> 16;
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
+ temp = maxSamples - pReverb->m_nMaxExcursion;
+ }
+ if (temp < pReverb->m_nMaxExcursion) {
+ temp = pReverb->m_nMaxExcursion;
+ }
+
+ temp -= pReverb->m_nLateDelay;
+ pReverb->m_nDelay0Out += temp;
+ pReverb->m_nDelay1Out += temp;
+ pReverb->m_nLateDelay += temp;
+
+ LOGV("REVERB_PARAM_REVERB_DELAY, m_nLateDelay smps %d max smp delay %d", pReverb->m_nLateDelay, maxSamples);
+
+ // Convert milliseconds to sample count => m_nDelay1Out + m_nMaxExcursion
+ if (param == REVERB_PARAM_REVERB_DELAY)
+ break;
+
+ value16 = pProperties->diffusion;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DIFFUSION:
+ if (value16 < 0 || value16 > 1000)
+ return -EINVAL;
+
+ // Convert per mille to m_sAp0.m_nApGain, m_sAp1.m_nApGain
+ pReverb->m_sAp0.m_nApGain = AP0_GAIN_BASE + ((int32_t) value16
+ * AP0_GAIN_RANGE) / 1000;
+ pReverb->m_sAp1.m_nApGain = AP1_GAIN_BASE + ((int32_t) value16
+ * AP1_GAIN_RANGE) / 1000;
+
+ LOGV("REVERB_PARAM_DIFFUSION, m_sAp0.m_nApGain %d m_sAp1.m_nApGain %d", pReverb->m_sAp0.m_nApGain, pReverb->m_sAp1.m_nApGain);
+
+ if (param == REVERB_PARAM_DIFFUSION)
+ break;
+
+ value16 = pProperties->density;
+ /* FALL THROUGH */
+
+ case REVERB_PARAM_DENSITY:
+ if (value16 < 0 || value16 > 1000)
+ return -EINVAL;
+
+ // Convert per mille to m_sAp0.m_zApOut, m_sAp1.m_zApOut
+ maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
+
+ temp = AP0_TIME_BASE + ((int32_t) value16 * AP0_TIME_RANGE) / 1000;
+ /*lint -e{702} shift for performance */
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ if (temp > maxSamples)
+ temp = maxSamples;
+ pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
+
+ LOGV("REVERB_PARAM_DENSITY, Ap0 delay smps %d", temp);
+
+ temp = AP1_TIME_BASE + ((int32_t) value16 * AP1_TIME_RANGE) / 1000;
+ /*lint -e{702} shift for performance */
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ if (temp > maxSamples)
+ temp = maxSamples;
+ pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
+
+ LOGV("Ap1 delay smps %d", temp);
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return 0;
+} /* end Reverb_setParameter */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbUpdateXfade(reverb_object_t *pReverb, int nNumSamplesToAdd) {
+ uint16_t nOffset;
+ int16_t tempCos;
+ int16_t tempSin;
+
+ if (pReverb->m_nXfadeCounter >= pReverb->m_nXfadeInterval) {
+ /* update interval has elapsed, so reset counter */
+ pReverb->m_nXfadeCounter = 0;
+
+ // Pin the sin,cos values to min / max values to ensure that the
+ // modulated taps' coefs are zero (thus no clicks)
+ if (pReverb->m_nPhaseIncrement > 0) {
+ // if phase increment > 0, then sin -> 1, cos -> 0
+ pReverb->m_nSin = 32767;
+ pReverb->m_nCos = 0;
+
+ // reset the phase to match the sin, cos values
+ pReverb->m_nPhase = 32767;
+
+ // modulate the cross taps because their tap coefs are zero
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD1Cross = pReverb->m_nDelay1Out
+ - pReverb->m_nMaxExcursion + nOffset;
+
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD0Cross = pReverb->m_nDelay0Out
+ - pReverb->m_nMaxExcursion - nOffset;
+ } else {
+ // if phase increment < 0, then sin -> 0, cos -> 1
+ pReverb->m_nSin = 0;
+ pReverb->m_nCos = 32767;
+
+ // reset the phase to match the sin, cos values
+ pReverb->m_nPhase = -32768;
+
+ // modulate the self taps because their tap coefs are zero
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD0Self = pReverb->m_nDelay0Out
+ - pReverb->m_nMaxExcursion - nOffset;
+
+ nOffset = ReverbCalculateNoise(pReverb);
+
+ pReverb->m_zD1Self = pReverb->m_nDelay1Out
+ - pReverb->m_nMaxExcursion + nOffset;
+
+ } // end if-else (pReverb->m_nPhaseIncrement > 0)
+
+ // Reverse the direction of the sin,cos so that the
+ // tap whose coef was previously increasing now decreases
+ // and vice versa
+ pReverb->m_nPhaseIncrement = -pReverb->m_nPhaseIncrement;
+
+ } // end if counter >= update interval
+
+ //compute what phase will be next time
+ pReverb->m_nPhase += pReverb->m_nPhaseIncrement;
+
+ //calculate what the new sin and cos need to reach by the next update
+ ReverbCalculateSinCos(pReverb->m_nPhase, &tempSin, &tempCos);
+
+ //calculate the per-sample increment required to get there by the next update
+ /*lint -e{702} shift for performance */
+ pReverb->m_nSinIncrement = (tempSin - pReverb->m_nSin)
+ >> pReverb->m_nUpdatePeriodInBits;
+
+ /*lint -e{702} shift for performance */
+ pReverb->m_nCosIncrement = (tempCos - pReverb->m_nCos)
+ >> pReverb->m_nUpdatePeriodInBits;
+
+ /* increment update counter */
+ pReverb->m_nXfadeCounter += (uint16_t) nNumSamplesToAdd;
+
+ return 0;
+
+} /* end ReverbUpdateXfade */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * nMaxExcursion - noise value is limited to this value
+ * pnNoise - return new noise sample in this (not limited)
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - *pnNoise noise value is updated
+ *
+ *----------------------------------------------------------------------------
+ */
+static uint16_t ReverbCalculateNoise(reverb_object_t *pReverb) {
+ int16_t nNoise = pReverb->m_nNoise;
+
+ // calculate new noise value
+ if (pReverb->m_bUseNoise) {
+ nNoise = (int16_t) (nNoise * 5 + 1);
+ } else {
+ nNoise = 0;
+ }
+
+ pReverb->m_nNoise = nNoise;
+ // return the limited noise value
+ return (pReverb->m_nMaxExcursion & nNoise);
+
+} /* end ReverbCalculateNoise */
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase - phase angle
+ * pnSin - input old value, output new value
+ * pnCos - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos) {
+ int32_t nTemp;
+ int32_t nNetAngle;
+
+ // -1 <= nPhase < 1
+ // However, for the calculation, we need a value
+ // that ranges from -1/2 to +1/2, so divide the phase by 2
+ /*lint -e{702} shift for performance */
+ nNetAngle = nPhase >> 1;
+
+ /*
+ Implement the following
+ sin(x) = (2-4*c)*x^2 + c + x
+ cos(x) = (2-4*c)*x^2 + c - x
+
+ where c = 1/sqrt(2)
+ using the a0 + x*(a1 + x*a2) approach
+ */
+
+ /* limit the input "angle" to be between -0.5 and +0.5 */
+ if (nNetAngle > EG1_HALF) {
+ nNetAngle = EG1_HALF;
+ } else if (nNetAngle < EG1_MINUS_HALF) {
+ nNetAngle = EG1_MINUS_HALF;
+ }
+
+ /* calculate sin */
+ nTemp = EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+ nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+ *pnSin = (int16_t) SATURATE_EG1(nTemp);
+
+ /* calculate cos */
+ nTemp = -EG1_ONE + MULT_EG1_EG1(REVERB_PAN_G2, nNetAngle);
+ nTemp = REVERB_PAN_G0 + MULT_EG1_EG1(nTemp, nNetAngle);
+ *pnCos = (int16_t) SATURATE_EG1(nTemp);
+
+ return 0;
+} /* end ReverbCalculateSinCos */
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin - input old value, output new value
+ * pnCos - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+static int Reverb(reverb_object_t *pReverb, int nNumSamplesToAdd,
+ short *pOutputBuffer, short *pInputBuffer) {
+ int32_t i;
+ int32_t nDelayOut0;
+ int32_t nDelayOut1;
+ uint16_t nBase;
+
+ uint32_t nAddr;
+ int32_t nTemp1;
+ int32_t nTemp2;
+ int32_t nApIn;
+ int32_t nApOut;
+
+ int32_t j;
+ int32_t nEarlyOut;
+
+ int32_t tempValue;
+
+ // get the base address
+ nBase = pReverb->m_nBaseIndex;
+
+ for (i = 0; i < nNumSamplesToAdd; i++) {
+ // ********** Left Allpass - start
+ nApIn = *pInputBuffer;
+ if (!pReverb->m_Aux) {
+ pInputBuffer++;
+ }
+ // store to early delay line
+ nAddr = CIRCULAR(nBase, pReverb->m_nEarly0in, pReverb->m_nBufferMask);
+ pReverb->m_nDelayLine[nAddr] = (short) nApIn;
+
+ // left input = (left dry * m_nLateGain) + right feedback from previous period
+
+ nApIn = SATURATE(nApIn + pReverb->m_nRevFbkR);
+ nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
+
+ // fetch allpass delay line out
+ //nAddr = CIRCULAR(nBase, psAp0->m_zApOut, pReverb->m_nBufferMask);
+ nAddr
+ = CIRCULAR(nBase, pReverb->m_sAp0.m_zApOut, pReverb->m_nBufferMask);
+ nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate allpass feedforward; subtract the feedforward result
+ nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp0.m_nApGain);
+ nApOut = SATURATE(nDelayOut0 - nTemp1); // allpass output
+
+ // calculate allpass feedback; add the feedback result
+ nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp0.m_nApGain);
+ nTemp1 = SATURATE(nApIn + nTemp1);
+
+ // inject into allpass delay
+ nAddr
+ = CIRCULAR(nBase, pReverb->m_sAp0.m_zApIn, pReverb->m_nBufferMask);
+ pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
+
+ // inject allpass output into delay line
+ nAddr = CIRCULAR(nBase, pReverb->m_zD0In, pReverb->m_nBufferMask);
+ pReverb->m_nDelayLine[nAddr] = (short) nApOut;
+
+ // ********** Left Allpass - end
+
+ // ********** Right Allpass - start
+ nApIn = (*pInputBuffer++);
+ // store to early delay line
+ nAddr = CIRCULAR(nBase, pReverb->m_nEarly1in, pReverb->m_nBufferMask);
+ pReverb->m_nDelayLine[nAddr] = (short) nApIn;
+
+ // right input = (right dry * m_nLateGain) + left feedback from previous period
+ /*lint -e{702} use shift for performance */
+ nApIn = SATURATE(nApIn + pReverb->m_nRevFbkL);
+ nApIn = MULT_EG1_EG1(nApIn, pReverb->m_nLateGain);
+
+ // fetch allpass delay line out
+ nAddr
+ = CIRCULAR(nBase, pReverb->m_sAp1.m_zApOut, pReverb->m_nBufferMask);
+ nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate allpass feedforward; subtract the feedforward result
+ nTemp1 = MULT_EG1_EG1(nApIn, pReverb->m_sAp1.m_nApGain);
+ nApOut = SATURATE(nDelayOut1 - nTemp1); // allpass output
+
+ // calculate allpass feedback; add the feedback result
+ nTemp1 = MULT_EG1_EG1(nApOut, pReverb->m_sAp1.m_nApGain);
+ nTemp1 = SATURATE(nApIn + nTemp1);
+
+ // inject into allpass delay
+ nAddr
+ = CIRCULAR(nBase, pReverb->m_sAp1.m_zApIn, pReverb->m_nBufferMask);
+ pReverb->m_nDelayLine[nAddr] = (short) nTemp1;
+
+ // inject allpass output into delay line
+ nAddr = CIRCULAR(nBase, pReverb->m_zD1In, pReverb->m_nBufferMask);
+ pReverb->m_nDelayLine[nAddr] = (short) nApOut;
+
+ // ********** Right Allpass - end
+
+ // ********** D0 output - start
+ // fetch delay line self out
+ nAddr = CIRCULAR(nBase, pReverb->m_zD0Self, pReverb->m_nBufferMask);
+ nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nSin);
+
+ // fetch delay line cross out
+ nAddr = CIRCULAR(nBase, pReverb->m_zD1Cross, pReverb->m_nBufferMask);
+ nDelayOut0 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp2 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nCos);
+
+ // calculate unfiltered delay out
+ nDelayOut0 = SATURATE(nTemp1 + nTemp2);
+
+ // ********** D0 output - end
+
+ // ********** D1 output - start
+ // fetch delay line self out
+ nAddr = CIRCULAR(nBase, pReverb->m_zD1Self, pReverb->m_nBufferMask);
+ nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nSin);
+
+ // fetch delay line cross out
+ nAddr = CIRCULAR(nBase, pReverb->m_zD0Cross, pReverb->m_nBufferMask);
+ nDelayOut1 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate delay line self out
+ nTemp2 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nCos);
+
+ // calculate unfiltered delay out
+ nDelayOut1 = SATURATE(nTemp1 + nTemp2);
+
+ // ********** D1 output - end
+
+ // ********** mixer and feedback - start
+ // sum is fedback to right input (R + L)
+ nDelayOut0 = (short) SATURATE(nDelayOut0 + nDelayOut1);
+
+ // difference is feedback to left input (R - L)
+ /*lint -e{685} lint complains that it can't saturate negative */
+ nDelayOut1 = (short) SATURATE(nDelayOut1 - nDelayOut0);
+
+ // ********** mixer and feedback - end
+
+ // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+ nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRvbLpfFwd);
+
+ nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkL, pReverb->m_nRvbLpfFbk);
+
+ // calculate filtered delay out and simultaneously update LPF state variable
+ // filtered delay output is stored in m_nRevFbkL
+ pReverb->m_nRevFbkL = (short) SATURATE(nTemp1 + nTemp2);
+
+ // calculate lowpass filter (mixer scale factor included in LPF feedforward)
+ nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRvbLpfFwd);
+
+ nTemp2 = MULT_EG1_EG1(pReverb->m_nRevFbkR, pReverb->m_nRvbLpfFbk);
+
+ // calculate filtered delay out and simultaneously update LPF state variable
+ // filtered delay output is stored in m_nRevFbkR
+ pReverb->m_nRevFbkR = (short) SATURATE(nTemp1 + nTemp2);
+
+ // ********** start early reflection generator, left
+ //psEarly = &(pReverb->m_sEarlyL);
+
+
+ for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
+ // fetch delay line out
+ //nAddr = CIRCULAR(nBase, psEarly->m_zDelay[j], pReverb->m_nBufferMask);
+ nAddr
+ = CIRCULAR(nBase, pReverb->m_sEarlyL.m_zDelay[j], pReverb->m_nBufferMask);
+
+ nTemp1 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate reflection
+ //nTemp1 = MULT_EG1_EG1(nDelayOut0, psEarly->m_nGain[j]);
+ nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyL.m_nGain[j]);
+
+ nDelayOut0 = SATURATE(nDelayOut0 + nTemp1);
+
+ } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+ // apply lowpass to early reflections and reverb output
+ //nTemp1 = MULT_EG1_EG1(nEarlyOut, psEarly->m_nRvbLpfFwd);
+ nTemp1 = MULT_EG1_EG1(nDelayOut0, pReverb->m_nRoomLpfFwd);
+
+ //nTemp2 = MULT_EG1_EG1(psEarly->m_zLpf, psEarly->m_nLpfFbk);
+ nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfL, pReverb->m_nRoomLpfFbk);
+
+ // calculate filtered out and simultaneously update LPF state variable
+ // filtered output is stored in m_zOutLpfL
+ pReverb->m_zOutLpfL = (short) SATURATE(nTemp1 + nTemp2);
+
+ //sum with output buffer
+ tempValue = *pOutputBuffer;
+ *pOutputBuffer++ = (short) SATURATE(tempValue+pReverb->m_zOutLpfL);
+
+ // ********** end early reflection generator, left
+
+ // ********** start early reflection generator, right
+ //psEarly = &(pReverb->m_sEarlyR);
+
+ for (j = 0; j < REVERB_MAX_NUM_REFLECTIONS; j++) {
+ // fetch delay line out
+ nAddr
+ = CIRCULAR(nBase, pReverb->m_sEarlyR.m_zDelay[j], pReverb->m_nBufferMask);
+ nTemp1 = pReverb->m_nDelayLine[nAddr];
+
+ // calculate reflection
+ nTemp1 = MULT_EG1_EG1(nTemp1, pReverb->m_sEarlyR.m_nGain[j]);
+
+ nDelayOut1 = SATURATE(nDelayOut1 + nTemp1);
+
+ } // end for (j=0; j < REVERB_MAX_NUM_REFLECTIONS; j++)
+
+ // apply lowpass to early reflections
+ nTemp1 = MULT_EG1_EG1(nDelayOut1, pReverb->m_nRoomLpfFwd);
+
+ nTemp2 = MULT_EG1_EG1(pReverb->m_zOutLpfR, pReverb->m_nRoomLpfFbk);
+
+ // calculate filtered out and simultaneously update LPF state variable
+ // filtered output is stored in m_zOutLpfR
+ pReverb->m_zOutLpfR = (short) SATURATE(nTemp1 + nTemp2);
+
+ //sum with output buffer
+ tempValue = *pOutputBuffer;
+ *pOutputBuffer++ = (short) SATURATE(tempValue + pReverb->m_zOutLpfR);
+
+ // ********** end early reflection generator, right
+
+ // decrement base addr for next sample period
+ nBase--;
+
+ pReverb->m_nSin += pReverb->m_nSinIncrement;
+ pReverb->m_nCos += pReverb->m_nCosIncrement;
+
+ } // end for (i=0; i < nNumSamplesToAdd; i++)
+
+ // store the most up to date version
+ pReverb->m_nBaseIndex = nBase;
+
+ return 0;
+} /* end Reverb */
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+ */
+static int ReverbUpdateRoom(reverb_object_t *pReverb, bool fullUpdate) {
+ int temp;
+ int i;
+ int maxSamples;
+ int earlyDelay;
+ int earlyGain;
+
+ reverb_preset_t *pPreset =
+ &pReverb->m_sPreset.m_sPreset[pReverb->m_nNextRoom];
+
+ if (fullUpdate) {
+ pReverb->m_nRvbLpfFwd = pPreset->m_nRvbLpfFwd;
+ pReverb->m_nRvbLpfFbk = pPreset->m_nRvbLpfFbk;
+
+ pReverb->m_nEarlyGain = pPreset->m_nEarlyGain;
+ //stored as time based, convert to sample based
+ pReverb->m_nLateGain = pPreset->m_nLateGain;
+ pReverb->m_nRoomLpfFbk = pPreset->m_nRoomLpfFbk;
+ pReverb->m_nRoomLpfFwd = pPreset->m_nRoomLpfFwd;
+
+ // set the early reflections gains
+ earlyGain = pPreset->m_nEarlyGain;
+ for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+ pReverb->m_sEarlyL.m_nGain[i]
+ = MULT_EG1_EG1(pPreset->m_sEarlyL.m_nGain[i],earlyGain);
+ pReverb->m_sEarlyR.m_nGain[i]
+ = MULT_EG1_EG1(pPreset->m_sEarlyR.m_nGain[i],earlyGain);
+ }
+
+ pReverb->m_nMaxExcursion = pPreset->m_nMaxExcursion;
+
+ pReverb->m_sAp0.m_nApGain = pPreset->m_nAp0_ApGain;
+ pReverb->m_sAp1.m_nApGain = pPreset->m_nAp1_ApGain;
+
+ // set the early reflections delay
+ earlyDelay = ((int) pPreset->m_nEarlyDelay * pReverb->m_nSamplingRate)
+ >> 16;
+ pReverb->m_nEarlyDelay = earlyDelay;
+ maxSamples = (int32_t) (MAX_EARLY_TIME * pReverb->m_nSamplingRate)
+ >> 16;
+ for (i = 0; i < REVERB_MAX_NUM_REFLECTIONS; i++) {
+ //stored as time based, convert to sample based
+ temp = earlyDelay + (((int) pPreset->m_sEarlyL.m_zDelay[i]
+ * pReverb->m_nSamplingRate) >> 16);
+ if (temp > maxSamples)
+ temp = maxSamples;
+ pReverb->m_sEarlyL.m_zDelay[i] = pReverb->m_nEarly0in + temp;
+ //stored as time based, convert to sample based
+ temp = earlyDelay + (((int) pPreset->m_sEarlyR.m_zDelay[i]
+ * pReverb->m_nSamplingRate) >> 16);
+ if (temp > maxSamples)
+ temp = maxSamples;
+ pReverb->m_sEarlyR.m_zDelay[i] = pReverb->m_nEarly1in + temp;
+ }
+
+ maxSamples = (int32_t) (MAX_DELAY_TIME * pReverb->m_nSamplingRate)
+ >> 16;
+ //stored as time based, convert to sample based
+ /*lint -e{702} shift for performance */
+ temp = (pPreset->m_nLateDelay * pReverb->m_nSamplingRate) >> 16;
+ if ((temp + pReverb->m_nMaxExcursion) > maxSamples) {
+ temp = maxSamples - pReverb->m_nMaxExcursion;
+ }
+ temp -= pReverb->m_nLateDelay;
+ pReverb->m_nDelay0Out += temp;
+ pReverb->m_nDelay1Out += temp;
+ pReverb->m_nLateDelay += temp;
+
+ maxSamples = (int32_t) (MAX_AP_TIME * pReverb->m_nSamplingRate) >> 16;
+ //stored as time based, convert to absolute sample value
+ temp = pPreset->m_nAp0_ApOut;
+ /*lint -e{702} shift for performance */
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ if (temp > maxSamples)
+ temp = maxSamples;
+ pReverb->m_sAp0.m_zApOut = (uint16_t) (pReverb->m_sAp0.m_zApIn + temp);
+
+ //stored as time based, convert to absolute sample value
+ temp = pPreset->m_nAp1_ApOut;
+ /*lint -e{702} shift for performance */
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ if (temp > maxSamples)
+ temp = maxSamples;
+ pReverb->m_sAp1.m_zApOut = (uint16_t) (pReverb->m_sAp1.m_zApIn + temp);
+ //gpsReverbObject->m_sAp1.m_zApOut = pPreset->m_nAp1_ApOut;
+ }
+
+ //stored as time based, convert to sample based
+ temp = pPreset->m_nXfadeInterval;
+ /*lint -e{702} shift for performance */
+ temp = (temp * pReverb->m_nSamplingRate) >> 16;
+ pReverb->m_nXfadeInterval = (uint16_t) temp;
+ //gsReverbObject.m_nXfadeInterval = pPreset->m_nXfadeInterval;
+ pReverb->m_nXfadeCounter = pReverb->m_nXfadeInterval + 1; // force update on first iteration
+
+ pReverb->m_nCurrentRoom = pReverb->m_nNextRoom;
+
+ return 0;
+
+} /* end ReverbUpdateRoom */
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+ */
+static int ReverbReadInPresets(reverb_object_t *pReverb) {
+
+ int preset;
+
+ // this is for test only. OpenSL ES presets are mapped to 4 presets.
+ // REVERB_PRESET_NONE is mapped to bypass
+ for (preset = 0; preset < REVERB_NUM_PRESETS; preset++) {
+ reverb_preset_t *pPreset = &pReverb->m_sPreset.m_sPreset[preset];
+ switch (preset + 1) {
+ case REVERB_PRESET_PLATE:
+ case REVERB_PRESET_SMALLROOM:
+ pPreset->m_nRvbLpfFbk = 5077;
+ pPreset->m_nRvbLpfFwd = 11076;
+ pPreset->m_nEarlyGain = 27690;
+ pPreset->m_nEarlyDelay = 1311;
+ pPreset->m_nLateGain = 8191;
+ pPreset->m_nLateDelay = 3932;
+ pPreset->m_nRoomLpfFbk = 3692;
+ pPreset->m_nRoomLpfFwd = 20474;
+ pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+ pPreset->m_sEarlyL.m_nGain[0] = 22152;
+ pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+ pPreset->m_sEarlyL.m_nGain[1] = 17537;
+ pPreset->m_sEarlyL.m_zDelay[2] = 0;
+ pPreset->m_sEarlyL.m_nGain[2] = 14768;
+ pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+ pPreset->m_sEarlyL.m_nGain[3] = 14307;
+ pPreset->m_sEarlyL.m_zDelay[4] = 0;
+ pPreset->m_sEarlyL.m_nGain[4] = 13384;
+ pPreset->m_sEarlyR.m_zDelay[0] = 721;
+ pPreset->m_sEarlyR.m_nGain[0] = 20306;
+ pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+ pPreset->m_sEarlyR.m_nGain[1] = 17537;
+ pPreset->m_sEarlyR.m_zDelay[2] = 0;
+ pPreset->m_sEarlyR.m_nGain[2] = 14768;
+ pPreset->m_sEarlyR.m_zDelay[3] = 0;
+ pPreset->m_sEarlyR.m_nGain[3] = 16153;
+ pPreset->m_sEarlyR.m_zDelay[4] = 0;
+ pPreset->m_sEarlyR.m_nGain[4] = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6470; //6483;
+ pPreset->m_nAp0_ApGain = 14768;
+ pPreset->m_nAp0_ApOut = 792;
+ pPreset->m_nAp1_ApGain = 14777;
+ pPreset->m_nAp1_ApOut = 1191;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ break;
+ case REVERB_PRESET_MEDIUMROOM:
+ case REVERB_PRESET_LARGEROOM:
+ pPreset->m_nRvbLpfFbk = 5077;
+ pPreset->m_nRvbLpfFwd = 12922;
+ pPreset->m_nEarlyGain = 27690;
+ pPreset->m_nEarlyDelay = 1311;
+ pPreset->m_nLateGain = 8191;
+ pPreset->m_nLateDelay = 3932;
+ pPreset->m_nRoomLpfFbk = 3692;
+ pPreset->m_nRoomLpfFwd = 21703;
+ pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+ pPreset->m_sEarlyL.m_nGain[0] = 22152;
+ pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+ pPreset->m_sEarlyL.m_nGain[1] = 17537;
+ pPreset->m_sEarlyL.m_zDelay[2] = 0;
+ pPreset->m_sEarlyL.m_nGain[2] = 14768;
+ pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+ pPreset->m_sEarlyL.m_nGain[3] = 14307;
+ pPreset->m_sEarlyL.m_zDelay[4] = 0;
+ pPreset->m_sEarlyL.m_nGain[4] = 13384;
+ pPreset->m_sEarlyR.m_zDelay[0] = 721;
+ pPreset->m_sEarlyR.m_nGain[0] = 20306;
+ pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+ pPreset->m_sEarlyR.m_nGain[1] = 17537;
+ pPreset->m_sEarlyR.m_zDelay[2] = 0;
+ pPreset->m_sEarlyR.m_nGain[2] = 14768;
+ pPreset->m_sEarlyR.m_zDelay[3] = 0;
+ pPreset->m_sEarlyR.m_nGain[3] = 16153;
+ pPreset->m_sEarlyR.m_zDelay[4] = 0;
+ pPreset->m_sEarlyR.m_nGain[4] = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6449;
+ pPreset->m_nAp0_ApGain = 15691;
+ pPreset->m_nAp0_ApOut = 774;
+ pPreset->m_nAp1_ApGain = 16317;
+ pPreset->m_nAp1_ApOut = 1155;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ break;
+ case REVERB_PRESET_MEDIUMHALL:
+ pPreset->m_nRvbLpfFbk = 6461;
+ pPreset->m_nRvbLpfFwd = 14307;
+ pPreset->m_nEarlyGain = 27690;
+ pPreset->m_nEarlyDelay = 1311;
+ pPreset->m_nLateGain = 8191;
+ pPreset->m_nLateDelay = 3932;
+ pPreset->m_nRoomLpfFbk = 3692;
+ pPreset->m_nRoomLpfFwd = 24569;
+ pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+ pPreset->m_sEarlyL.m_nGain[0] = 22152;
+ pPreset->m_sEarlyL.m_zDelay[1] = 1462;
+ pPreset->m_sEarlyL.m_nGain[1] = 17537;
+ pPreset->m_sEarlyL.m_zDelay[2] = 0;
+ pPreset->m_sEarlyL.m_nGain[2] = 14768;
+ pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+ pPreset->m_sEarlyL.m_nGain[3] = 14307;
+ pPreset->m_sEarlyL.m_zDelay[4] = 0;
+ pPreset->m_sEarlyL.m_nGain[4] = 13384;
+ pPreset->m_sEarlyR.m_zDelay[0] = 721;
+ pPreset->m_sEarlyR.m_nGain[0] = 20306;
+ pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+ pPreset->m_sEarlyR.m_nGain[1] = 17537;
+ pPreset->m_sEarlyR.m_zDelay[2] = 0;
+ pPreset->m_sEarlyR.m_nGain[2] = 14768;
+ pPreset->m_sEarlyR.m_zDelay[3] = 0;
+ pPreset->m_sEarlyR.m_nGain[3] = 16153;
+ pPreset->m_sEarlyR.m_zDelay[4] = 0;
+ pPreset->m_sEarlyR.m_nGain[4] = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6391;
+ pPreset->m_nAp0_ApGain = 15230;
+ pPreset->m_nAp0_ApOut = 708;
+ pPreset->m_nAp1_ApGain = 15547;
+ pPreset->m_nAp1_ApOut = 1023;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ break;
+ case REVERB_PRESET_LARGEHALL:
+ pPreset->m_nRvbLpfFbk = 8307;
+ pPreset->m_nRvbLpfFwd = 14768;
+ pPreset->m_nEarlyGain = 27690;
+ pPreset->m_nEarlyDelay = 1311;
+ pPreset->m_nLateGain = 8191;
+ pPreset->m_nLateDelay = 3932;
+ pPreset->m_nRoomLpfFbk = 3692;
+ pPreset->m_nRoomLpfFwd = 24569;
+ pPreset->m_sEarlyL.m_zDelay[0] = 1376;
+ pPreset->m_sEarlyL.m_nGain[0] = 22152;
+ pPreset->m_sEarlyL.m_zDelay[1] = 2163;
+ pPreset->m_sEarlyL.m_nGain[1] = 17537;
+ pPreset->m_sEarlyL.m_zDelay[2] = 0;
+ pPreset->m_sEarlyL.m_nGain[2] = 14768;
+ pPreset->m_sEarlyL.m_zDelay[3] = 1835;
+ pPreset->m_sEarlyL.m_nGain[3] = 14307;
+ pPreset->m_sEarlyL.m_zDelay[4] = 0;
+ pPreset->m_sEarlyL.m_nGain[4] = 13384;
+ pPreset->m_sEarlyR.m_zDelay[0] = 721;
+ pPreset->m_sEarlyR.m_nGain[0] = 20306;
+ pPreset->m_sEarlyR.m_zDelay[1] = 2621;
+ pPreset->m_sEarlyR.m_nGain[1] = 17537;
+ pPreset->m_sEarlyR.m_zDelay[2] = 0;
+ pPreset->m_sEarlyR.m_nGain[2] = 14768;
+ pPreset->m_sEarlyR.m_zDelay[3] = 0;
+ pPreset->m_sEarlyR.m_nGain[3] = 16153;
+ pPreset->m_sEarlyR.m_zDelay[4] = 0;
+ pPreset->m_sEarlyR.m_nGain[4] = 13384;
+ pPreset->m_nMaxExcursion = 127;
+ pPreset->m_nXfadeInterval = 6388;
+ pPreset->m_nAp0_ApGain = 15691;
+ pPreset->m_nAp0_ApOut = 711;
+ pPreset->m_nAp1_ApGain = 16317;
+ pPreset->m_nAp1_ApOut = 1029;
+ pPreset->m_rfu4 = 0;
+ pPreset->m_rfu5 = 0;
+ pPreset->m_rfu6 = 0;
+ pPreset->m_rfu7 = 0;
+ pPreset->m_rfu8 = 0;
+ pPreset->m_rfu9 = 0;
+ pPreset->m_rfu10 = 0;
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/media/libeffects/testlibs/EffectReverb.h b/media/libeffects/testlibs/EffectReverb.h
new file mode 100644
index 0000000..dbcd192
--- /dev/null
+++ b/media/libeffects/testlibs/EffectReverb.h
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTREVERB_H_
+#define ANDROID_EFFECTREVERB_H_
+
+#include <media/EffectEnvironmentalReverbApi.h>
+#include <media/EffectPresetReverbApi.h>
+
+
+/*------------------------------------
+ * defines
+ *------------------------------------
+*/
+
+/*
+CIRCULAR() calculates the array index using modulo arithmetic.
+The "trick" is that modulo arithmetic is simplified by masking
+the effective address where the mask is (2^n)-1. This only works
+if the buffer size is a power of two.
+*/
+#define CIRCULAR(base,offset,size) (uint32_t)( \
+ ( \
+ ((int32_t)(base)) + ((int32_t)(offset)) \
+ ) \
+ & size \
+ )
+
+#define NUM_OUTPUT_CHANNELS 2
+#define OUTPUT_CHANNELS CHANNEL_STEREO
+
+#define REVERB_BUFFER_SIZE_IN_SAMPLES_MAX 16384
+
+#define REVERB_NUM_PRESETS REVERB_PRESET_PLATE // REVERB_PRESET_NONE is not included
+#define REVERB_MAX_NUM_REFLECTIONS 5 // max num reflections per channel
+
+
+// xfade parameters
+#define REVERB_XFADE_PERIOD_IN_SECONDS (double) (100.0 / 1000.0) // xfade once every this many seconds
+
+
+/**********/
+/* the entire synth uses various flags in a bit field */
+
+/* if flag is set, synth reset has been requested */
+#define REVERB_FLAG_RESET_IS_REQUESTED 0x01 /* bit 0 */
+#define MASK_REVERB_RESET_IS_REQUESTED 0x01
+#define MASK_REVERB_RESET_IS_NOT_REQUESTED (uint32_t)(~MASK_REVERB_RESET_IS_REQUESTED)
+
+/*
+by default, we always want to update ALL channel parameters
+when we reset the synth (e.g., during GM ON)
+*/
+#define DEFAULT_REVERB_FLAGS 0x0
+
+/* coefficients for generating sin, cos */
+#define REVERB_PAN_G2 4294940151 /* -0.82842712474619 = 2 - 4/sqrt(2) */
+/*
+int32_t nPanG1 = +1.0 for sin
+int32_t nPanG1 = -1.0 for cos
+*/
+#define REVERB_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */
+
+/*************************************************************/
+// define the input injection points
+#define GUARD 5 // safety guard of this many samples
+
+#define MAX_AP_TIME (int) ((20*65536)/1000) // delay time in time units (65536th of sec)
+#define MAX_DELAY_TIME (int) ((65*65536)/1000) // delay time in time units
+#define MAX_EARLY_TIME (int) ((65*65536)/1000) // delay time in time units
+
+#define AP0_IN 0
+
+
+#define REVERB_DEFAULT_ROOM_NUMBER 1 // default preset number
+#define DEFAULT_AP0_GAIN 19400
+#define DEFAULT_AP1_GAIN -19400
+
+#define REVERB_DEFAULT_WET 32767
+#define REVERB_DEFAULT_DRY 0
+
+#define REVERB_WET_MAX 32767
+#define REVERB_WET_MIN 0
+#define REVERB_DRY_MAX 32767
+#define REVERB_DRY_MIN 0
+
+// constants for reverb density
+// The density expressed in permilles changes the Allpass delay in a linear manner in the range defined by
+// AP0_TIME_BASE to AP0_TIME_BASE + AP0_TIME_RANGE
+#define AP0_TIME_BASE (int)((9*65536)/1000)
+#define AP0_TIME_RANGE (int)((4*65536)/1000)
+#define AP1_TIME_BASE (int)((12*65536)/1000)
+#define AP1_TIME_RANGE (int)((8*65536)/1000)
+
+// constants for reverb diffusion
+// The diffusion expressed in permilles changes the Allpass gain in a linear manner in the range defined by
+// AP0_GAIN_BASE to AP0_GAIN_BASE + AP0_GAIN_RANGE
+#define AP0_GAIN_BASE (int)(9830)
+#define AP0_GAIN_RANGE (int)(19660-9830)
+#define AP1_GAIN_BASE (int)(6553)
+#define AP1_GAIN_RANGE (int)(22936-6553)
+
+
+enum reverb_state_e {
+ REVERB_STATE_UNINITIALIZED,
+ REVERB_STATE_INITIALIZED,
+ REVERB_STATE_ACTIVE,
+};
+
+/* parameters for each allpass */
+typedef struct
+{
+ uint16_t m_zApOut; // delay offset for ap out
+
+ int16_t m_nApGain; // gain for ap
+
+ uint16_t m_zApIn; // delay offset for ap in
+
+} allpass_object_t;
+
+
+/* parameters for early reflections */
+typedef struct
+{
+ uint16_t m_zDelay[REVERB_MAX_NUM_REFLECTIONS]; // delay offset for ap out
+
+ int16_t m_nGain[REVERB_MAX_NUM_REFLECTIONS]; // gain for ap
+
+} early_reflection_object_t;
+
+//demo
+typedef struct
+{
+ int16_t m_nRvbLpfFbk;
+ int16_t m_nRvbLpfFwd;
+ int16_t m_nRoomLpfFbk;
+ int16_t m_nRoomLpfFwd;
+
+ int16_t m_nEarlyGain;
+ int16_t m_nEarlyDelay;
+ int16_t m_nLateGain;
+ int16_t m_nLateDelay;
+
+ early_reflection_object_t m_sEarlyL;
+ early_reflection_object_t m_sEarlyR;
+
+ uint16_t m_nMaxExcursion; //28
+ int16_t m_nXfadeInterval;
+
+ int16_t m_nAp0_ApGain; //30
+ int16_t m_nAp0_ApOut;
+ int16_t m_nAp1_ApGain;
+ int16_t m_nAp1_ApOut;
+ int16_t m_nDiffusion;
+
+ int16_t m_rfu4;
+ int16_t m_rfu5;
+ int16_t m_rfu6;
+ int16_t m_rfu7;
+ int16_t m_rfu8;
+ int16_t m_rfu9;
+ int16_t m_rfu10; //43
+
+} reverb_preset_t;
+
+typedef struct
+{
+ reverb_preset_t m_sPreset[REVERB_NUM_PRESETS]; // array of presets(does not include REVERB_PRESET_NONE)
+
+} reverb_preset_bank_t;
+
+
+/* parameters for each reverb */
+typedef struct
+{
+ /* update counter keeps track of when synth params need updating */
+ /* only needs to be as large as REVERB_UPDATE_PERIOD_IN_SAMPLES */
+ int16_t m_nUpdateCounter;
+
+ uint16_t m_nBaseIndex; // base index for circular buffer
+
+ // reverb delay line offsets, allpass parameters, etc:
+
+ short m_nRevFbkR; // combine feedback reverb right out with dry left in
+ short m_zOutLpfL; // left reverb output
+
+ allpass_object_t m_sAp0; // allpass 0 (left channel)
+
+ uint16_t m_zD0In; // delay offset for delay line D0 in
+
+ short m_nRevFbkL; // combine feedback reverb left out with dry right in
+ short m_zOutLpfR; // right reverb output
+
+ allpass_object_t m_sAp1; // allpass 1 (right channel)
+
+ uint16_t m_zD1In; // delay offset for delay line D1 in
+
+ // delay output taps, notice criss cross order
+ uint16_t m_zD0Self; // self feeds forward d0 --> d0
+
+ uint16_t m_zD1Cross; // cross feeds across d1 --> d0
+
+ uint16_t m_zD1Self; // self feeds forward d1 --> d1
+
+ uint16_t m_zD0Cross; // cross feeds across d0 --> d1
+
+ int16_t m_nSin; // gain for self taps
+
+ int16_t m_nCos; // gain for cross taps
+
+ int16_t m_nSinIncrement; // increment for gain
+
+ int16_t m_nCosIncrement; // increment for gain
+
+ int16_t m_nRvbLpfFwd; // reverb feedback lpf forward gain (includes scaling for mixer)
+
+ int16_t m_nRvbLpfFbk; // reverb feedback lpf feedback gain
+
+ int16_t m_nRoomLpfFwd; // room lpf forward gain (includes scaling for mixer)
+
+ int16_t m_nRoomLpfFbk; // room lpf feedback gain
+
+ uint16_t m_nXfadeInterval; // update/xfade after this many samples
+
+ uint16_t m_nXfadeCounter; // keep track of when to xfade
+
+ int16_t m_nPhase; // -1 <= m_nPhase < 1
+ // but during sin,cos calculations
+ // use m_nPhase/2
+
+ int16_t m_nPhaseIncrement; // add this to m_nPhase each frame
+
+ int16_t m_nNoise; // random noise sample
+
+ uint16_t m_nMaxExcursion; // the taps can excurse +/- this amount
+
+ uint16_t m_bUseNoise; // if TRUE, use noise as input signal
+
+ uint16_t m_bBypass; // if TRUE, then bypass reverb and copy input to output
+
+ int16_t m_nCurrentRoom; // preset number for current room
+
+ int16_t m_nNextRoom; // preset number for next room
+
+ int16_t m_nEarlyGain; // gain for early (widen) signal
+ int16_t m_nEarlyDelay; // initial dealy for early (widen) signal
+ int16_t m_nEarly0in;
+ int16_t m_nEarly1in;
+ int16_t m_nLateGain; // gain for late reverb
+ int16_t m_nLateDelay;
+
+ int16_t m_nDiffusion;
+
+ early_reflection_object_t m_sEarlyL; // left channel early reflections
+ early_reflection_object_t m_sEarlyR; // right channel early reflections
+
+ short m_nDelayLine[REVERB_BUFFER_SIZE_IN_SAMPLES_MAX]; // one large delay line for all reverb elements
+
+ reverb_preset_t pPreset;
+
+ reverb_preset_bank_t m_sPreset;
+
+ //int8_t preset;
+ uint32_t m_nSamplingRate;
+ int32_t m_nUpdatePeriodInBits;
+ int32_t m_nBufferMask;
+ int32_t m_nUpdatePeriodInSamples;
+ int32_t m_nDelay0Out;
+ int32_t m_nDelay1Out;
+ int16_t m_nCosWT_5KHz;
+
+ uint16_t m_Aux; // if TRUE, is connected as auxiliary effect
+ uint16_t m_Preset; // if TRUE, expose preset revert interface
+
+ uint32_t mState;
+} reverb_object_t;
+
+
+
+typedef struct reverb_module_s {
+ const struct effect_interface_s *itfe;
+ effect_config_t config;
+ reverb_object_t context;
+} reverb_module_t;
+
+/*------------------------------------
+ * Effect API
+ *------------------------------------
+*/
+int EffectQueryNumberEffects(uint32_t *pNumEffects);
+int EffectQueryEffect(uint32_t index,
+ effect_descriptor_t *pDescriptor);
+int EffectCreate(effect_uuid_t *effectUID,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface);
+int EffectRelease(effect_interface_t interface);
+
+static int Reverb_Process(effect_interface_t self,
+ audio_buffer_t *inBuffer,
+ audio_buffer_t *outBuffer);
+static int Reverb_Command(effect_interface_t self,
+ uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *replySize,
+ void *pReplyData);
+
+
+/*------------------------------------
+ * internal functions
+ *------------------------------------
+*/
+
+int Reverb_Init(reverb_module_t *pRvbModule, int aux, int preset);
+int Reverb_Configure(reverb_module_t *pRvbModule, effect_config_t *pConfig, bool init);
+void Reverb_Reset(reverb_object_t *pReverb, bool init);
+
+int Reverb_setParameter (reverb_object_t *pReverb, int32_t param, size_t size, void *pValue);
+int Reverb_getParameter(reverb_object_t *pReverb, int32_t param, size_t *pSize, void *pValue);
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateXfade
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the xfade parameters as required
+ *
+ * Inputs:
+ * nNumSamplesToAdd - number of samples to write to buffer
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - xfade parameters will be changed
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbUpdateXfade(reverb_object_t* pReverbData, int nNumSamplesToAdd);
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateNoise
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a noise sample and limit its value
+ *
+ * Inputs:
+ * Pointer to reverb context
+ *
+ * Outputs:
+ * new limited noise value
+ *
+ * Side Effects:
+ * - pReverbData->m_nNoise value is updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static uint16_t ReverbCalculateNoise(reverb_object_t *pReverbData);
+
+/*----------------------------------------------------------------------------
+ * ReverbCalculateSinCos
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Calculate a new sin and cosine value based on the given phase
+ *
+ * Inputs:
+ * nPhase - phase angle
+ * pnSin - input old value, output new value
+ * pnCos - input old value, output new value
+ *
+ * Outputs:
+ *
+ * Side Effects:
+ * - *pnSin, *pnCos are updated
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbCalculateSinCos(int16_t nPhase, int16_t *pnSin, int16_t *pnCos);
+
+/*----------------------------------------------------------------------------
+ * Reverb
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * apply reverb to the given signal
+ *
+ * Inputs:
+ * nNu
+ * pnSin - input old value, output new value
+ * pnCos - input old value, output new value
+ *
+ * Outputs:
+ * number of samples actually reverberated
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+static int Reverb(reverb_object_t* pReverbData, int nNumSamplesToAdd, short *pOutputBuffer, short *pInputBuffer);
+
+/*----------------------------------------------------------------------------
+ * ReverbReadInPresets()
+ *----------------------------------------------------------------------------
+ * Purpose: sets global reverb preset bank to defaults
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *----------------------------------------------------------------------------
+*/
+static int ReverbReadInPresets(reverb_object_t* pReverbData);
+
+
+/*----------------------------------------------------------------------------
+ * ReverbUpdateRoom
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Update the room's preset parameters as required
+ *
+ * Inputs:
+ *
+ * Outputs:
+ *
+ *
+ * Side Effects:
+ * - reverb paramters (fbk, fwd, etc) will be changed
+ * - m_nCurrentRoom := m_nNextRoom
+ *----------------------------------------------------------------------------
+*/
+static int ReverbUpdateRoom(reverb_object_t* pReverbData, bool fullUpdate);
+
+
+static int ReverbComputeConstants(reverb_object_t *pReverbData, uint32_t samplingRate);
+
+#endif /*ANDROID_EFFECTREVERB_H_*/
diff --git a/media/libeffects/testlibs/EffectsMath.c b/media/libeffects/testlibs/EffectsMath.c
new file mode 100644
index 0000000..41ec662
--- /dev/null
+++ b/media/libeffects/testlibs/EffectsMath.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "EFFECTSMATH"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+
+#include "EffectsMath.h"
+
+// gLogTab contains pre-calculated values of log2(1 + ai5*2^-1 + ai4*2^-2 + ai3*2^-3 + ai2*2^-4 + ai1*2^-5 + ai0*2^-6)
+// for integers in the range 0 to 63 (i = ai5*2^5 + ai4*2^4 + ai3*2^3 + ai2*2^2 + ai1*2^1 + ai0*2^0)
+// It is used for a better than piece wise approximation of lin to log2 conversion
+
+static const uint16_t gLogTab[] =
+{
+ 0, 733, 1455, 2166,
+ 2866, 3556, 4236, 4907,
+ 5568, 6220, 6863, 7498,
+ 8124, 8742, 9352, 9954,
+ 10549, 11136, 11716, 12289,
+ 12855, 13415, 13968, 14514,
+ 15055, 15589, 16117, 16639,
+ 17156, 17667, 18173, 18673,
+ 19168, 19658, 20143, 20623,
+ 21098, 21568, 22034, 22495,
+ 22952, 23404, 23852, 24296,
+ 24736, 25172, 25604, 26031,
+ 26455, 26876, 27292, 27705,
+ 28114, 28520, 28922, 29321,
+ 29717, 30109, 30498, 30884,
+ 31267, 31647, 32024, 32397,
+ 32768
+};
+
+int32_t Effects_log2(uint32_t x) {
+ int32_t exp = 31 - __builtin_clz(x);
+ uint32_t segStart = x >> (exp - 6);
+ uint32_t i = segStart & 0x3F;
+ int32_t log = (int32_t)gLogTab[i];
+ int32_t logEnd = (int32_t)gLogTab[i+1];
+ segStart <<= exp - 6;
+
+ return (exp << 15) + log + (((x - segStart) * (logEnd - log)) >> (exp - 6));
+}
+
+// gExpTab[i] = (2^(i>>6)) << 22
+static const uint32_t gExpTab[] = {
+ 4194304, 4239977, 4286147, 4332820,
+ 4380002, 4427697, 4475911, 4524651,
+ 4573921, 4623728, 4674077, 4724974,
+ 4776426, 4828438, 4881016, 4934167,
+ 4987896, 5042211, 5097117, 5152621,
+ 5208729, 5265449, 5322786, 5380747,
+ 5439339, 5498570, 5558445, 5618973,
+ 5680159, 5742012, 5804539, 5867746,
+ 5931642, 5996233, 6061528, 6127533,
+ 6194258, 6261709, 6329894, 6398822,
+ 6468501, 6538938, 6610143, 6682122,
+ 6754886, 6828442, 6902799, 6977965,
+ 7053950, 7130763, 7208412, 7286906,
+ 7366255, 7446469, 7527555, 7609525,
+ 7692387, 7776152, 7860829, 7946428,
+ 8032959, 8120432, 8208857, 8298246,
+ 8388608
+};
+
+
+uint32_t Effects_exp2(int32_t x) {
+ int32_t i = x >> 15;
+ assert(i < 32);
+ x &= (1 << 15) - 1;
+ int32_t j = x >> 9;
+ x &= (1 << 9) - 1;
+ uint32_t exp = gExpTab[j];
+ uint32_t expEnd = gExpTab[j+1];
+
+ return ((exp << 9) + (expEnd - exp) * x) >> (31 - i);
+}
+
+
+int16_t Effects_MillibelsToLinear16 (int32_t nGain)
+{
+ nGain = ((nGain + MB_TO_LIN_K1) << 15 ) / MB_TO_LIN_K2;
+ uint32_t exp2 = Effects_exp2(nGain);
+
+ if (exp2 > 32767) exp2 = 32767;
+
+ return (int16_t)exp2;
+}
+
+
+int16_t Effects_Linear16ToMillibels (int32_t nGain)
+{
+ return (int16_t)(((MB_TO_LIN_K2*Effects_log2(nGain))>>15)-MB_TO_LIN_K1);
+}
+
+
+int32_t Effects_Sqrt(int32_t in)
+{
+ int32_t tmp;
+ int32_t out = 0;
+ int32_t i;
+ int32_t j;
+
+
+ if (in == 0) return 0;
+
+ if (in >= 0x10000000)
+ {
+ out = 0x4000;
+ in -= 0x10000000;
+ }
+
+ j = 32 - __builtin_clz(in);
+
+ if (j & 1) j++;
+ j >>= 1;
+
+ for (i = j; i > 0; i--) {
+ tmp = (out << i) + (1 << ((i - 1)*2));
+ if (in >= tmp)
+ {
+ out += 1 << (i-1);
+ in -= tmp;
+ }
+ }
+
+ return out;
+}
+
diff --git a/media/libeffects/testlibs/EffectsMath.h b/media/libeffects/testlibs/EffectsMath.h
new file mode 100644
index 0000000..2a44399
--- /dev/null
+++ b/media/libeffects/testlibs/EffectsMath.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2008 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTSMATH_H_
+#define ANDROID_EFFECTSMATH_H_
+
+#include <stdint.h>
+
+#if __cplusplus
+extern "C" {
+#endif
+
+/** coefs for pan, generates sin, cos */
+#define COEFF_PAN_G2 -27146 /* -0.82842712474619 = 2 - 4/sqrt(2) */
+#define COEFF_PAN_G0 23170 /* 0.707106781186547 = 1/sqrt(2) */
+
+/*
+coefficients for approximating
+2^x = gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3
+where x is a int.frac number representing number of octaves.
+Actually, we approximate only the 2^(frac) using the power series
+and implement the 2^(int) as a shift, so that
+2^x == 2^(int.frac) == 2^(int) * 2^(fract)
+ == (gn2toX0 + gn2toX1*x + gn2toX2*x^2 + gn2toX3*x^3) << (int)
+
+The gn2toX.. were generated using a best fit for a 3rd
+order polynomial, instead of taking the coefficients from
+a truncated Taylor (or Maclaurin?) series.
+*/
+
+#define GN2_TO_X0 32768 /* 1 */
+#define GN2_TO_X1 22833 /* 0.696807861328125 */
+#define GN2_TO_X2 7344 /* 0.22412109375 */
+#define GN2_TO_X3 2588 /* 0.0789794921875 */
+
+/*----------------------------------------------------------------------------
+ * Fixed Point Math
+ *----------------------------------------------------------------------------
+ * These macros are used for fixed point multiplies. If the processor
+ * supports fixed point multiplies, replace these macros with inline
+ * assembly code to improve performance.
+ *----------------------------------------------------------------------------
+*/
+
+/* Fixed point multiply 0.15 x 0.15 = 0.15 returned as 32-bits */
+#define FMUL_15x15(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((int32_t)(a) * (int32_t)(b)) >> 15)
+
+/* Fixed point multiply 0.7 x 0.7 = 0.15 returned as 32-bits */
+#define FMUL_7x7(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((int32_t)(a) * (int32_t)(b) ) << 1)
+
+/* Fixed point multiply 0.8 x 0.8 = 0.15 returned as 32-bits */
+#define FMUL_8x8(a,b) \
+ /*lint -e(704) <avoid multiply for performance>*/ \
+ (((int32_t)(a) * (int32_t)(b) ) >> 1)
+
+/* Fixed point multiply 0.8 x 1.15 = 0.15 returned as 32-bits */
+#define FMUL_8x15(a,b) \
+ /*lint -e(704) <avoid divide for performance>*/ \
+ (((int32_t)((a) << 7) * (int32_t)(b)) >> 15)
+
+/* macros for fractional phase accumulator */
+/*
+Note: changed the _U32 to _I32 on 03/14/02. This should not
+affect the phase calculations, and should allow us to reuse these
+macros for other audio sample related math.
+*/
+#define HARDWARE_BIT_WIDTH 32
+
+#define NUM_PHASE_INT_BITS 1
+#define NUM_PHASE_FRAC_BITS 15
+
+#define PHASE_FRAC_MASK (uint32_t) ((0x1L << NUM_PHASE_FRAC_BITS) -1)
+
+#define GET_PHASE_INT_PART(x) (uint32_t)((uint32_t)(x) >> NUM_PHASE_FRAC_BITS)
+#define GET_PHASE_FRAC_PART(x) (uint32_t)((uint32_t)(x) & PHASE_FRAC_MASK)
+
+#define DEFAULT_PHASE_FRAC 0
+#define DEFAULT_PHASE_INT 0
+
+/*
+Linear interpolation calculates:
+output = (1-frac) * sample[n] + (frac) * sample[n+1]
+
+where conceptually 0 <= frac < 1
+
+For a fixed point implementation, frac is actually an integer value
+with an implied binary point one position to the left. The value of
+one (unity) is given by PHASE_ONE
+one half and one quarter are useful for 4-point linear interp.
+*/
+#define PHASE_ONE (int32_t) (0x1L << NUM_PHASE_FRAC_BITS)
+
+/*
+ Multiply the signed audio sample by the unsigned fraction.
+- a is the signed audio sample
+- b is the unsigned fraction (cast to signed int as long as coef
+ uses (n-1) or less bits, where n == hardware bit width)
+*/
+#define MULT_AUDIO_COEF(audio,coef) /*lint -e704 <avoid divide for performance>*/ \
+ (int32_t)( \
+ ( \
+ ((int32_t)(audio)) * ((int32_t)(coef)) \
+ ) \
+ >> NUM_PHASE_FRAC_BITS \
+ ) \
+ /* lint +704 <restore checking>*/
+
+/* wet / dry calculation macros */
+#define NUM_WET_DRY_FRAC_BITS 7 // 15
+#define NUM_WET_DRY_INT_BITS 9 // 1
+
+/* define a 1.0 */
+#define WET_DRY_ONE (int32_t) ((0x1L << NUM_WET_DRY_FRAC_BITS))
+#define WET_DRY_MINUS_ONE (int32_t) (~WET_DRY_ONE)
+#define WET_DRY_FULL_SCALE (int32_t) (WET_DRY_ONE - 1)
+
+#define MULT_AUDIO_WET_DRY_COEF(audio,coef) /*lint -e(702) <avoid divide for performance>*/ \
+ (int32_t)( \
+ ( \
+ ((int32_t)(audio)) * ((int32_t)(coef)) \
+ ) \
+ >> NUM_WET_DRY_FRAC_BITS \
+ )
+
+/* Envelope 1 (EG1) calculation macros */
+#define NUM_EG1_INT_BITS 1
+#define NUM_EG1_FRAC_BITS 15
+
+/* the max positive gain used in the synth for EG1 */
+/* SYNTH_FULL_SCALE_EG1_GAIN must match the value in the dls2eas
+converter, otherwise, the values we read from the .eas file are bogus. */
+#define SYNTH_FULL_SCALE_EG1_GAIN (int32_t) ((0x1L << NUM_EG1_FRAC_BITS) -1)
+
+/* define a 1.0 */
+#define EG1_ONE (int32_t) ((0x1L << NUM_EG1_FRAC_BITS))
+#define EG1_MINUS_ONE (int32_t) (~SYNTH_FULL_SCALE_EG1_GAIN)
+
+#define EG1_HALF (int32_t) (EG1_ONE/2)
+#define EG1_MINUS_HALF (int32_t) (EG1_MINUS_ONE/2)
+
+/*
+We implement the EG1 using a linear gain value, which means that the
+attack segment is handled by incrementing (adding) the linear gain.
+However, EG1 treats the Decay, Sustain, and Release differently than
+the Attack portion. For Decay, Sustain, and Release, the gain is
+linear on dB scale, which is equivalent to exponential damping on
+a linear scale. Because we use a linear gain for EG1, we implement
+the Decay and Release as multiplication (instead of incrementing
+as we did for the attack segment).
+Therefore, we need the following macro to implement the multiplication
+(i.e., exponential damping) during the Decay and Release segments of
+the EG1
+*/
+#define MULT_EG1_EG1(gain,damping) /*lint -e(704) <avoid divide for performance>*/ \
+ (int32_t)( \
+ ( \
+ ((int32_t)(gain)) * ((int32_t)(damping)) \
+ ) \
+ >> NUM_EG1_FRAC_BITS \
+ )
+
+// Use the following macro specifically for the filter, when multiplying
+// the b1 coefficient. The 0 <= |b1| < 2, which therefore might overflow
+// in certain conditions because we store b1 as a 1.15 value.
+// Instead, we could store b1 as b1p (b1' == b1 "prime") where
+// b1p == b1/2, thus ensuring no potential overflow for b1p because
+// 0 <= |b1p| < 1
+// However, during the filter calculation, we must account for the fact
+// that we are using b1p instead of b1, and thereby multiply by
+// an extra factor of 2. Rather than multiply by an extra factor of 2,
+// we can instead shift the result right by one less, hence the
+// modified shift right value of (NUM_EG1_FRAC_BITS -1)
+#define MULT_EG1_EG1_X2(gain,damping) /*lint -e(702) <avoid divide for performance>*/ \
+ (int32_t)( \
+ ( \
+ ((int32_t)(gain)) * ((int32_t)(damping)) \
+ ) \
+ >> (NUM_EG1_FRAC_BITS -1) \
+ )
+
+#define SATURATE_EG1(x) /*lint -e{734} saturation operation */ \
+ ((int32_t)(x) > SYNTH_FULL_SCALE_EG1_GAIN) ? (SYNTH_FULL_SCALE_EG1_GAIN) : \
+ ((int32_t)(x) < EG1_MINUS_ONE) ? (EG1_MINUS_ONE) : (x);
+
+
+/* use "digital cents" == "dents" instead of cents */
+/* we coudl re-use the phase frac macros, but if we do,
+we must change the phase macros to cast to _I32 instead of _U32,
+because using a _U32 cast causes problems when shifting the exponent
+for the 2^x calculation, because right shift a negative values MUST
+be sign extended, or else the 2^x calculation is wrong */
+
+/* use "digital cents" == "dents" instead of cents */
+#define NUM_DENTS_FRAC_BITS 12
+#define NUM_DENTS_INT_BITS (HARDWARE_BIT_WIDTH - NUM_DENTS_FRAC_BITS)
+
+#define DENTS_FRAC_MASK (int32_t) ((0x1L << NUM_DENTS_FRAC_BITS) -1)
+
+#define GET_DENTS_INT_PART(x) /*lint -e(704) <avoid divide for performance>*/ \
+ (int32_t)((int32_t)(x) >> NUM_DENTS_FRAC_BITS)
+
+#define GET_DENTS_FRAC_PART(x) (int32_t)((int32_t)(x) & DENTS_FRAC_MASK)
+
+#define DENTS_ONE (int32_t) (0x1L << NUM_DENTS_FRAC_BITS)
+
+/* use CENTS_TO_DENTS to convert a value in cents to dents */
+#define CENTS_TO_DENTS (int32_t) (DENTS_ONE * (0x1L << NUM_EG1_FRAC_BITS) / 1200L) \
+
+
+/*
+For gain, the LFO generates a value that modulates in terms
+of dB. However, we use a linear gain value, so we must convert
+the LFO value in dB to a linear gain. Normally, we would use
+linear gain = 10^x, where x = LFO value in dB / 20.
+Instead, we implement 10^x using our 2^x approximation.
+because
+
+ 10^x = 2^(log2(10^x)) = 2^(x * log2(10))
+
+so we need to multiply by log2(10) which is just a constant.
+Ah, but just wait -- our 2^x actually doesn't exactly implement
+2^x, but it actually assumes that the input is in cents, and within
+the 2^x approximation converts its input from cents to octaves
+by dividing its input by 1200.
+
+So, in order to convert the LFO gain value in dB to something
+that our existing 2^x approximation can use, multiply the LFO gain
+by log2(10) * 1200 / 20
+
+The divide by 20 helps convert dB to linear gain, and we might
+as well incorporate that operation into this conversion.
+Of course, we need to keep some fractional bits, so multiply
+the constant by NUM_EG1_FRAC_BITS
+*/
+
+/* use LFO_GAIN_TO_CENTS to convert the LFO gain value to cents */
+#if 0
+#define DOUBLE_LOG2_10 (double) (3.32192809488736) /* log2(10) */
+
+#define DOUBLE_LFO_GAIN_TO_CENTS (double) \
+ ( \
+ (DOUBLE_LOG2_10) * \
+ 1200.0 / \
+ 20.0 \
+ )
+
+#define LFO_GAIN_TO_CENTS (int32_t) \
+ ( \
+ DOUBLE_LFO_GAIN_TO_CENTS * \
+ (0x1L << NUM_EG1_FRAC_BITS) \
+ )
+#endif
+
+#define LFO_GAIN_TO_CENTS (int32_t) (1671981156L >> (23 - NUM_EG1_FRAC_BITS))
+
+
+#define MULT_DENTS_COEF(dents,coef) /*lint -e704 <avoid divide for performance>*/ \
+ (int32_t)( \
+ ( \
+ ((int32_t)(dents)) * ((int32_t)(coef)) \
+ ) \
+ >> NUM_DENTS_FRAC_BITS \
+ ) \
+ /* lint +e704 <restore checking>*/
+
+
+/* we use 16-bits in the PC per audio sample */
+#define BITS_PER_AUDIO_SAMPLE 16
+
+/* we define 1 as 1.0 - 1 LSbit */
+#define DISTORTION_ONE (int32_t)((0x1L << (BITS_PER_AUDIO_SAMPLE-1)) -1)
+#define DISTORTION_MINUS_ONE (int32_t)(~DISTORTION_ONE)
+
+/* drive coef is given as int.frac */
+#define NUM_DRIVE_COEF_INT_BITS 1
+#define NUM_DRIVE_COEF_FRAC_BITS 4
+
+#define MULT_AUDIO_DRIVE(audio,drive) /*lint -e(702) <avoid divide for performance>*/ \
+ (int32_t) ( \
+ ( \
+ ((int32_t)(audio)) * ((int32_t)(drive)) \
+ ) \
+ >> NUM_DRIVE_COEF_FRAC_BITS \
+ )
+
+#define MULT_AUDIO_AUDIO(audio1,audio2) /*lint -e(702) <avoid divide for performance>*/ \
+ (int32_t) ( \
+ ( \
+ ((int32_t)(audio1)) * ((int32_t)(audio2)) \
+ ) \
+ >> (BITS_PER_AUDIO_SAMPLE-1) \
+ )
+
+#define SATURATE(x) \
+ ((((int32_t)(x)) > DISTORTION_ONE) ? (DISTORTION_ONE) : \
+ (((int32_t)(x)) < DISTORTION_MINUS_ONE) ? (DISTORTION_MINUS_ONE) : ((int32_t)(x)));
+
+
+/*----------------------------------------------------------------------------
+ * Effects_log2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fixed-point log2 function.
+ *
+ * Inputs:
+ * Input is interpreted as an integer (should not be 0).
+ *
+ * Outputs:
+ * Output is in 15-bit precision.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int32_t Effects_log2(uint32_t x);
+
+/*----------------------------------------------------------------------------
+ * Effects_exp2()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Fixed-point radix-2 exponent.
+ *
+ * Inputs:
+ * Input is in 15-bit precision. Must be non-negative and less than 32.
+ *
+ * Outputs:
+ * Output is an integer.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+uint32_t Effects_exp2(int32_t x);
+
+/*----------------------------------------------------------------------------
+ * Effects_MillibelsToLinear16()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform gain in millibels to linear gain multiplier:
+ *
+ * mB = 2000*log(lin/32767)
+ * => lin = 2^((mB+2000*log(32767))/2000*log(2))
+ * => lin = Effects_exp2(((mB + K1) << 15) / K2)
+ * with:
+ * K1 = 2000*log(32767) and K2 = 2000*log(2)
+ *
+ * Inputs:
+ * nGain - log scale value in millibels.
+ *
+ * Outputs:
+ * Returns a 16-bit linear value approximately equal to 2^(nGain/1024)
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+#define MB_TO_LIN_K1 9031
+#define MB_TO_LIN_K2 602
+int16_t Effects_MillibelsToLinear16 (int32_t nGain);
+
+/*----------------------------------------------------------------------------
+ * Effects_Linear16ToMillibels()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Transform linear gain multiplier to millibels
+ * mB = 2000*log(lin/32767)
+ * = 2000*log(2)*log2(lin)-2000*log(32767)
+ * => mB = K1*Effects_log2(lin) + K2
+ * with:
+ * K1 = 2000*log(2) and K2 = -2000*log(32767)
+ *
+ * Inputs:
+ * nGain - linear multiplier ranging form 0 to 32767 (corresponding to [0 1] gain range).
+ *
+ * Outputs:
+ * Returns a 16-bit log value expressed in milllibels.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int16_t Effects_Linear16ToMillibels (int32_t nGain);
+
+/*----------------------------------------------------------------------------
+ * Effects_Sqrt()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Returns the square root of the argument given.
+ *
+ * Inputs:
+ * in - positive number in the range 0 - 2^28
+ *
+ * Outputs:
+ * Returned value: square root of in.
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+*/
+int32_t Effects_Sqrt(int32_t in);
+
+#if __cplusplus
+} // extern "C"
+#endif
+
+#endif /*ANDROID_EFFECTSMATH_H_*/
+
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
new file mode 100644
index 0000000..48b45ff
--- /dev/null
+++ b/media/libeffects/visualizer/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Visualizer library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ EffectVisualizer.cpp
+
+LOCAL_CFLAGS+= -O2
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+LOCAL_MODULE:= libvisualizer
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
+LOCAL_C_INCLUDES := \
+ $(call include-path-for, graphics corecg)
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY) \ No newline at end of file
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
new file mode 100644
index 0000000..8ab57c9
--- /dev/null
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Visualizer"
+//#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <new>
+#include <media/EffectVisualizerApi.h>
+
+namespace android {
+
+// effect_interface_t interface implementation for visualizer effect
+extern "C" const struct effect_interface_s gVisualizerInterface;
+
+// Google Visualizer UUID: d069d9e0-8329-11df-9168-0002a5d5c51b
+const effect_descriptor_t gVisualizerDescriptor = {
+ {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // type
+ {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // uuid
+ EFFECT_API_VERSION,
+ (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST),
+ 0, // TODO
+ 1,
+ "Visualizer",
+ "Google Inc.",
+};
+
+enum visualizer_state_e {
+ VISUALIZER_STATE_UNINITIALIZED,
+ VISUALIZER_STATE_INITIALIZED,
+ VISUALIZER_STATE_ACTIVE,
+};
+
+struct VisualizerContext {
+ const struct effect_interface_s *mItfe;
+ effect_config_t mConfig;
+ uint32_t mState;
+ uint32_t mCaptureIdx;
+ uint32_t mCaptureSize;
+ uint32_t mCurrentBuf;
+ uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX];
+};
+
+
+//
+//--- Local functions
+//
+
+void Visualizer_reset(VisualizerContext *pContext)
+{
+ pContext->mCaptureIdx = 0;
+ pContext->mCurrentBuf = 0;
+ memset(pContext->mCaptureBuf[0], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+ memset(pContext->mCaptureBuf[1], 0, VISUALIZER_CAPTURE_SIZE_MAX);
+}
+
+//----------------------------------------------------------------------------
+// Visualizer_configure()
+//----------------------------------------------------------------------------
+// Purpose: Set input and output audio configuration.
+//
+// Inputs:
+// pContext: effect engine context
+// pConfig: pointer to effect_config_t structure holding input and output
+// configuration parameters
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Visualizer_configure(VisualizerContext *pContext, effect_config_t *pConfig)
+{
+ LOGV("Visualizer_configure start");
+
+ if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL;
+ if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL;
+ if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
+ if (pConfig->inputCfg.channels != CHANNEL_STEREO) return -EINVAL;
+ if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
+ pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
+ if (pConfig->inputCfg.format != SAMPLE_FORMAT_PCM_S15) return -EINVAL;
+
+ memcpy(&pContext->mConfig, pConfig, sizeof(effect_config_t));
+
+ Visualizer_reset(pContext);
+
+ return 0;
+}
+
+
+//----------------------------------------------------------------------------
+// Visualizer_init()
+//----------------------------------------------------------------------------
+// Purpose: Initialize engine with default configuration.
+//
+// Inputs:
+// pContext: effect engine context
+//
+// Outputs:
+//
+//----------------------------------------------------------------------------
+
+int Visualizer_init(VisualizerContext *pContext)
+{
+ pContext->mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+ pContext->mConfig.inputCfg.channels = CHANNEL_STEREO;
+ pContext->mConfig.inputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->mConfig.inputCfg.samplingRate = 44100;
+ pContext->mConfig.inputCfg.bufferProvider.getBuffer = NULL;
+ pContext->mConfig.inputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->mConfig.inputCfg.bufferProvider.cookie = NULL;
+ pContext->mConfig.inputCfg.mask = EFFECT_CONFIG_ALL;
+ pContext->mConfig.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+ pContext->mConfig.outputCfg.channels = CHANNEL_STEREO;
+ pContext->mConfig.outputCfg.format = SAMPLE_FORMAT_PCM_S15;
+ pContext->mConfig.outputCfg.samplingRate = 44100;
+ pContext->mConfig.outputCfg.bufferProvider.getBuffer = NULL;
+ pContext->mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
+ pContext->mConfig.outputCfg.bufferProvider.cookie = NULL;
+ pContext->mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+ pContext->mCaptureSize = VISUALIZER_CAPTURE_SIZE_MAX;
+
+ Visualizer_configure(pContext, &pContext->mConfig);
+
+ return 0;
+}
+
+//
+//--- Effect Library Interface Implementation
+//
+
+extern "C" int EffectQueryNumberEffects(uint32_t *pNumEffects) {
+ *pNumEffects = 1;
+ return 0;
+}
+
+extern "C" int EffectQueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+ if (pDescriptor == NULL) {
+ return -EINVAL;
+ }
+ if (index > 0) {
+ return -EINVAL;
+ }
+ memcpy(pDescriptor, &gVisualizerDescriptor, sizeof(effect_descriptor_t));
+ return 0;
+}
+
+extern "C" int EffectCreate(effect_uuid_t *uuid,
+ int32_t sessionId,
+ int32_t ioId,
+ effect_interface_t *pInterface) {
+ int ret;
+ int i;
+
+ if (pInterface == NULL || uuid == NULL) {
+ return -EINVAL;
+ }
+
+ if (memcmp(uuid, &gVisualizerDescriptor.uuid, sizeof(effect_uuid_t)) != 0) {
+ return -EINVAL;
+ }
+
+ VisualizerContext *pContext = new VisualizerContext;
+
+ pContext->mItfe = &gVisualizerInterface;
+ pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+
+ ret = Visualizer_init(pContext);
+ if (ret < 0) {
+ LOGW("EffectCreate() init failed");
+ delete pContext;
+ return ret;
+ }
+
+ *pInterface = (effect_interface_t)pContext;
+
+ pContext->mState = VISUALIZER_STATE_INITIALIZED;
+
+ LOGV("EffectCreate %p", pContext);
+
+ return 0;
+
+}
+
+extern "C" int EffectRelease(effect_interface_t interface) {
+ VisualizerContext * pContext = (VisualizerContext *)interface;
+
+ LOGV("EffectRelease %p", interface);
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+ pContext->mState = VISUALIZER_STATE_UNINITIALIZED;
+ delete pContext;
+
+ return 0;
+}
+
+//
+//--- Effect Control Interface Implementation
+//
+
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
+extern "C" int Visualizer_process(
+ effect_interface_t self,audio_buffer_t *inBuffer, audio_buffer_t *outBuffer)
+{
+ android::VisualizerContext * pContext = (android::VisualizerContext *)self;
+
+ if (pContext == NULL) {
+ return -EINVAL;
+ }
+
+ if (inBuffer == NULL || inBuffer->raw == NULL ||
+ outBuffer == NULL || outBuffer->raw == NULL ||
+ inBuffer->frameCount != outBuffer->frameCount ||
+ inBuffer->frameCount == 0) {
+ return -EINVAL;
+ }
+
+ // all code below assumes stereo 16 bit PCM output and input
+ uint32_t captIdx;
+ uint32_t inIdx;
+ uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
+ for (inIdx = 0, captIdx = pContext->mCaptureIdx;
+ inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
+ inIdx++, captIdx++) {
+ int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
+ smp = (smp + (1 << 8)) >> 9;
+ buf[captIdx] = ((uint8_t)smp)^0x80;
+ }
+ pContext->mCaptureIdx = captIdx;
+
+ // go to next buffer when buffer full
+ if (pContext->mCaptureIdx == pContext->mCaptureSize) {
+ pContext->mCurrentBuf ^= 1;
+ pContext->mCaptureIdx = 0;
+ }
+
+ if (inBuffer->raw != outBuffer->raw) {
+ if (pContext->mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ for (size_t i = 0; i < outBuffer->frameCount*2; i++) {
+ outBuffer->s16[i] = clamp16(outBuffer->s16[i] + inBuffer->s16[i]);
+ }
+ } else {
+ memcpy(outBuffer->raw, inBuffer->raw, outBuffer->frameCount * 2 * sizeof(int16_t));
+ }
+ }
+ if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
+ return -ENODATA;
+ }
+ return 0;
+} // end Visualizer_process
+
+extern "C" int Visualizer_command(effect_interface_t self, uint32_t cmdCode, uint32_t cmdSize,
+ void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+ android::VisualizerContext * pContext = (android::VisualizerContext *)self;
+ int retsize;
+
+ if (pContext == NULL || pContext->mState == VISUALIZER_STATE_UNINITIALIZED) {
+ return -EINVAL;
+ }
+
+// LOGV("Visualizer_command command %d cmdSize %d",cmdCode, cmdSize);
+
+ switch (cmdCode) {
+ case EFFECT_CMD_INIT:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Visualizer_init(pContext);
+ break;
+ case EFFECT_CMD_CONFIGURE:
+ if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+ || pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ *(int *) pReplyData = Visualizer_configure(pContext,
+ (effect_config_t *) pCmdData);
+ break;
+ case EFFECT_CMD_RESET:
+ Visualizer_reset(pContext);
+ break;
+ case EFFECT_CMD_ENABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pContext->mState != VISUALIZER_STATE_INITIALIZED) {
+ return -ENOSYS;
+ }
+ pContext->mState = VISUALIZER_STATE_ACTIVE;
+ LOGV("EFFECT_CMD_ENABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_DISABLE:
+ if (pReplyData == NULL || *replySize != sizeof(int)) {
+ return -EINVAL;
+ }
+ if (pContext->mState != VISUALIZER_STATE_ACTIVE) {
+ return -ENOSYS;
+ }
+ pContext->mState = VISUALIZER_STATE_INITIALIZED;
+ LOGV("EFFECT_CMD_DISABLE() OK");
+ *(int *)pReplyData = 0;
+ break;
+ case EFFECT_CMD_GET_PARAM: {
+ if (pCmdData == NULL ||
+ cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
+ pReplyData == NULL ||
+ *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) {
+ return -EINVAL;
+ }
+ memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t));
+ effect_param_t *p = (effect_param_t *)pReplyData;
+ p->status = 0;
+ *replySize = sizeof(effect_param_t) + sizeof(uint32_t);
+ if (p->psize != sizeof(uint32_t) ||
+ *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+ p->status = -EINVAL;
+ break;
+ }
+ LOGV("get mCaptureSize = %d", pContext->mCaptureSize);
+ *((uint32_t *)p->data + 1) = pContext->mCaptureSize;
+ p->vsize = sizeof(uint32_t);
+ *replySize += sizeof(uint32_t);
+ } break;
+ case EFFECT_CMD_SET_PARAM: {
+ if (pCmdData == NULL ||
+ cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) ||
+ pReplyData == NULL || *replySize != sizeof(int32_t)) {
+ return -EINVAL;
+ }
+ *(int32_t *)pReplyData = 0;
+ effect_param_t *p = (effect_param_t *)pCmdData;
+ if (p->psize != sizeof(uint32_t) ||
+ p->vsize != sizeof(uint32_t) ||
+ *(uint32_t *)p->data != VISU_PARAM_CAPTURE_SIZE) {
+ *(int32_t *)pReplyData = -EINVAL;
+ break;;
+ }
+ pContext->mCaptureSize = *((uint32_t *)p->data + 1);
+ LOGV("set mCaptureSize = %d", pContext->mCaptureSize);
+ } break;
+ case EFFECT_CMD_SET_DEVICE:
+ case EFFECT_CMD_SET_VOLUME:
+ case EFFECT_CMD_SET_AUDIO_MODE:
+ break;
+
+
+ case VISU_CMD_CAPTURE:
+ if (pReplyData == NULL || *replySize != (int)pContext->mCaptureSize) {
+ LOGV("VISU_CMD_CAPTURE() error *replySize %d pContext->mCaptureSize %d",
+ *replySize, pContext->mCaptureSize);
+ return -EINVAL;
+ }
+ if (pContext->mState == VISUALIZER_STATE_ACTIVE) {
+ memcpy(pReplyData,
+ pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1],
+ pContext->mCaptureSize);
+ } else {
+ memset(pReplyData, 0x80, pContext->mCaptureSize);
+ }
+ break;
+
+ default:
+ LOGW("Visualizer_command invalid command %d",cmdCode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+// effect_interface_t interface implementation for visualizer effect
+const struct effect_interface_s gVisualizerInterface = {
+ Visualizer_process,
+ Visualizer_command
+};
+
+} // namespace
+
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 3adabcc..977e6be 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -12,6 +12,7 @@ LOCAL_SRC_FILES:= \
mediaplayer.cpp \
IMediaPlayerService.cpp \
IMediaPlayerClient.cpp \
+ IMediaRecorderClient.cpp \
IMediaPlayer.cpp \
IMediaRecorder.cpp \
Metadata.cpp \
@@ -26,7 +27,11 @@ LOCAL_SRC_FILES:= \
MediaScannerClient.cpp \
autodetect.cpp \
IMediaDeathNotifier.cpp \
- MediaProfiles.cpp
+ MediaProfiles.cpp \
+ IEffect.cpp \
+ IEffectClient.cpp \
+ AudioEffect.cpp \
+ Visualizer.cpp
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
new file mode 100644
index 0000000..3cdf48a
--- /dev/null
+++ b/media/libmedia/AudioEffect.cpp
@@ -0,0 +1,462 @@
+/*
+**
+** Copyright 2010, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioEffect"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <private/media/AudioEffectShared.h>
+#include <media/AudioEffect.h>
+
+#include <utils/Log.h>
+#include <cutils/atomic.h>
+#include <binder/IPCThreadState.h>
+
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+AudioEffect::AudioEffect()
+ : mStatus(NO_INIT)
+{
+}
+
+
+AudioEffect::AudioEffect(const effect_uuid_t *type,
+ const effect_uuid_t *uuid,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t output
+ )
+ : mStatus(NO_INIT)
+{
+ mStatus = set(type, uuid, priority, cbf, user, sessionId, output);
+}
+
+AudioEffect::AudioEffect(const char *typeStr,
+ const char *uuidStr,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t output
+ )
+ : mStatus(NO_INIT)
+{
+ effect_uuid_t type;
+ effect_uuid_t *pType = NULL;
+ effect_uuid_t uuid;
+ effect_uuid_t *pUuid = NULL;
+
+ LOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
+
+ if (typeStr != NULL) {
+ if (stringToGuid(typeStr, &type) == NO_ERROR) {
+ pType = &type;
+ }
+ }
+
+ if (uuidStr != NULL) {
+ if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
+ pUuid = &uuid;
+ }
+ }
+
+ mStatus = set(pType, pUuid, priority, cbf, user, sessionId, output);
+}
+
+status_t AudioEffect::set(const effect_uuid_t *type,
+ const effect_uuid_t *uuid,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t output)
+{
+ sp<IEffect> iEffect;
+ sp<IMemory> cblk;
+ int enabled;
+
+ LOGV("set %p mUserData: %p", this, user);
+
+ if (mIEffect != 0) {
+ LOGW("Effect already in use");
+ return INVALID_OPERATION;
+ }
+
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ LOGE("set(): Could not get audioflinger");
+ return NO_INIT;
+ }
+
+ if (type == NULL && uuid == NULL) {
+ LOGW("Must specify at least type or uuid");
+ return BAD_VALUE;
+ }
+
+ mPriority = priority;
+ mCbf = cbf;
+ mUserData = user;
+ mSessionId = sessionId;
+
+ memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
+ memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+ memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+
+ if (type != NULL) {
+ memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t));
+ }
+ if (uuid != NULL) {
+ memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t));
+ }
+
+ mIEffectClient = new EffectClient(this);
+
+ iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
+ mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
+
+ if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+ LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
+ return mStatus;
+ }
+
+ mEnabled = (volatile int32_t)enabled;
+
+ mIEffect = iEffect;
+ cblk = iEffect->getCblk();
+ if (cblk == 0) {
+ mStatus = NO_INIT;
+ LOGE("Could not get control block");
+ return mStatus;
+ }
+
+ mIEffect = iEffect;
+ mCblkMemory = cblk;
+ mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
+ int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
+ mCblk->buffer = (uint8_t *)mCblk + bufOffset;
+
+ iEffect->asBinder()->linkToDeath(mIEffectClient);
+ LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ", this, mDescriptor.name, mId, mStatus, mEnabled);
+
+ return mStatus;
+}
+
+
+AudioEffect::~AudioEffect()
+{
+ LOGV("Destructor %p", this);
+
+ if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
+ setEnabled(false);
+ if (mIEffect != NULL) {
+ mIEffect->disconnect();
+ mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
+ }
+ IPCThreadState::self()->flushCommands();
+ }
+ mIEffect.clear();
+ mIEffectClient.clear();
+ mCblkMemory.clear();
+}
+
+
+status_t AudioEffect::initCheck() const
+{
+ return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+effect_descriptor_t AudioEffect::descriptor() const
+{
+ return mDescriptor;
+}
+
+bool AudioEffect::getEnabled() const
+{
+ return (mEnabled != 0);
+}
+
+status_t AudioEffect::setEnabled(bool enabled)
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ if (enabled) {
+ LOGV("enable %p", this);
+ if (android_atomic_or(1, &mEnabled) == 0) {
+ return mIEffect->enable();
+ }
+ } else {
+ LOGV("disable %p", this);
+ if (android_atomic_and(~1, &mEnabled) == 1) {
+ return mIEffect->disable();
+ }
+ }
+ return INVALID_OPERATION;
+}
+
+status_t AudioEffect::command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *cmdData,
+ uint32_t *replySize,
+ void *replyData)
+{
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ return INVALID_OPERATION;
+ }
+
+ return mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
+}
+
+
+status_t AudioEffect::setParameter(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ uint32_t size = sizeof(int);
+ uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+ LOGV("setParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+ return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size, &param->status);
+}
+
+status_t AudioEffect::setParameterDeferred(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mCblk->lock);
+
+ int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+ int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
+
+ if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
+ return NO_MEMORY;
+ }
+ int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
+ *p++ = size;
+ memcpy(p, param, sizeof(effect_param_t) + psize);
+ mCblk->clientIndex += size;
+
+ return NO_ERROR;
+}
+
+status_t AudioEffect::setParameterCommit()
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ Mutex::Autolock _l(mCblk->lock);
+ if (mCblk->clientIndex == 0) {
+ return INVALID_OPERATION;
+ }
+ uint32_t size = 0;
+ return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
+}
+
+status_t AudioEffect::getParameter(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ return INVALID_OPERATION;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ LOGV("getParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+ uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+ return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param, &psize, param);
+}
+
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::binderDied()
+{
+ LOGW("IEffect died");
+ mStatus = NO_INIT;
+ if (mCbf) {
+ status_t status = DEAD_OBJECT;
+ mCbf(EVENT_ERROR, mUserData, &status);
+ }
+ mIEffect.clear();
+}
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::controlStatusChanged(bool controlGranted)
+{
+ LOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf, mUserData);
+ if (controlGranted) {
+ if (mStatus == ALREADY_EXISTS) {
+ mStatus = NO_ERROR;
+ }
+ } else {
+ if (mStatus == NO_ERROR) {
+ mStatus = ALREADY_EXISTS;
+ }
+ }
+ if (mCbf) {
+ mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
+ }
+}
+
+void AudioEffect::enableStatusChanged(bool enabled)
+{
+ LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
+ if (mStatus == ALREADY_EXISTS) {
+ mEnabled = enabled;
+ if (mCbf) {
+ mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
+ }
+ }
+}
+
+void AudioEffect::commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *cmdData,
+ uint32_t replySize,
+ void *replyData)
+{
+ if (cmdData == NULL || replyData == NULL) {
+ return;
+ }
+
+ if (mCbf && cmdCode == EFFECT_CMD_SET_PARAM) {
+ effect_param_t *cmd = (effect_param_t *)cmdData;
+ cmd->status = *(int32_t *)replyData;
+ mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::loadEffectLibrary(const char *libPath, int *handle)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->loadEffectLibrary(libPath, handle);
+}
+
+status_t AudioEffect::unloadEffectLibrary(int handle)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->unloadEffectLibrary(handle);
+}
+
+status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->queryNumberEffects(numEffects);
+}
+
+status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->queryEffect(index, descriptor);
+}
+
+status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->getEffectDescriptor(uuid, descriptor);
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
+{
+ if (str == NULL || guid == NULL) {
+ return BAD_VALUE;
+ }
+
+ int tmp[10];
+
+ if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+ return BAD_VALUE;
+ }
+ guid->timeLow = (uint32_t)tmp[0];
+ guid->timeMid = (uint16_t)tmp[1];
+ guid->timeHiAndVersion = (uint16_t)tmp[2];
+ guid->clockSeq = (uint16_t)tmp[3];
+ guid->node[0] = (uint8_t)tmp[4];
+ guid->node[1] = (uint8_t)tmp[5];
+ guid->node[2] = (uint8_t)tmp[6];
+ guid->node[3] = (uint8_t)tmp[7];
+ guid->node[4] = (uint8_t)tmp[8];
+ guid->node[5] = (uint8_t)tmp[9];
+
+ return NO_ERROR;
+}
+
+status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
+{
+ if (guid == NULL || str == NULL) {
+ return BAD_VALUE;
+ }
+
+ snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ guid->timeLow,
+ guid->timeMid,
+ guid->timeHiAndVersion,
+ guid->clockSeq,
+ guid->node[0],
+ guid->node[1],
+ guid->node[2],
+ guid->node[3],
+ guid->node[4],
+ guid->node[5]);
+
+ return NO_ERROR;
+}
+
+
+}; // namespace android
+
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index ad037d6..a6c515c 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -41,11 +41,43 @@
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
namespace android {
+// ---------------------------------------------------------------------------
+
+// static
+status_t AudioRecord::getMinFrameCount(
+ int* frameCount,
+ uint32_t sampleRate,
+ int format,
+ int channelCount)
+{
+ size_t size = 0;
+ if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &size)
+ != NO_ERROR) {
+ LOGE("AudioSystem could not query the input buffer size.");
+ return NO_INIT;
+ }
+
+ if (size == 0) {
+ LOGE("Unsupported configuration: sampleRate %d, format %d, channelCount %d",
+ sampleRate, format, channelCount);
+ return BAD_VALUE;
+ }
+
+ // We double the size of input buffer for ping pong use of record buffer.
+ size <<= 1;
+
+ if (AudioSystem::isLinearPCM(format)) {
+ size /= channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
+ }
+
+ *frameCount = size;
+ return NO_ERROR;
+}
// ---------------------------------------------------------------------------
AudioRecord::AudioRecord()
- : mStatus(NO_INIT)
+ : mStatus(NO_INIT), mSessionId(0)
{
}
@@ -58,11 +90,12 @@ AudioRecord::AudioRecord(
uint32_t flags,
callback_t cbf,
void* user,
- int notificationFrames)
- : mStatus(NO_INIT)
+ int notificationFrames,
+ int sessionId)
+ : mStatus(NO_INIT), mSessionId(0)
{
mStatus = set(inputSource, sampleRate, format, channels,
- frameCount, flags, cbf, user, notificationFrames);
+ frameCount, flags, cbf, user, notificationFrames, sessionId);
}
AudioRecord::~AudioRecord()
@@ -91,7 +124,8 @@ status_t AudioRecord::set(
callback_t cbf,
void* user,
int notificationFrames,
- bool threadCanCallJava)
+ bool threadCanCallJava,
+ int sessionId)
{
LOGV("set(): sampleRate %d, channels %d, frameCount %d",sampleRate, channels, frameCount);
@@ -119,6 +153,7 @@ status_t AudioRecord::set(
if (!AudioSystem::isInputChannel(channels)) {
return BAD_VALUE;
}
+
int channelCount = AudioSystem::popCount(channels);
audio_io_handle_t input = AudioSystem::getInput(inputSource,
@@ -129,29 +164,11 @@ status_t AudioRecord::set(
}
// validate framecount
- size_t inputBuffSizeInBytes = -1;
- if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
- != NO_ERROR) {
- LOGE("AudioSystem could not query the input buffer size.");
- return NO_INIT;
- }
-
- if (inputBuffSizeInBytes == 0) {
- LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
- sampleRate, channelCount, format);
- return BAD_VALUE;
- }
-
- int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
- if (AudioSystem::isLinearPCM(format)) {
- frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? sizeof(int16_t) : sizeof(int8_t));
- } else {
- frameSizeInBytes = sizeof(int8_t);
+ int minFrameCount = 0;
+ status_t status = getMinFrameCount(&minFrameCount, sampleRate, format, channelCount);
+ if (status != NO_ERROR) {
+ return status;
}
-
-
- // We use 2* size of input buffer for ping pong use of record buffer.
- int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
if (frameCount == 0) {
@@ -164,10 +181,11 @@ status_t AudioRecord::set(
notificationFrames = frameCount/2;
}
- // create the IAudioRecord
- status_t status = openRecord(sampleRate, format, channelCount,
- frameCount, flags, input);
+ mSessionId = sessionId;
+ // create the IAudioRecord
+ status = openRecord(sampleRate, format, channelCount,
+ frameCount, flags, input);
if (status != NO_ERROR) {
return status;
}
@@ -414,6 +432,7 @@ status_t AudioRecord::openRecord(
channelCount,
frameCount,
((uint16_t)flags) << 16,
+ &mSessionId,
&status);
if (record == 0) {
LOGE("AudioFlinger could not create record track, status: %d", status);
@@ -430,7 +449,7 @@ status_t AudioRecord::openRecord(
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- mCblk->out = 0;
+ mCblk->flags &= ~CBLK_DIRECTION_MSK;
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
return NO_ERROR;
@@ -532,6 +551,11 @@ audio_io_handle_t AudioRecord::getInput()
return mInput;
}
+int AudioRecord::getSessionId()
+{
+ return mSessionId;
+}
+
// -------------------------------------------------------------------------
ssize_t AudioRecord::read(void* buffer, size_t userSize)
@@ -644,10 +668,10 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
// Manage overrun callback
if (mActive && (mCblk->framesAvailable_l() == 0)) {
- LOGV("Overrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
- if (mCblk->flowControlFlag == 0) {
+ LOGV("Overrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags);
+ if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
mCbf(EVENT_OVERRUN, mUserData, 0);
- mCblk->flowControlFlag = 1;
+ mCblk->flags |= CBLK_UNDERRUN_ON;
}
}
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 5e6ce42..7e3b743 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -364,6 +364,12 @@ unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
return result;
}
+int AudioSystem::newAudioSessionId() {
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return 0;
+ return af->newAudioSessionId();
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {
@@ -584,18 +590,22 @@ audio_io_handle_t AudioSystem::getOutput(stream_type stream,
return output;
}
-status_t AudioSystem::startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+status_t AudioSystem::startOutput(audio_io_handle_t output,
+ AudioSystem::stream_type stream,
+ int session)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- return aps->startOutput(output, stream);
+ return aps->startOutput(output, stream, session);
}
-status_t AudioSystem::stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+status_t AudioSystem::stopOutput(audio_io_handle_t output,
+ AudioSystem::stream_type stream,
+ int session)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
- return aps->stopOutput(output, stream);
+ return aps->stopOutput(output, stream, session);
}
void AudioSystem::releaseOutput(audio_io_handle_t output)
@@ -660,6 +670,38 @@ status_t AudioSystem::getStreamVolumeIndex(stream_type stream, int *index)
return aps->getStreamVolumeIndex(stream, index);
}
+uint32_t AudioSystem::getStrategyForStream(AudioSystem::stream_type stream)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return 0;
+ return aps->getStrategyForStream(stream);
+}
+
+audio_io_handle_t AudioSystem::getOutputForEffect(effect_descriptor_t *desc)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->getOutputForEffect(desc);
+}
+
+status_t AudioSystem::registerEffect(effect_descriptor_t *desc,
+ audio_io_handle_t output,
+ uint32_t strategy,
+ int session,
+ int id)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->registerEffect(desc, output, strategy, session, id);
+}
+
+status_t AudioSystem::unregisterEffect(int id)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->unregisterEffect(id);
+}
+
// ---------------------------------------------------------------------------
void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) {
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index cd7bcd5..890786e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -41,6 +41,35 @@
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
namespace android {
+// ---------------------------------------------------------------------------
+
+// static
+status_t AudioTrack::getMinFrameCount(
+ int* frameCount,
+ int streamType,
+ uint32_t sampleRate)
+{
+ int afSampleRate;
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+ int afFrameCount;
+ if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+ uint32_t afLatency;
+ if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ // Ensure that buffer depth covers at least audio hardware latency
+ uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
+ if (minBufCount < 2) minBufCount = 2;
+
+ *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :
+ afFrameCount * minBufCount * sampleRate / afSampleRate;
+ return NO_ERROR;
+}
// ---------------------------------------------------------------------------
@@ -58,11 +87,13 @@ AudioTrack::AudioTrack(
uint32_t flags,
callback_t cbf,
void* user,
- int notificationFrames)
+ int notificationFrames,
+ int sessionId)
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
- frameCount, flags, cbf, user, notificationFrames, 0);
+ frameCount, flags, cbf, user, notificationFrames,
+ 0, false, sessionId);
}
AudioTrack::AudioTrack(
@@ -74,11 +105,13 @@ AudioTrack::AudioTrack(
uint32_t flags,
callback_t cbf,
void* user,
- int notificationFrames)
+ int notificationFrames,
+ int sessionId)
: mStatus(NO_INIT)
{
mStatus = set(streamType, sampleRate, format, channels,
- 0, flags, cbf, user, notificationFrames, sharedBuffer);
+ 0, flags, cbf, user, notificationFrames,
+ sharedBuffer, false, sessionId);
}
AudioTrack::~AudioTrack()
@@ -110,7 +143,8 @@ status_t AudioTrack::set(
void* user,
int notificationFrames,
const sp<IMemory>& sharedBuffer,
- bool threadCanCallJava)
+ bool threadCanCallJava,
+ int sessionId)
{
LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size());
@@ -124,10 +158,6 @@ status_t AudioTrack::set(
if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
return NO_INIT;
}
- int afFrameCount;
- if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
- return NO_INIT;
- }
uint32_t afLatency;
if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
return NO_INIT;
@@ -173,48 +203,17 @@ status_t AudioTrack::set(
return BAD_VALUE;
}
- if (!AudioSystem::isLinearPCM(format)) {
- if (sharedBuffer != 0) {
- frameCount = sharedBuffer->size();
- }
- } else {
- // Ensure that buffer depth covers at least audio hardware latency
- uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
- if (minBufCount < 2) minBufCount = 2;
-
- int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
-
- if (sharedBuffer == 0) {
- if (frameCount == 0) {
- frameCount = minFrameCount;
- }
- if (notificationFrames == 0) {
- notificationFrames = frameCount/2;
- }
- // Make sure that application is notified with sufficient margin
- // before underrun
- if (notificationFrames > frameCount/2) {
- notificationFrames = frameCount/2;
- }
- if (frameCount < minFrameCount) {
- LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
- return BAD_VALUE;
- }
- } else {
- // Ensure that buffer alignment matches channelcount
- if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
- LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
- return BAD_VALUE;
- }
- frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
- }
- }
-
mVolume[LEFT] = 1.0f;
mVolume[RIGHT] = 1.0f;
+ mSendLevel = 0;
+ mFrameCount = frameCount;
+ mNotificationFramesReq = notificationFrames;
+ mSessionId = sessionId;
+ mAuxEffectId = 0;
+
// create the IAudioTrack
status_t status = createTrack(streamType, sampleRate, format, channelCount,
- frameCount, flags, sharedBuffer, output);
+ frameCount, flags, sharedBuffer, output, true);
if (status != NO_ERROR) {
return status;
@@ -238,10 +237,7 @@ status_t AudioTrack::set(
mMuted = false;
mActive = 0;
mCbf = cbf;
- mNotificationFrames = notificationFrames;
- mRemainingFrames = notificationFrames;
mUserData = user;
- mLatency = afLatency + (1000*mFrameCount) / sampleRate;
mLoopCount = 0;
mMarkerPosition = 0;
mMarkerReached = false;
@@ -281,7 +277,7 @@ int AudioTrack::channelCount() const
uint32_t AudioTrack::frameCount() const
{
- return mFrameCount;
+ return mCblk->frameCount;
}
int AudioTrack::frameSize() const
@@ -303,6 +299,7 @@ sp<IMemory>& AudioTrack::sharedBuffer()
void AudioTrack::start()
{
sp<AudioTrackThread> t = mAudioTrackThread;
+ status_t status;
LOGV("start %p", this);
if (t != 0) {
@@ -325,11 +322,18 @@ void AudioTrack::start()
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
- status_t status = mAudioTrack->start();
+ if (mCblk->flags & CBLK_INVALID_MSK) {
+ LOGW("start() track %p invalidated, creating a new one", this);
+ // no need to clear the invalid flag as this cblk will not be used anymore
+ // force new track creation
+ status = DEAD_OBJECT;
+ } else {
+ status = mAudioTrack->start();
+ }
if (status == DEAD_OBJECT) {
LOGV("start() dead IAudioTrack: creating a new one");
status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
- mFrameCount, mFlags, mSharedBuffer, getOutput());
+ mFrameCount, mFlags, mSharedBuffer, getOutput(), false);
if (status == NO_ERROR) {
status = mAudioTrack->start();
if (status == NO_ERROR) {
@@ -430,19 +434,50 @@ bool AudioTrack::muted() const
return mMuted;
}
-void AudioTrack::setVolume(float left, float right)
+status_t AudioTrack::setVolume(float left, float right)
{
+ if (left > 1.0f || right > 1.0f) {
+ return BAD_VALUE;
+ }
+
mVolume[LEFT] = left;
mVolume[RIGHT] = right;
// write must be atomic
- mCblk->volumeLR = (int32_t(int16_t(left * 0x1000)) << 16) | int16_t(right * 0x1000);
+ mCblk->volumeLR = (uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000);
+
+ return NO_ERROR;
}
void AudioTrack::getVolume(float* left, float* right)
{
- *left = mVolume[LEFT];
- *right = mVolume[RIGHT];
+ if (left != NULL) {
+ *left = mVolume[LEFT];
+ }
+ if (right != NULL) {
+ *right = mVolume[RIGHT];
+ }
+}
+
+status_t AudioTrack::setAuxEffectSendLevel(float level)
+{
+ LOGV("setAuxEffectSendLevel(%f)", level);
+ if (level > 1.0f) {
+ return BAD_VALUE;
+ }
+
+ mSendLevel = level;
+
+ mCblk->sendLevel = uint16_t(level * 0x1000);
+
+ return NO_ERROR;
+}
+
+void AudioTrack::getAuxEffectSendLevel(float* level)
+{
+ if (level != NULL) {
+ *level = mSendLevel;
+ }
}
status_t AudioTrack::setSampleRate(int rate)
@@ -479,14 +514,14 @@ status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount
}
if (loopStart >= loopEnd ||
- loopEnd - loopStart > mFrameCount) {
- LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, mFrameCount, cblk->user);
+ loopEnd - loopStart > cblk->frameCount) {
+ LOGE("setLoop invalid value: loopStart %d, loopEnd %d, loopCount %d, framecount %d, user %d", loopStart, loopEnd, loopCount, cblk->frameCount, cblk->user);
return BAD_VALUE;
}
- if ((mSharedBuffer != 0) && (loopEnd > mFrameCount)) {
+ if ((mSharedBuffer != 0) && (loopEnd > cblk->frameCount)) {
LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
- loopStart, loopEnd, mFrameCount);
+ loopStart, loopEnd, cblk->frameCount);
return BAD_VALUE;
}
@@ -566,7 +601,7 @@ status_t AudioTrack::setPosition(uint32_t position)
if (position > mCblk->user) return BAD_VALUE;
mCblk->server = position;
- mCblk->forceReady = 1;
+ mCblk->flags |= CBLK_FORCEREADY_ON;
return NO_ERROR;
}
@@ -586,7 +621,7 @@ status_t AudioTrack::reload()
flush();
- mCblk->stepUser(mFrameCount);
+ mCblk->stepUser(mCblk->frameCount);
return NO_ERROR;
}
@@ -597,6 +632,21 @@ audio_io_handle_t AudioTrack::getOutput()
mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
}
+int AudioTrack::getSessionId()
+{
+ return mSessionId;
+}
+
+status_t AudioTrack::attachAuxEffect(int effectId)
+{
+ LOGV("attachAuxEffect(%d)", effectId);
+ status_t status = mAudioTrack->attachAuxEffect(effectId);
+ if (status == NO_ERROR) {
+ mAuxEffectId = effectId;
+ }
+ return status;
+}
+
// -------------------------------------------------------------------------
status_t AudioTrack::createTrack(
@@ -607,7 +657,8 @@ status_t AudioTrack::createTrack(
int frameCount,
uint32_t flags,
const sp<IMemory>& sharedBuffer,
- audio_io_handle_t output)
+ audio_io_handle_t output,
+ bool enforceFrameCount)
{
status_t status;
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
@@ -616,6 +667,61 @@ status_t AudioTrack::createTrack(
return NO_INIT;
}
+ int afSampleRate;
+ if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+ int afFrameCount;
+ if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+ uint32_t afLatency;
+ if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
+ return NO_INIT;
+ }
+
+ mNotificationFramesAct = mNotificationFramesReq;
+ if (!AudioSystem::isLinearPCM(format)) {
+ if (sharedBuffer != 0) {
+ frameCount = sharedBuffer->size();
+ }
+ } else {
+ // Ensure that buffer depth covers at least audio hardware latency
+ uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+ if (minBufCount < 2) minBufCount = 2;
+
+ int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+ if (sharedBuffer == 0) {
+ if (frameCount == 0) {
+ frameCount = minFrameCount;
+ }
+ if (mNotificationFramesAct == 0) {
+ mNotificationFramesAct = frameCount/2;
+ }
+ // Make sure that application is notified with sufficient margin
+ // before underrun
+ if (mNotificationFramesAct > (uint32_t)frameCount/2) {
+ mNotificationFramesAct = frameCount/2;
+ }
+ if (frameCount < minFrameCount) {
+ if (enforceFrameCount) {
+ LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+ return BAD_VALUE;
+ } else {
+ frameCount = minFrameCount;
+ }
+ }
+ } else {
+ // Ensure that buffer alignment matches channelcount
+ if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+ LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+ return BAD_VALUE;
+ }
+ frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+ }
+ }
+
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
streamType,
sampleRate,
@@ -625,6 +731,7 @@ status_t AudioTrack::createTrack(
((uint16_t)flags) << 16,
sharedBuffer,
output,
+ &mSessionId,
&status);
if (track == 0) {
@@ -641,20 +748,22 @@ status_t AudioTrack::createTrack(
mCblkMemory.clear();
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
- mCblk->out = 1;
- // Update buffer size in case it has been limited by AudioFlinger during track creation
- mFrameCount = mCblk->frameCount;
+ mCblk->flags |= CBLK_DIRECTION_OUT;
if (sharedBuffer == 0) {
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
} else {
mCblk->buffers = sharedBuffer->pointer();
// Force buffer full condition as data is already present in shared memory
- mCblk->stepUser(mFrameCount);
+ mCblk->stepUser(mCblk->frameCount);
}
- mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
+ mCblk->volumeLR = (uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | uint16_t(mVolume[LEFT] * 0x1000);
+ mCblk->sendLevel = uint16_t(mSendLevel * 0x1000);
+ mAudioTrack->attachAuxEffect(mAuxEffectId);
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
+ mRemainingFrames = mNotificationFramesAct;
+ mLatency = afLatency + (1000*mCblk->frameCount) / sampleRate;
return NO_ERROR;
}
@@ -685,8 +794,15 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
cblk->lock.unlock();
return WOULD_BLOCK;
}
-
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+ if (!(cblk->flags & CBLK_INVALID_MSK)) {
+ result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
+ }
+ if (cblk->flags & CBLK_INVALID_MSK) {
+ LOGW("obtainBuffer() track %p invalidated, creating a new one", this);
+ // no need to clear the invalid flag as this cblk will not be used anymore
+ cblk->lock.unlock();
+ goto create_new_track;
+ }
if (__builtin_expect(result!=NO_ERROR, false)) {
cblk->waitTimeMs += waitTimeMs;
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
@@ -700,8 +816,9 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
result = mAudioTrack->start();
if (result == DEAD_OBJECT) {
LOGW("obtainBuffer() dead IAudioTrack: creating a new one");
+create_new_track:
result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount,
- mFrameCount, mFlags, mSharedBuffer, getOutput());
+ mFrameCount, mFlags, mSharedBuffer, getOutput(), false);
if (result == NO_ERROR) {
cblk = mCblk;
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
@@ -826,13 +943,13 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
// Manage underrun callback
if (mActive && (mCblk->framesReady() == 0)) {
- LOGV("Underrun user: %x, server: %x, flowControlFlag %d", mCblk->user, mCblk->server, mCblk->flowControlFlag);
- if (mCblk->flowControlFlag == 0) {
+ LOGV("Underrun user: %x, server: %x, flags %04x", mCblk->user, mCblk->server, mCblk->flags);
+ if ((mCblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
mCbf(EVENT_UNDERRUN, mUserData, 0);
if (mCblk->server == mCblk->frameCount) {
mCbf(EVENT_BUFFER_END, mUserData, 0);
}
- mCblk->flowControlFlag = 1;
+ mCblk->flags |= CBLK_UNDERRUN_ON;
if (mSharedBuffer != 0) return false;
}
}
@@ -932,7 +1049,7 @@ bool AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread)
while (frames);
if (frames == 0) {
- mRemainingFrames = mNotificationFrames;
+ mRemainingFrames = mNotificationFramesAct;
} else {
mRemainingFrames = frames;
}
@@ -949,7 +1066,7 @@ status_t AudioTrack::dump(int fd, const Vector<String16>& args) const
result.append(" AudioTrack::dump\n");
snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]);
result.append(buffer);
- snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount);
+ snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mCblk->frameCount);
result.append(buffer);
snprintf(buffer, 255, " sample rate(%d), status(%d), muted(%d)\n", (mCblk == 0) ? 0 : mCblk->sampleRate, mStatus, mMuted);
result.append(buffer);
@@ -986,7 +1103,7 @@ audio_track_cblk_t::audio_track_cblk_t()
: lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0),
userBase(0), serverBase(0), buffers(0), frameCount(0),
loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), volumeLR(0),
- flowControlFlag(1), forceReady(0)
+ flags(0), sendLevel(0)
{
}
@@ -996,7 +1113,7 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
u += frameCount;
// Ensure that user is never ahead of server for AudioRecord
- if (out) {
+ if (flags & CBLK_DIRECTION_MSK) {
// If stepServer() has been called once, switch to normal obtainBuffer() timeout period
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
@@ -1013,7 +1130,7 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount)
this->user = u;
// Clear flow control error condition as new data has been written/read to/from buffer.
- flowControlFlag = 0;
+ flags &= ~CBLK_UNDERRUN_MSK;
return u;
}
@@ -1038,7 +1155,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
uint32_t s = this->server;
s += frameCount;
- if (out) {
+ if (flags & CBLK_DIRECTION_MSK) {
// Mark that we have read the first buffer so that next time stepUser() is called
// we switch to normal obtainBuffer() timeout period
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
@@ -1089,7 +1206,7 @@ uint32_t audio_track_cblk_t::framesAvailable_l()
uint32_t u = this->user;
uint32_t s = this->server;
- if (out) {
+ if (flags & CBLK_DIRECTION_MSK) {
uint32_t limit = (s < loopStart) ? s : loopStart;
return limit + frameCount - u;
} else {
@@ -1102,7 +1219,7 @@ uint32_t audio_track_cblk_t::framesReady()
uint32_t u = this->user;
uint32_t s = this->server;
- if (out) {
+ if (flags & CBLK_DIRECTION_MSK) {
if (u < loopEnd) {
return u - s;
} else {
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 47bcc12..3a89e25 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -62,7 +62,15 @@ enum {
SET_STREAM_OUTPUT,
SET_VOICE_VOLUME,
GET_RENDER_POSITION,
- GET_INPUT_FRAMES_LOST
+ GET_INPUT_FRAMES_LOST,
+ NEW_AUDIO_SESSION_ID,
+ LOAD_EFFECT_LIBRARY,
+ UNLOAD_EFFECT_LIBRARY,
+ QUERY_NUM_EFFECTS,
+ QUERY_EFFECT,
+ GET_EFFECT_DESCRIPTOR,
+ CREATE_EFFECT,
+ MOVE_EFFECTS
};
class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -83,6 +91,7 @@ public:
uint32_t flags,
const sp<IMemory>& sharedBuffer,
int output,
+ int *sessionId,
status_t *status)
{
Parcel data, reply;
@@ -97,10 +106,19 @@ public:
data.writeInt32(flags);
data.writeStrongBinder(sharedBuffer->asBinder());
data.writeInt32(output);
+ int lSessionId = 0;
+ if (sessionId != NULL) {
+ lSessionId = *sessionId;
+ }
+ data.writeInt32(lSessionId);
status_t lStatus = remote()->transact(CREATE_TRACK, data, &reply);
if (lStatus != NO_ERROR) {
LOGE("createTrack error: %s", strerror(-lStatus));
} else {
+ lSessionId = reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
lStatus = reply.readInt32();
track = interface_cast<IAudioTrack>(reply.readStrongBinder());
}
@@ -118,6 +136,7 @@ public:
int channelCount,
int frameCount,
uint32_t flags,
+ int *sessionId,
status_t *status)
{
Parcel data, reply;
@@ -130,10 +149,19 @@ public:
data.writeInt32(channelCount);
data.writeInt32(frameCount);
data.writeInt32(flags);
+ int lSessionId = 0;
+ if (sessionId != NULL) {
+ lSessionId = *sessionId;
+ }
+ data.writeInt32(lSessionId);
status_t lStatus = remote()->transact(OPEN_RECORD, data, &reply);
if (lStatus != NO_ERROR) {
LOGE("openRecord error: %s", strerror(-lStatus));
} else {
+ lSessionId = reply.readInt32();
+ if (sessionId != NULL) {
+ *sessionId = lSessionId;
+ }
lStatus = reply.readInt32();
record = interface_cast<IAudioRecord>(reply.readStrongBinder());
}
@@ -497,6 +525,169 @@ public:
remote()->transact(GET_INPUT_FRAMES_LOST, data, &reply);
return reply.readInt32();
}
+
+ virtual int newAudioSessionId()
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply);
+ int id = 0;
+ if (status == NO_ERROR) {
+ id = reply.readInt32();
+ }
+ return id;
+ }
+
+ virtual status_t loadEffectLibrary(const char *libPath, int *handle)
+ {
+ if (libPath == NULL || handle == NULL) {
+ return BAD_VALUE;
+ }
+ *handle = 0;
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeCString(libPath);
+ status_t status = remote()->transact(LOAD_EFFECT_LIBRARY, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ if (status == NO_ERROR) {
+ *handle = reply.readInt32();
+ }
+ }
+ return status;
+ }
+
+ virtual status_t unloadEffectLibrary(int handle)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(handle);
+ status_t status = remote()->transact(UNLOAD_EFFECT_LIBRARY, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ }
+ return status;
+ }
+
+ virtual status_t queryNumberEffects(uint32_t *numEffects)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ status_t status = remote()->transact(QUERY_NUM_EFFECTS, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (numEffects) {
+ *numEffects = (uint32_t)reply.readInt32();
+ }
+ return NO_ERROR;
+ }
+
+ virtual status_t queryEffect(uint32_t index, effect_descriptor_t *pDescriptor)
+ {
+ if (pDescriptor == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(index);
+ status_t status = remote()->transact(QUERY_EFFECT, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ reply.read(pDescriptor, sizeof(effect_descriptor_t));
+ return NO_ERROR;
+ }
+
+ virtual status_t getEffectDescriptor(effect_uuid_t *pUuid, effect_descriptor_t *pDescriptor)
+ {
+ if (pUuid == NULL || pDescriptor == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.write(pUuid, sizeof(effect_uuid_t));
+ status_t status = remote()->transact(GET_EFFECT_DESCRIPTOR, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = reply.readInt32();
+ if (status != NO_ERROR) {
+ return status;
+ }
+ reply.read(pDescriptor, sizeof(effect_descriptor_t));
+ return NO_ERROR;
+ }
+
+ virtual sp<IEffect> createEffect(pid_t pid,
+ effect_descriptor_t *pDesc,
+ const sp<IEffectClient>& client,
+ int32_t priority,
+ int output,
+ int sessionId,
+ status_t *status,
+ int *id,
+ int *enabled)
+ {
+ Parcel data, reply;
+ sp<IEffect> effect;
+
+ if (pDesc == NULL) {
+ return effect;
+ if (status) {
+ *status = BAD_VALUE;
+ }
+ }
+
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ data.write(pDesc, sizeof(effect_descriptor_t));
+ data.writeStrongBinder(client->asBinder());
+ data.writeInt32(priority);
+ data.writeInt32(output);
+ data.writeInt32(sessionId);
+
+ status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply);
+ if (lStatus != NO_ERROR) {
+ LOGE("createEffect error: %s", strerror(-lStatus));
+ } else {
+ lStatus = reply.readInt32();
+ int tmp = reply.readInt32();
+ if (id) {
+ *id = tmp;
+ }
+ tmp = reply.readInt32();
+ if (enabled) {
+ *enabled = tmp;
+ }
+ effect = interface_cast<IEffect>(reply.readStrongBinder());
+ reply.read(pDesc, sizeof(effect_descriptor_t));
+ }
+ if (status) {
+ *status = lStatus;
+ }
+
+ return effect;
+ }
+
+ virtual status_t moveEffects(int session, int srcOutput, int dstOutput)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(session);
+ data.writeInt32(srcOutput);
+ data.writeInt32(dstOutput);
+ remote()->transact(MOVE_EFFECTS, data, &reply);
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -518,10 +709,12 @@ status_t BnAudioFlinger::onTransact(
uint32_t flags = data.readInt32();
sp<IMemory> buffer = interface_cast<IMemory>(data.readStrongBinder());
int output = data.readInt32();
+ int sessionId = data.readInt32();
status_t status;
sp<IAudioTrack> track = createTrack(pid,
streamType, sampleRate, format,
- channelCount, bufferCount, flags, buffer, output, &status);
+ channelCount, bufferCount, flags, buffer, output, &sessionId, &status);
+ reply->writeInt32(sessionId);
reply->writeInt32(status);
reply->writeStrongBinder(track->asBinder());
return NO_ERROR;
@@ -535,9 +728,11 @@ status_t BnAudioFlinger::onTransact(
int channelCount = data.readInt32();
size_t bufferCount = data.readInt32();
uint32_t flags = data.readInt32();
+ int sessionId = data.readInt32();
status_t status;
sp<IAudioRecord> record = openRecord(pid, input,
- sampleRate, format, channelCount, bufferCount, flags, &status);
+ sampleRate, format, channelCount, bufferCount, flags, &sessionId, &status);
+ reply->writeInt32(sessionId);
reply->writeInt32(status);
reply->writeStrongBinder(record->asBinder());
return NO_ERROR;
@@ -768,7 +963,87 @@ status_t BnAudioFlinger::onTransact(
reply->writeInt32(getInputFramesLost(ioHandle));
return NO_ERROR;
} break;
+ case NEW_AUDIO_SESSION_ID: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(newAudioSessionId());
+ return NO_ERROR;
+ } break;
+ case LOAD_EFFECT_LIBRARY: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int handle;
+ status_t status = loadEffectLibrary(data.readCString(), &handle);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32(handle);
+ }
+ return NO_ERROR;
+ }
+ case UNLOAD_EFFECT_LIBRARY: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ reply->writeInt32(unloadEffectLibrary(data.readInt32()));
+ return NO_ERROR;
+ }
+ case QUERY_NUM_EFFECTS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ uint32_t numEffects;
+ status_t status = queryNumberEffects(&numEffects);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->writeInt32((int32_t)numEffects);
+ }
+ return NO_ERROR;
+ }
+ case QUERY_EFFECT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ effect_descriptor_t desc;
+ status_t status = queryEffect(data.readInt32(), &desc);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->write(&desc, sizeof(effect_descriptor_t));
+ }
+ return NO_ERROR;
+ }
+ case GET_EFFECT_DESCRIPTOR: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ effect_uuid_t uuid;
+ data.read(&uuid, sizeof(effect_uuid_t));
+ effect_descriptor_t desc;
+ status_t status = getEffectDescriptor(&uuid, &desc);
+ reply->writeInt32(status);
+ if (status == NO_ERROR) {
+ reply->write(&desc, sizeof(effect_descriptor_t));
+ }
+ return NO_ERROR;
+ }
+ case CREATE_EFFECT: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ pid_t pid = data.readInt32();
+ effect_descriptor_t desc;
+ data.read(&desc, sizeof(effect_descriptor_t));
+ sp<IEffectClient> client = interface_cast<IEffectClient>(data.readStrongBinder());
+ int32_t priority = data.readInt32();
+ int output = data.readInt32();
+ int sessionId = data.readInt32();
+ status_t status;
+ int id;
+ int enabled;
+ sp<IEffect> effect = createEffect(pid, &desc, client, priority, output, sessionId, &status, &id, &enabled);
+ reply->writeInt32(status);
+ reply->writeInt32(id);
+ reply->writeInt32(enabled);
+ reply->writeStrongBinder(effect->asBinder());
+ reply->write(&desc, sizeof(effect_descriptor_t));
+ return NO_ERROR;
+ } break;
+ case MOVE_EFFECTS: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int session = data.readInt32();
+ int srcOutput = data.readInt32();
+ int dstOutput = data.readInt32();
+ reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 18dd173..950c213 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -44,7 +44,11 @@ enum {
RELEASE_INPUT,
INIT_STREAM_VOLUME,
SET_STREAM_VOLUME,
- GET_STREAM_VOLUME
+ GET_STREAM_VOLUME,
+ GET_STRATEGY_FOR_STREAM,
+ GET_OUTPUT_FOR_EFFECT,
+ REGISTER_EFFECT,
+ UNREGISTER_EFFECT
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -137,22 +141,28 @@ public:
return static_cast <audio_io_handle_t> (reply.readInt32());
}
- virtual status_t startOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+ virtual status_t startOutput(audio_io_handle_t output,
+ AudioSystem::stream_type stream,
+ int session)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(output);
data.writeInt32(stream);
+ data.writeInt32(session);
remote()->transact(START_OUTPUT, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
- virtual status_t stopOutput(audio_io_handle_t output, AudioSystem::stream_type stream)
+ virtual status_t stopOutput(audio_io_handle_t output,
+ AudioSystem::stream_type stream,
+ int session)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(output);
data.writeInt32(stream);
+ data.writeInt32(session);
remote()->transact(STOP_OUTPUT, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
@@ -242,6 +252,51 @@ public:
if (index) *index = lIndex;
return static_cast <status_t> (reply.readInt32());
}
+
+ virtual uint32_t getStrategyForStream(AudioSystem::stream_type stream)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(static_cast <uint32_t>(stream));
+ remote()->transact(GET_STRATEGY_FOR_STREAM, data, &reply);
+ return reply.readInt32();
+ }
+
+ virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(desc, sizeof(effect_descriptor_t));
+ remote()->transact(GET_OUTPUT_FOR_EFFECT, data, &reply);
+ return static_cast <audio_io_handle_t> (reply.readInt32());
+ }
+
+ virtual status_t registerEffect(effect_descriptor_t *desc,
+ audio_io_handle_t output,
+ uint32_t strategy,
+ int session,
+ int id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.write(desc, sizeof(effect_descriptor_t));
+ data.writeInt32(output);
+ data.writeInt32(strategy);
+ data.writeInt32(session);
+ data.writeInt32(id);
+ remote()->transact(REGISTER_EFFECT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
+ virtual status_t unregisterEffect(int id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(id);
+ remote()->transact(UNREGISTER_EFFECT, data, &reply);
+ return static_cast <status_t> (reply.readInt32());
+ }
+
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -255,18 +310,24 @@ status_t BnAudioPolicyService::onTransact(
switch(code) {
case SET_DEVICE_CONNECTION_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
- AudioSystem::device_connection_state state = static_cast <AudioSystem::device_connection_state>(data.readInt32());
+ AudioSystem::audio_devices device =
+ static_cast <AudioSystem::audio_devices>(data.readInt32());
+ AudioSystem::device_connection_state state =
+ static_cast <AudioSystem::device_connection_state>(data.readInt32());
const char *device_address = data.readCString();
- reply->writeInt32(static_cast <uint32_t>(setDeviceConnectionState(device, state, device_address)));
+ reply->writeInt32(static_cast<uint32_t> (setDeviceConnectionState(device,
+ state,
+ device_address)));
return NO_ERROR;
} break;
case GET_DEVICE_CONNECTION_STATE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::audio_devices device = static_cast <AudioSystem::audio_devices>(data.readInt32());
+ AudioSystem::audio_devices device =
+ static_cast<AudioSystem::audio_devices> (data.readInt32());
const char *device_address = data.readCString();
- reply->writeInt32(static_cast <uint32_t>(getDeviceConnectionState(device, device_address)));
+ reply->writeInt32(static_cast<uint32_t> (getDeviceConnectionState(device,
+ device_address)));
return NO_ERROR;
} break;
@@ -287,7 +348,8 @@ status_t BnAudioPolicyService::onTransact(
case SET_FORCE_USE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
AudioSystem::force_use usage = static_cast <AudioSystem::force_use>(data.readInt32());
- AudioSystem::forced_config config = static_cast <AudioSystem::forced_config>(data.readInt32());
+ AudioSystem::forced_config config =
+ static_cast <AudioSystem::forced_config>(data.readInt32());
reply->writeInt32(static_cast <uint32_t>(setForceUse(usage, config)));
return NO_ERROR;
} break;
@@ -301,11 +363,13 @@ status_t BnAudioPolicyService::onTransact(
case GET_OUTPUT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ AudioSystem::stream_type stream =
+ static_cast <AudioSystem::stream_type>(data.readInt32());
uint32_t samplingRate = data.readInt32();
uint32_t format = data.readInt32();
uint32_t channels = data.readInt32();
- AudioSystem::output_flags flags = static_cast <AudioSystem::output_flags>(data.readInt32());
+ AudioSystem::output_flags flags =
+ static_cast <AudioSystem::output_flags>(data.readInt32());
audio_io_handle_t output = getOutput(stream,
samplingRate,
@@ -320,7 +384,10 @@ status_t BnAudioPolicyService::onTransact(
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
uint32_t stream = data.readInt32();
- reply->writeInt32(static_cast <uint32_t>(startOutput(output, (AudioSystem::stream_type)stream)));
+ int session = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(startOutput(output,
+ (AudioSystem::stream_type)stream,
+ session)));
return NO_ERROR;
} break;
@@ -328,7 +395,10 @@ status_t BnAudioPolicyService::onTransact(
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_io_handle_t output = static_cast <audio_io_handle_t>(data.readInt32());
uint32_t stream = data.readInt32();
- reply->writeInt32(static_cast <uint32_t>(stopOutput(output, (AudioSystem::stream_type)stream)));
+ int session = data.readInt32();
+ reply->writeInt32(static_cast <uint32_t>(stopOutput(output,
+ (AudioSystem::stream_type)stream,
+ session)));
return NO_ERROR;
} break;
@@ -345,7 +415,8 @@ status_t BnAudioPolicyService::onTransact(
uint32_t samplingRate = data.readInt32();
uint32_t format = data.readInt32();
uint32_t channels = data.readInt32();
- AudioSystem::audio_in_acoustics acoustics = static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
+ AudioSystem::audio_in_acoustics acoustics =
+ static_cast <AudioSystem::audio_in_acoustics>(data.readInt32());
audio_io_handle_t input = getInput(inputSource,
samplingRate,
format,
@@ -378,7 +449,8 @@ status_t BnAudioPolicyService::onTransact(
case INIT_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ AudioSystem::stream_type stream =
+ static_cast <AudioSystem::stream_type>(data.readInt32());
int indexMin = data.readInt32();
int indexMax = data.readInt32();
reply->writeInt32(static_cast <uint32_t>(initStreamVolume(stream, indexMin,indexMax)));
@@ -387,7 +459,8 @@ status_t BnAudioPolicyService::onTransact(
case SET_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ AudioSystem::stream_type stream =
+ static_cast <AudioSystem::stream_type>(data.readInt32());
int index = data.readInt32();
reply->writeInt32(static_cast <uint32_t>(setStreamVolumeIndex(stream, index)));
return NO_ERROR;
@@ -395,7 +468,8 @@ status_t BnAudioPolicyService::onTransact(
case GET_STREAM_VOLUME: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
- AudioSystem::stream_type stream = static_cast <AudioSystem::stream_type>(data.readInt32());
+ AudioSystem::stream_type stream =
+ static_cast <AudioSystem::stream_type>(data.readInt32());
int index;
status_t status = getStreamVolumeIndex(stream, &index);
reply->writeInt32(index);
@@ -403,6 +477,46 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
} break;
+ case GET_STRATEGY_FOR_STREAM: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ AudioSystem::stream_type stream =
+ static_cast <AudioSystem::stream_type>(data.readInt32());
+ reply->writeInt32(getStrategyForStream(stream));
+ return NO_ERROR;
+ } break;
+
+ case GET_OUTPUT_FOR_EFFECT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ effect_descriptor_t desc;
+ data.read(&desc, sizeof(effect_descriptor_t));
+ audio_io_handle_t output = getOutputForEffect(&desc);
+ reply->writeInt32(static_cast <int>(output));
+ return NO_ERROR;
+ } break;
+
+ case REGISTER_EFFECT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ effect_descriptor_t desc;
+ data.read(&desc, sizeof(effect_descriptor_t));
+ audio_io_handle_t output = data.readInt32();
+ uint32_t strategy = data.readInt32();
+ int session = data.readInt32();
+ int id = data.readInt32();
+ reply->writeInt32(static_cast <int32_t>(registerEffect(&desc,
+ output,
+ strategy,
+ session,
+ id)));
+ return NO_ERROR;
+ } break;
+
+ case UNREGISTER_EFFECT: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int id = data.readInt32();
+ reply->writeInt32(static_cast <int32_t>(unregisterEffect(id)));
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 01ffd75..bc8ff34 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -34,7 +34,8 @@ enum {
STOP,
FLUSH,
MUTE,
- PAUSE
+ PAUSE,
+ ATTACH_AUX_EFFECT
};
class BpAudioTrack : public BpInterface<IAudioTrack>
@@ -97,7 +98,21 @@ public:
cblk = interface_cast<IMemory>(reply.readStrongBinder());
}
return cblk;
- }
+ }
+
+ virtual status_t attachAuxEffect(int effectId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
+ data.writeInt32(effectId);
+ status_t status = remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
+ if (status == NO_ERROR) {
+ status = reply.readInt32();
+ } else {
+ LOGW("attachAuxEffect() error: %s", strerror(-status));
+ }
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioTrack, "android.media.IAudioTrack");
@@ -138,6 +153,11 @@ status_t BnAudioTrack::onTransact(
pause();
return NO_ERROR;
}
+ case ATTACH_AUX_EFFECT: {
+ CHECK_INTERFACE(IAudioTrack, data, reply);
+ reply->writeInt32(attachAuxEffect(data.readInt32()));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IEffect.cpp b/media/libmedia/IEffect.cpp
new file mode 100644
index 0000000..a945b97
--- /dev/null
+++ b/media/libmedia/IEffect.cpp
@@ -0,0 +1,195 @@
+/*
+**
+** Copyright 2010, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IEffect"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <binder/Parcel.h>
+#include <media/IEffect.h>
+
+namespace android {
+
+enum {
+ ENABLE = IBinder::FIRST_CALL_TRANSACTION,
+ DISABLE,
+ COMMAND,
+ DISCONNECT,
+ GET_CBLK
+};
+
+class BpEffect: public BpInterface<IEffect>
+{
+public:
+ BpEffect(const sp<IBinder>& impl)
+ : BpInterface<IEffect>(impl)
+ {
+ }
+
+ status_t enable()
+ {
+ LOGV("enable");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+ remote()->transact(ENABLE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t disable()
+ {
+ LOGV("disable");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+ remote()->transact(DISABLE, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t command(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t *pReplySize,
+ void *pReplyData)
+ {
+ LOGV("command");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+ data.writeInt32(cmdCode);
+ int size = cmdSize;
+ if (pCmdData == NULL) {
+ size = 0;
+ }
+ data.writeInt32(size);
+ if (size) {
+ data.write(pCmdData, size);
+ }
+ if (pReplySize == NULL) {
+ size = 0;
+ } else {
+ size = *pReplySize;
+ }
+ data.writeInt32(size);
+ remote()->transact(COMMAND, data, &reply);
+ status_t status = reply.readInt32();
+ size = reply.readInt32();
+ if (size != 0 && pReplyData != NULL && pReplySize != NULL) {
+ reply.read(pReplyData, size);
+ *pReplySize = size;
+ }
+ return status;
+ }
+
+ void disconnect()
+ {
+ LOGV("disconnect");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+ remote()->transact(DISCONNECT, data, &reply);
+ return;
+ }
+
+ virtual sp<IMemory> getCblk() const
+ {
+ Parcel data, reply;
+ sp<IMemory> cblk;
+ data.writeInterfaceToken(IEffect::getInterfaceDescriptor());
+ status_t status = remote()->transact(GET_CBLK, data, &reply);
+ if (status == NO_ERROR) {
+ cblk = interface_cast<IMemory>(reply.readStrongBinder());
+ }
+ return cblk;
+ }
+ };
+
+IMPLEMENT_META_INTERFACE(Effect, "android.media.IEffect");
+
+// ----------------------------------------------------------------------
+
+status_t BnEffect::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case ENABLE: {
+ LOGV("ENABLE");
+ CHECK_INTERFACE(IEffect, data, reply);
+ reply->writeInt32(enable());
+ return NO_ERROR;
+ } break;
+
+ case DISABLE: {
+ LOGV("DISABLE");
+ CHECK_INTERFACE(IEffect, data, reply);
+ reply->writeInt32(disable());
+ return NO_ERROR;
+ } break;
+
+ case COMMAND: {
+ LOGV("COMMAND");
+ CHECK_INTERFACE(IEffect, data, reply);
+ uint32_t cmdCode = data.readInt32();
+ uint32_t cmdSize = data.readInt32();
+ char *cmd = NULL;
+ if (cmdSize) {
+ cmd = (char *)malloc(cmdSize);
+ data.read(cmd, cmdSize);
+ }
+ uint32_t replySize = data.readInt32();
+ uint32_t replySz = replySize;
+ char *resp = NULL;
+ if (replySize) {
+ resp = (char *)malloc(replySize);
+ }
+ status_t status = command(cmdCode, cmdSize, cmd, &replySz, resp);
+ reply->writeInt32(status);
+ if (replySz < replySize) {
+ replySize = replySz;
+ }
+ reply->writeInt32(replySize);
+ if (replySize) {
+ reply->write(resp, replySize);
+ }
+ if (cmd) {
+ free(cmd);
+ }
+ if (resp) {
+ free(resp);
+ }
+ return NO_ERROR;
+ } break;
+
+ case DISCONNECT: {
+ LOGV("DISCONNECT");
+ CHECK_INTERFACE(IEffect, data, reply);
+ disconnect();
+ return NO_ERROR;
+ } break;
+
+ case GET_CBLK: {
+ CHECK_INTERFACE(IEffect, data, reply);
+ reply->writeStrongBinder(getCblk()->asBinder());
+ return NO_ERROR;
+ } break;
+
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IEffectClient.cpp b/media/libmedia/IEffectClient.cpp
new file mode 100644
index 0000000..1fa9cbe
--- /dev/null
+++ b/media/libmedia/IEffectClient.cpp
@@ -0,0 +1,145 @@
+/*
+**
+** Copyright 2010, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "IEffectClient"
+#include <utils/Log.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <media/IEffectClient.h>
+
+namespace android {
+
+enum {
+ CONTROL_STATUS_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
+ ENABLE_STATUS_CHANGED,
+ COMMAND_EXECUTED
+};
+
+class BpEffectClient: public BpInterface<IEffectClient>
+{
+public:
+ BpEffectClient(const sp<IBinder>& impl)
+ : BpInterface<IEffectClient>(impl)
+ {
+ }
+
+ void controlStatusChanged(bool controlGranted)
+ {
+ LOGV("controlStatusChanged");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+ data.writeInt32((uint32_t)controlGranted);
+ remote()->transact(CONTROL_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ void enableStatusChanged(bool enabled)
+ {
+ LOGV("enableStatusChanged");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+ data.writeInt32((uint32_t)enabled);
+ remote()->transact(ENABLE_STATUS_CHANGED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+ void commandExecuted(uint32_t cmdCode,
+ uint32_t cmdSize,
+ void *pCmdData,
+ uint32_t replySize,
+ void *pReplyData)
+ {
+ LOGV("commandExecuted");
+ Parcel data, reply;
+ data.writeInterfaceToken(IEffectClient::getInterfaceDescriptor());
+ data.writeInt32(cmdCode);
+ int size = cmdSize;
+ if (pCmdData == NULL) {
+ size = 0;
+ }
+ data.writeInt32(size);
+ if (size) {
+ data.write(pCmdData, size);
+ }
+ size = replySize;
+ if (pReplyData == NULL) {
+ size = 0;
+ }
+ data.writeInt32(size);
+ if (size) {
+ data.write(pReplyData, size);
+ }
+ remote()->transact(COMMAND_EXECUTED, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+
+};
+
+IMPLEMENT_META_INTERFACE(EffectClient, "android.media.IEffectClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnEffectClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case CONTROL_STATUS_CHANGED: {
+ LOGV("CONTROL_STATUS_CHANGED");
+ CHECK_INTERFACE(IEffectClient, data, reply);
+ bool hasControl = (bool)data.readInt32();
+ controlStatusChanged(hasControl);
+ return NO_ERROR;
+ } break;
+ case ENABLE_STATUS_CHANGED: {
+ LOGV("ENABLE_STATUS_CHANGED");
+ CHECK_INTERFACE(IEffectClient, data, reply);
+ bool enabled = (bool)data.readInt32();
+ enableStatusChanged(enabled);
+ return NO_ERROR;
+ } break;
+ case COMMAND_EXECUTED: {
+ LOGV("COMMAND_EXECUTED");
+ CHECK_INTERFACE(IEffectClient, data, reply);
+ uint32_t cmdCode = data.readInt32();
+ uint32_t cmdSize = data.readInt32();
+ char *cmd = NULL;
+ if (cmdSize) {
+ cmd = (char *)malloc(cmdSize);
+ data.read(cmd, cmdSize);
+ }
+ uint32_t replySize = data.readInt32();
+ char *resp = NULL;
+ if (replySize) {
+ resp = (char *)malloc(replySize);
+ data.read(resp, replySize);
+ }
+ commandExecuted(cmdCode, cmdSize, cmd, replySize, resp);
+ if (cmd) {
+ free(cmd);
+ }
+ if (resp) {
+ free(resp);
+ }
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index ed792b3..0f55b19 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -45,6 +45,8 @@ enum {
GET_METADATA,
SUSPEND,
RESUME,
+ SET_AUX_EFFECT_SEND_LEVEL,
+ ATTACH_AUX_EFFECT
};
class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -221,6 +223,24 @@ public:
return reply.readInt32();
}
+
+ status_t setAuxEffectSendLevel(float level)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeFloat(level);
+ remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply);
+ return reply.readInt32();
+ }
+
+ status_t attachAuxEffect(int effectId)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ data.writeInt32(effectId);
+ remote()->transact(ATTACH_AUX_EFFECT, data, &reply);
+ return reply.readInt32();
+ }
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -339,6 +359,16 @@ status_t BnMediaPlayer::onTransact(
reply->setDataPosition(0);
return NO_ERROR;
} break;
+ case SET_AUX_EFFECT_SEND_LEVEL: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(setAuxEffectSendLevel(data.readFloat()));
+ return NO_ERROR;
+ } break;
+ case ATTACH_AUX_EFFECT: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+ reply->writeInt32(attachAuxEffect(data.readInt32()));
+ return NO_ERROR;
+ } break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index 71c5f86..4abfa75 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -35,8 +35,7 @@ enum {
DECODE_FD,
CREATE_MEDIA_RECORDER,
CREATE_METADATA_RETRIEVER,
- GET_OMX,
- SNOOP
+ GET_OMX
};
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
@@ -58,7 +57,7 @@ public:
virtual sp<IMediaPlayer> create(
pid_t pid, const sp<IMediaPlayerClient>& client,
- const char* url, const KeyedVector<String8, String8> *headers) {
+ const char* url, const KeyedVector<String8, String8> *headers, int audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeInt32(pid);
@@ -75,8 +74,10 @@ public:
data.writeString8(headers->valueAt(i));
}
}
+ data.writeInt32(audioSessionId);
remote()->transact(CREATE_URL, data, &reply);
+
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}
@@ -89,7 +90,8 @@ public:
return interface_cast<IMediaRecorder>(reply.readStrongBinder());
}
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length)
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd,
+ int64_t offset, int64_t length, int audioSessionId)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -98,8 +100,11 @@ public:
data.writeFileDescriptor(fd);
data.writeInt64(offset);
data.writeInt64(length);
+ data.writeInt32(audioSessionId);
+
remote()->transact(CREATE_FD, data, &reply);
- return interface_cast<IMediaPlayer>(reply.readStrongBinder());
+
+ return interface_cast<IMediaPlayer>(reply.readStrongBinder());;
}
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
@@ -128,14 +133,6 @@ public:
return interface_cast<IMemory>(reply.readStrongBinder());
}
- virtual sp<IMemory> snoop()
- {
- Parcel data, reply;
- data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
- remote()->transact(SNOOP, data, &reply);
- return interface_cast<IMemory>(reply.readStrongBinder());
- }
-
virtual sp<IOMX> getOMX() {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
@@ -166,9 +163,10 @@ status_t BnMediaPlayerService::onTransact(
String8 value = data.readString8();
headers.add(key, value);
}
+ int audioSessionId = data.readInt32();
sp<IMediaPlayer> player = create(
- pid, client, url, numHeaders > 0 ? &headers : NULL);
+ pid, client, url, numHeaders > 0 ? &headers : NULL, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
@@ -180,7 +178,9 @@ status_t BnMediaPlayerService::onTransact(
int fd = dup(data.readFileDescriptor());
int64_t offset = data.readInt64();
int64_t length = data.readInt64();
- sp<IMediaPlayer> player = create(pid, client, fd, offset, length);
+ int audioSessionId = data.readInt32();
+
+ sp<IMediaPlayer> player = create(pid, client, fd, offset, length, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
@@ -212,12 +212,6 @@ status_t BnMediaPlayerService::onTransact(
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
- case SNOOP: {
- CHECK_INTERFACE(IMediaPlayerService, data, reply);
- sp<IMemory> snooped_audio = snoop();
- reply->writeStrongBinder(snooped_audio->asBinder());
- return NO_ERROR;
- } break;
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
pid_t pid = data.readInt32();
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 1de9f9b..4eb63e8 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -21,7 +21,7 @@
#include <binder/Parcel.h>
#include <surfaceflinger/ISurface.h>
#include <camera/ICamera.h>
-#include <media/IMediaPlayerClient.h>
+#include <media/IMediaRecorderClient.h>
#include <media/IMediaRecorder.h>
namespace android {
@@ -189,7 +189,7 @@ public:
return reply.readInt32();
}
- status_t setListener(const sp<IMediaPlayerClient>& listener)
+ status_t setListener(const sp<IMediaRecorderClient>& listener)
{
LOGV("setListener(%p)", listener.get());
Parcel data, reply;
@@ -399,8 +399,8 @@ status_t BnMediaRecorder::onTransact(
case SET_LISTENER: {
LOGV("SET_LISTENER");
CHECK_INTERFACE(IMediaRecorder, data, reply);
- sp<IMediaPlayerClient> listener =
- interface_cast<IMediaPlayerClient>(data.readStrongBinder());
+ sp<IMediaRecorderClient> listener =
+ interface_cast<IMediaRecorderClient>(data.readStrongBinder());
reply->writeInt32(setListener(listener));
return NO_ERROR;
} break;
diff --git a/media/libmedia/IMediaRecorderClient.cpp b/media/libmedia/IMediaRecorderClient.cpp
new file mode 100644
index 0000000..ff235c9
--- /dev/null
+++ b/media/libmedia/IMediaRecorderClient.cpp
@@ -0,0 +1,70 @@
+/*
+**
+** Copyright 2010, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <utils/RefBase.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+
+#include <media/IMediaRecorderClient.h>
+
+namespace android {
+
+enum {
+ NOTIFY = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+class BpMediaRecorderClient: public BpInterface<IMediaRecorderClient>
+{
+public:
+ BpMediaRecorderClient(const sp<IBinder>& impl)
+ : BpInterface<IMediaRecorderClient>(impl)
+ {
+ }
+
+ virtual void notify(int msg, int ext1, int ext2)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IMediaRecorderClient::getInterfaceDescriptor());
+ data.writeInt32(msg);
+ data.writeInt32(ext1);
+ data.writeInt32(ext2);
+ remote()->transact(NOTIFY, data, &reply, IBinder::FLAG_ONEWAY);
+ }
+};
+
+IMPLEMENT_META_INTERFACE(MediaRecorderClient, "android.media.IMediaRecorderClient");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaRecorderClient::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch(code) {
+ case NOTIFY: {
+ CHECK_INTERFACE(IMediaRecorderClient, data, reply);
+ int msg = data.readInt32();
+ int ext1 = data.readInt32();
+ int ext2 = data.readInt32();
+ notify(msg, ext1, ext2);
+ return NO_ERROR;
+ } break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+}; // namespace android
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 01b6737..f3804b8 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -57,7 +57,7 @@ sp<IOMXRenderer> IOMX::createRendererFromJavaSurface(
return NULL;
}
- jfieldID surfaceID = env->GetFieldID(surfaceClass, "mSurface", "I");
+ jfieldID surfaceID = env->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
if (surfaceID == NULL) {
LOGE("Can't find Surface.mSurface");
return NULL;
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 1263373..3869389 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -272,7 +272,7 @@ MediaProfiles::createEncoderOutputFileFormat(const char **atts)
}
/*static*/ MediaProfiles::CamcorderProfile*
-MediaProfiles::createCamcorderProfile(const char **atts)
+MediaProfiles::createCamcorderProfile(int cameraId, const char **atts)
{
CHECK(!strcmp("quality", atts[0]) &&
!strcmp("fileFormat", atts[2]) &&
@@ -287,16 +287,47 @@ MediaProfiles::createCamcorderProfile(const char **atts)
CHECK(fileFormat != -1);
MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = cameraId;
profile->mFileFormat = static_cast<output_format>(fileFormat);
profile->mQuality = static_cast<camcorder_quality>(quality);
profile->mDuration = atoi(atts[5]);
return profile;
}
-/*static*/ int
-MediaProfiles::getImageEncodingQualityLevel(const char** atts)
+MediaProfiles::ImageEncodingQualityLevels*
+MediaProfiles::findImageEncodingQualityLevels(int cameraId) const
+{
+ int n = mImageEncodingQualityLevels.size();
+ for (int i = 0; i < n; i++) {
+ ImageEncodingQualityLevels *levels = mImageEncodingQualityLevels[i];
+ if (levels->mCameraId == cameraId) {
+ return levels;
+ }
+ }
+ return NULL;
+}
+
+void MediaProfiles::addImageEncodingQualityLevel(int cameraId, const char** atts)
{
CHECK(!strcmp("quality", atts[0]));
+ int quality = atoi(atts[1]);
+ LOGV("%s: cameraId=%d, quality=%d\n", __func__, cameraId, quality);
+ ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+
+ if (levels == NULL) {
+ levels = new ImageEncodingQualityLevels();
+ levels->mCameraId = cameraId;
+ mImageEncodingQualityLevels.add(levels);
+ }
+
+ levels->mLevels.add(quality);
+}
+
+/*static*/ int
+MediaProfiles::getCameraId(const char** atts)
+{
+ if (!atts[0]) return 0; // default cameraId = 0
+ CHECK(!strcmp("cameraId", atts[0]));
return atoi(atts[1]);
}
@@ -322,10 +353,13 @@ MediaProfiles::startElementHandler(void *userData, const char *name, const char
profiles->mAudioDecoders.add(createAudioDecoderCap(atts));
} else if (strcmp("EncoderOutputFileFormat", name) == 0) {
profiles->mEncoderOutputFileFormats.add(createEncoderOutputFileFormat(atts));
+ } else if (strcmp("CamcorderProfiles", name) == 0) {
+ profiles->mCurrentCameraId = getCameraId(atts);
} else if (strcmp("EncoderProfile", name) == 0) {
- profiles->mCamcorderProfiles.add(createCamcorderProfile(atts));
+ profiles->mCamcorderProfiles.add(
+ createCamcorderProfile(profiles->mCurrentCameraId, atts));
} else if (strcmp("ImageEncoding", name) == 0) {
- profiles->mImageEncodingQualityLevels.add(getImageEncodingQualityLevel(atts));
+ profiles->addImageEncodingQualityLevel(profiles->mCurrentCameraId, atts);
}
}
@@ -383,7 +417,8 @@ MediaProfiles::createDefaultCamcorderHighProfile()
new MediaProfiles::VideoCodec(VIDEO_ENCODER_H263, 360000, 352, 288, 20);
AudioCodec *audioCodec = new AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
- CamcorderProfile *profile = new CamcorderProfile;
+ CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = 0;
profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
profile->mQuality = CAMCORDER_QUALITY_HIGH;
profile->mDuration = 60;
@@ -402,6 +437,7 @@ MediaProfiles::createDefaultCamcorderLowProfile()
new MediaProfiles::AudioCodec(AUDIO_ENCODER_AMR_NB, 12200, 8000, 1);
MediaProfiles::CamcorderProfile *profile = new MediaProfiles::CamcorderProfile;
+ profile->mCameraId = 0;
profile->mFileFormat = OUTPUT_FORMAT_THREE_GPP;
profile->mQuality = CAMCORDER_QUALITY_LOW;
profile->mDuration = 30;
@@ -458,9 +494,12 @@ MediaProfiles::createDefaultAmrNBEncoderCap()
/*static*/ void
MediaProfiles::createDefaultImageEncodingQualityLevels(MediaProfiles *profiles)
{
- profiles->mImageEncodingQualityLevels.add(70);
- profiles->mImageEncodingQualityLevels.add(80);
- profiles->mImageEncodingQualityLevels.add(90);
+ ImageEncodingQualityLevels *levels = new ImageEncodingQualityLevels();
+ levels->mCameraId = 0;
+ levels->mLevels.add(70);
+ levels->mLevels.add(80);
+ levels->mLevels.add(90);
+ profiles->mImageEncodingQualityLevels.add(levels);
}
/*static*/ MediaProfiles*
@@ -629,19 +668,24 @@ Vector<audio_decoder> MediaProfiles::getAudioDecoders() const
return decoders; // copy out
}
-int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_quality quality) const
+int MediaProfiles::getCamcorderProfileParamByName(const char *name,
+ int cameraId,
+ camcorder_quality quality) const
{
- LOGV("getCamcorderProfileParamByName: %s for quality %d", name, quality);
+ LOGV("getCamcorderProfileParamByName: %s for camera %d, quality %d",
+ name, cameraId, quality);
int index = -1;
for (size_t i = 0, n = mCamcorderProfiles.size(); i < n; ++i) {
- if (mCamcorderProfiles[i]->mQuality == quality) {
+ if (mCamcorderProfiles[i]->mCameraId == cameraId &&
+ mCamcorderProfiles[i]->mQuality == quality) {
index = i;
break;
}
}
if (index == -1) {
- LOGE("The given camcorder profile quality %d is not found", quality);
+ LOGE("The given camcorder profile camera %d quality %d is not found",
+ cameraId, quality);
return -1;
}
@@ -657,13 +701,18 @@ int MediaProfiles::getCamcorderProfileParamByName(const char *name, camcorder_qu
if (!strcmp("aud.ch", name)) return mCamcorderProfiles[index]->mAudioCodec->mChannels;
if (!strcmp("aud.hz", name)) return mCamcorderProfiles[index]->mAudioCodec->mSampleRate;
- LOGE("The given camcorder profile param name %s is not found", name);
+ LOGE("The given camcorder profile param id %d name %s is not found", cameraId, name);
return -1;
}
-Vector<int> MediaProfiles::getImageEncodingQualityLevels() const
+Vector<int> MediaProfiles::getImageEncodingQualityLevels(int cameraId) const
{
- return mImageEncodingQualityLevels; // copy out
+ Vector<int> result;
+ ImageEncodingQualityLevels *levels = findImageEncodingQualityLevels(cameraId);
+ if (levels != NULL) {
+ result = levels->mLevels; // copy out
+ }
+ return result;
}
MediaProfiles::~MediaProfiles()
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 843a8fd..6f581d3 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaScanner"
+#include <utils/Log.h>
+
#include <media/mediascanner.h>
#include <sys/stat.h>
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
new file mode 100644
index 0000000..32cdb49
--- /dev/null
+++ b/media/libmedia/Visualizer.cpp
@@ -0,0 +1,330 @@
+/*
+**
+** Copyright 2010, 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.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Visualizer"
+#include <utils/Log.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <media/Visualizer.h>
+
+extern "C" {
+#define FLOATING_POINT 1
+#include "fftwrap.h"
+}
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+Visualizer::Visualizer (int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId)
+ : AudioEffect(SL_IID_VISUALIZATION, NULL, priority, cbf, user, sessionId),
+ mCaptureRate(CAPTURE_RATE_DEF),
+ mCaptureSize(CAPTURE_SIZE_DEF),
+ mSampleRate(44100000),
+ mCaptureCallBack(NULL),
+ mCaptureCbkUser(NULL)
+{
+ initCaptureSize();
+ if (mCaptureSize != 0) {
+ mFftTable = spx_fft_init(mCaptureSize);
+ } else {
+ mFftTable = NULL;
+ }
+}
+
+Visualizer::~Visualizer()
+{
+ if (mFftTable != NULL) {
+ spx_fft_destroy(mFftTable);
+ }
+}
+
+status_t Visualizer::setEnabled(bool enabled)
+{
+ Mutex::Autolock _l(mLock);
+
+ sp<CaptureThread> t = mCaptureThread;
+ if (t != 0) {
+ if (enabled) {
+ if (t->exitPending()) {
+ if (t->requestExitAndWait() == WOULD_BLOCK) {
+ LOGE("Visualizer::enable() called from thread");
+ return INVALID_OPERATION;
+ }
+ }
+ }
+ t->mLock.lock();
+ }
+
+ status_t status = AudioEffect::setEnabled(enabled);
+
+ if (status == NO_ERROR) {
+ if (t != 0) {
+ if (enabled) {
+ t->run("AudioTrackThread");
+ } else {
+ t->requestExit();
+ }
+ }
+ }
+
+ if (t != 0) {
+ t->mLock.unlock();
+ }
+
+ return status;
+}
+
+status_t Visualizer::setCaptureCallBack(capture_cbk_t cbk, void* user, uint32_t flags, uint32_t rate)
+{
+ if (rate > CAPTURE_RATE_MAX) {
+ return BAD_VALUE;
+ }
+ Mutex::Autolock _l(mLock);
+
+ if (mEnabled) {
+ return INVALID_OPERATION;
+ }
+
+ sp<CaptureThread> t = mCaptureThread;
+ if (t != 0) {
+ t->mLock.lock();
+ }
+ mCaptureThread.clear();
+ mCaptureCallBack = cbk;
+ mCaptureCbkUser = user;
+ mCaptureFlags = flags;
+ mCaptureRate = rate;
+
+ if (t != 0) {
+ t->mLock.unlock();
+ }
+
+ if (cbk != NULL) {
+ mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
+ if (mCaptureThread == 0) {
+ LOGE("Could not create callback thread");
+ return NO_INIT;
+ }
+ }
+ LOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
+ rate, mCaptureThread.get(), mCaptureFlags);
+ return NO_ERROR;
+}
+
+status_t Visualizer::setCaptureSize(uint32_t size)
+{
+ if (size > VISUALIZER_CAPTURE_SIZE_MAX ||
+ size < VISUALIZER_CAPTURE_SIZE_MIN ||
+ AudioSystem::popCount(size) != 1) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mLock);
+ if (mEnabled) {
+ return INVALID_OPERATION;
+ }
+
+ uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+ effect_param_t *p = (effect_param_t *)buf32;
+
+ p->psize = sizeof(uint32_t);
+ p->vsize = sizeof(uint32_t);
+ *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE;
+ *((int32_t *)p->data + 1)= size;
+ status_t status = setParameter(p);
+
+ LOGV("setCaptureSize size %d status %d p->status %d", size, status, p->status);
+
+ if (status == NO_ERROR) {
+ status = p->status;
+ }
+ if (status == NO_ERROR) {
+ mCaptureSize = size;
+ if (mFftTable != NULL) {
+ spx_fft_destroy(mFftTable);
+ }
+ mFftTable = spx_fft_init(mCaptureSize);
+ LOGV("setCaptureSize size %d mFftTable %p", mCaptureSize, mFftTable);
+ }
+
+ return status;
+}
+
+status_t Visualizer::getWaveForm(uint8_t *waveform)
+{
+ if (waveform == NULL) {
+ return BAD_VALUE;
+ }
+ if (mCaptureSize == 0) {
+ return NO_INIT;
+ }
+
+ status_t status = NO_ERROR;
+ if (mEnabled) {
+ uint32_t replySize = mCaptureSize;
+ status_t status = command(VISU_CMD_CAPTURE, 0, NULL, &replySize, waveform);
+ if (replySize == 0) {
+ status = NOT_ENOUGH_DATA;
+ }
+ } else {
+ memset(waveform, 0x80, mCaptureSize);
+ }
+ return status;
+}
+
+status_t Visualizer::getFft(uint8_t *fft)
+{
+ if (fft == NULL) {
+ return BAD_VALUE;
+ }
+ if (mCaptureSize == 0) {
+ return NO_INIT;
+ }
+
+ status_t status = NO_ERROR;
+ if (mEnabled) {
+ uint8_t buf[mCaptureSize];
+ status_t status = getWaveForm(buf);
+ if (status == NO_ERROR) {
+ status = doFft(fft, buf);
+ }
+ } else {
+ memset(fft, 0, mCaptureSize);
+ }
+ return status;
+}
+
+status_t Visualizer::doFft(uint8_t *fft, uint8_t *waveform)
+{
+ if (mFftTable == NULL) {
+ return NO_INIT;
+ }
+
+ float fsrc[mCaptureSize];
+ for (uint32_t i = 0; i < mCaptureSize; i++) {
+ fsrc[i] = (int16_t)(waveform[i] ^ 0x80) << 8;
+ }
+ float fdst[mCaptureSize];
+ spx_fft_float(mFftTable, fsrc, fdst);
+ for (uint32_t i = 0; i < mCaptureSize; i++) {
+ fft[i] = (uint8_t)((int32_t)fdst[i] >> 8);
+ }
+ return NO_ERROR;
+}
+
+void Visualizer::periodicCapture()
+{
+ Mutex::Autolock _l(mLock);
+ LOGV("periodicCapture() %p mCaptureCallBack %p mCaptureFlags 0x%08x",
+ this, mCaptureCallBack, mCaptureFlags);
+ if (mCaptureCallBack != NULL &&
+ (mCaptureFlags & (CAPTURE_WAVEFORM|CAPTURE_FFT)) &&
+ mCaptureSize != 0) {
+ uint8_t waveform[mCaptureSize];
+ status_t status = getWaveForm(waveform);
+ if (status != NO_ERROR) {
+ return;
+ }
+ uint8_t fft[mCaptureSize];
+ if (mCaptureFlags & CAPTURE_FFT) {
+ status = doFft(fft, waveform);
+ }
+ if (status != NO_ERROR) {
+ return;
+ }
+ uint8_t *wavePtr = NULL;
+ uint8_t *fftPtr = NULL;
+ uint32_t waveSize = 0;
+ uint32_t fftSize = 0;
+ if (mCaptureFlags & CAPTURE_WAVEFORM) {
+ wavePtr = waveform;
+ waveSize = mCaptureSize;
+ }
+ if (mCaptureFlags & CAPTURE_FFT) {
+ fftPtr = fft;
+ fftSize = mCaptureSize;
+ }
+ mCaptureCallBack(mCaptureCbkUser, waveSize, wavePtr, fftSize, fftPtr, mSampleRate);
+ }
+}
+
+uint32_t Visualizer::initCaptureSize()
+{
+ uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+ effect_param_t *p = (effect_param_t *)buf32;
+
+ p->psize = sizeof(uint32_t);
+ p->vsize = sizeof(uint32_t);
+ *(int32_t *)p->data = VISU_PARAM_CAPTURE_SIZE;
+ status_t status = getParameter(p);
+
+ if (status == NO_ERROR) {
+ status = p->status;
+ }
+
+ uint32_t size = 0;
+ if (status == NO_ERROR) {
+ size = *((int32_t *)p->data + 1);
+ }
+ mCaptureSize = size;
+
+ LOGV("initCaptureSize size %d status %d", mCaptureSize, status);
+
+ return size;
+}
+
+//-------------------------------------------------------------------------
+
+Visualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava)
+ : Thread(bCanCallJava), mReceiver(receiver)
+{
+ mSleepTimeUs = 1000000000 / captureRate;
+ LOGV("CaptureThread cstor %p captureRate %d mSleepTimeUs %d", this, captureRate, mSleepTimeUs);
+}
+
+bool Visualizer::CaptureThread::threadLoop()
+{
+ LOGV("CaptureThread %p enter", this);
+ while (!exitPending())
+ {
+ usleep(mSleepTimeUs);
+ mReceiver.periodicCapture();
+ }
+ LOGV("CaptureThread %p exiting", this);
+ return false;
+}
+
+status_t Visualizer::CaptureThread::readyToRun()
+{
+ return NO_ERROR;
+}
+
+void Visualizer::CaptureThread::onFirstRef()
+{
+}
+
+}; // namespace android
+
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index c6bbbcc..1c99ae5 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -55,6 +55,7 @@ MediaPlayer::MediaPlayer()
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
+ mAudioSessionId = AudioSystem::newAudioSessionId();
}
MediaPlayer::~MediaPlayer()
@@ -137,7 +138,7 @@ status_t MediaPlayer::setDataSource(
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(
- service->create(getpid(), this, url, headers));
+ service->create(getpid(), this, url, headers, mAudioSessionId));
err = setDataSource(player);
}
}
@@ -150,7 +151,7 @@ status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
status_t err = UNKNOWN_ERROR;
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
- sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length));
+ sp<IMediaPlayer> player(service->create(getpid(), this, fd, offset, length, mAudioSessionId));
err = setDataSource(player);
}
return err;
@@ -269,6 +270,7 @@ status_t MediaPlayer::start()
MEDIA_PLAYER_PLAYBACK_COMPLETE | MEDIA_PLAYER_PAUSED ) ) ) {
mPlayer->setLooping(mLoop);
mPlayer->setVolume(mLeftVolume, mRightVolume);
+ mPlayer->setAuxEffectSendLevel(mSendLevel);
mCurrentState = MEDIA_PLAYER_STARTED;
status_t ret = mPlayer->start();
if (ret != NO_ERROR) {
@@ -501,6 +503,52 @@ status_t MediaPlayer::setVolume(float leftVolume, float rightVolume)
return OK;
}
+status_t MediaPlayer::setAudioSessionId(int sessionId)
+{
+ LOGV("MediaPlayer::setAudioSessionId(%d)", sessionId);
+ Mutex::Autolock _l(mLock);
+ if (!(mCurrentState & MEDIA_PLAYER_IDLE)) {
+ LOGE("setAudioSessionId called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+ if (sessionId < 0) {
+ return BAD_VALUE;
+ }
+ mAudioSessionId = sessionId;
+ return NO_ERROR;
+}
+
+int MediaPlayer::getAudioSessionId()
+{
+ Mutex::Autolock _l(mLock);
+ return mAudioSessionId;
+}
+
+status_t MediaPlayer::setAuxEffectSendLevel(float level)
+{
+ LOGV("MediaPlayer::setAuxEffectSendLevel(%f)", level);
+ Mutex::Autolock _l(mLock);
+ mSendLevel = level;
+ if (mPlayer != 0) {
+ return mPlayer->setAuxEffectSendLevel(level);
+ }
+ return OK;
+}
+
+status_t MediaPlayer::attachAuxEffect(int effectId)
+{
+ LOGV("MediaPlayer::attachAuxEffect(%d)", effectId);
+ Mutex::Autolock _l(mLock);
+ if (mPlayer == 0 ||
+ (mCurrentState & MEDIA_PLAYER_IDLE) ||
+ (mCurrentState == MEDIA_PLAYER_STATE_ERROR )) {
+ LOGE("attachAuxEffect called in state %d", mCurrentState);
+ return INVALID_OPERATION;
+ }
+
+ return mPlayer->attachAuxEffect(effectId);
+}
+
void MediaPlayer::notify(int msg, int ext1, int ext2)
{
LOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
@@ -636,61 +684,4 @@ void MediaPlayer::died()
}
-extern "C" {
-#define FLOATING_POINT 1
-#include "fftwrap.h"
-}
-
-static void *ffttable = NULL;
-
-// peeks at the audio data and fills 'data' with the requested kind
-// (currently kind=0 returns mono 16 bit PCM data, and kind=1 returns
-// 256 point FFT data). Return value is number of samples returned,
-// which may be 0.
-/*static*/ int MediaPlayer::snoop(short* data, int len, int kind) {
-
- sp<IMemory> p;
- const sp<IMediaPlayerService>& service = getMediaPlayerService();
- if (service != 0) {
- // Take a peek at the waveform. The returned data consists of 16 bit mono PCM data.
- p = service->snoop();
-
- if (p == NULL) {
- return 0;
- }
-
- if (kind == 0) { // return waveform data
- int plen = p->size();
- len *= 2; // number of shorts -> number of bytes
- short *src = (short*) p->pointer();
- if (plen > len) {
- plen = len;
- }
- memcpy(data, src, plen);
- return plen / sizeof(short); // return number of samples
- } else if (kind == 1) {
- // TODO: use a more efficient FFT
- // Right now this uses the speex library, which is compiled to do a float FFT
- if (!ffttable) ffttable = spx_fft_init(512);
- short *usrc = (short*) p->pointer();
- float fsrc[512];
- for (int i=0;i<512;i++)
- fsrc[i] = usrc[i];
- float fdst[512];
- spx_fft_float(ffttable, fsrc, fdst);
- if (len > 512) {
- len = 512;
- }
- len /= 2; // only half the output data is valid
- for (int i=0; i < len; i++)
- data[i] = fdst[i];
- return len;
- }
-
- } else {
- LOGE("Unable to locate media service");
- }
- return 0;
-}
-
}; // namespace android
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index cf97b23..8f010c9 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -11,21 +11,11 @@ LOCAL_SRC_FILES:= \
MediaPlayerService.cpp \
MetadataRetrieverClient.cpp \
TestPlayerStub.cpp \
- VorbisPlayer.cpp \
- VorbisMetadataRetriever.cpp \
- MidiMetadataRetriever.cpp \
- MidiFile.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES += \
- StagefrightPlayer.cpp \
+ MidiMetadataRetriever.cpp \
+ MidiFile.cpp \
+ StagefrightPlayer.cpp \
StagefrightRecorder.cpp
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT=1
-
-endif
-
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -ldl -lpthread
endif
@@ -37,6 +27,7 @@ LOCAL_SHARED_LIBRARIES := \
libvorbisidec \
libsonivox \
libmedia \
+ libcamera_client \
libandroid_runtime \
libstagefright \
libstagefright_omx \
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 6a6afa1..b5972e7 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -56,7 +56,6 @@
#include "MetadataRetrieverClient.h"
#include "MidiFile.h"
-#include "VorbisPlayer.h"
#include <media/PVPlayer.h>
#include "TestPlayerStub.h"
#include "StagefrightPlayer.h"
@@ -197,8 +196,6 @@ extmap FILE_EXTS [] = {
{".rtttl", SONIVOX_PLAYER},
{".rtx", SONIVOX_PLAYER},
{".ota", SONIVOX_PLAYER},
- {".ogg", VORBIS_PLAYER},
- {".oga", VORBIS_PLAYER},
#ifndef NO_OPENCORE
{".wma", PV_PLAYER},
{".wmv", PV_PLAYER},
@@ -228,14 +225,10 @@ MediaPlayerService::~MediaPlayerService()
sp<IMediaRecorder> MediaPlayerService::createMediaRecorder(pid_t pid)
{
-#ifndef NO_OPENCORE
sp<MediaRecorderClient> recorder = new MediaRecorderClient(this, pid);
wp<MediaRecorderClient> w = recorder;
Mutex::Autolock lock(mLock);
mMediaRecorderClients.add(w);
-#else
- sp<MediaRecorderClient> recorder = NULL;
-#endif
LOGV("Create new media recorder client from pid %d", pid);
return recorder;
}
@@ -256,11 +249,12 @@ sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pi
sp<IMediaPlayer> MediaPlayerService::create(
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers)
+ const KeyedVector<String8, String8> *headers, int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
- sp<Client> c = new Client(this, pid, connId, client);
- LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId);
+ sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+ LOGV("Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d",
+ connId, pid, url, connId, audioSessionId);
if (NO_ERROR != c->setDataSource(url, headers))
{
c.clear();
@@ -273,12 +267,12 @@ sp<IMediaPlayer> MediaPlayerService::create(
}
sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client,
- int fd, int64_t offset, int64_t length)
+ int fd, int64_t offset, int64_t length, int audioSessionId)
{
int32_t connId = android_atomic_inc(&mNextConnId);
- sp<Client> c = new Client(this, pid, connId, client);
- LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld",
- connId, pid, fd, offset, length);
+ sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
+ LOGV("Create new client(%d) from pid %d, fd=%d, offset=%lld, length=%lld, audioSessionId=%d",
+ connId, pid, fd, offset, length, audioSessionId);
if (NO_ERROR != c->setDataSource(fd, offset, length)) {
c.clear();
} else {
@@ -335,6 +329,10 @@ status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector<String16>& a
snprintf(buffer, 255, " msec per frame(%f), latency (%d)\n",
mMsecsPerFrame, mLatency);
result.append(buffer);
+ snprintf(buffer, 255, " aux effect id(%d), send level (%f)\n",
+ mAuxEffectId, mSendLevel);
+ result.append(buffer);
+
::write(fd, result.string(), result.size());
if (mTrack != 0) {
mTrack->dump(fd, args);
@@ -517,11 +515,17 @@ status_t MediaPlayerService::dump(int fd, const Vector<String16>& args)
sp<Client> c = mClients[i].promote();
if (c != 0) c->dump(fd, args);
}
- for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
- result.append(" MediaRecorderClient\n");
- sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
- snprintf(buffer, 255, " pid(%d)\n\n", c->mPid);
- result.append(buffer);
+ if (mMediaRecorderClients.size() == 0) {
+ result.append(" No media recorder client\n\n");
+ } else {
+ for (int i = 0, n = mMediaRecorderClients.size(); i < n; ++i) {
+ sp<MediaRecorderClient> c = mMediaRecorderClients[i].promote();
+ snprintf(buffer, 255, " MediaRecorderClient pid(%d)\n", c->mPid);
+ result.append(buffer);
+ write(fd, result.string(), result.size());
+ result = "\n";
+ c->dump(fd, args);
+ }
}
result.append(" Files opened and/or mapped:\n");
@@ -613,7 +617,7 @@ void MediaPlayerService::removeClient(wp<Client> client)
}
MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t pid,
- int32_t connId, const sp<IMediaPlayerClient>& client)
+ int32_t connId, const sp<IMediaPlayerClient>& client, int audioSessionId)
{
LOGV("Client(%d) constructor", connId);
mPid = pid;
@@ -622,6 +626,8 @@ MediaPlayerService::Client::Client(const sp<MediaPlayerService>& service, pid_t
mClient = client;
mLoop = false;
mStatus = NO_INIT;
+ mAudioSessionId = audioSessionId;
+
#if CALLBACK_ANTAGONIZER
LOGD("create Antagonizer");
mAntagonizer = new Antagonizer(notify, this);
@@ -667,37 +673,9 @@ void MediaPlayerService::Client::disconnect()
}
static player_type getDefaultPlayerType() {
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-player", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- return STAGEFRIGHT_PLAYER;
- }
-#endif
-
- return PV_PLAYER;
-}
-
-// By default we use the VORBIS_PLAYER for vorbis playback (duh!),
-// but if the magic property is set we will use our new experimental
-// stagefright code instead.
-static player_type OverrideStagefrightForVorbis(player_type player) {
- if (player != VORBIS_PLAYER) {
- return player;
- }
-
-#if BUILD_WITH_FULL_STAGEFRIGHT
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-vorbis", value, NULL)
- && (!strcmp(value, "1") || !strcmp(value, "true"))) {
- return STAGEFRIGHT_PLAYER;
- }
-#endif
-
- return VORBIS_PLAYER;
+ return STAGEFRIGHT_PLAYER;
}
-
player_type getPlayerType(int fd, int64_t offset, int64_t length)
{
char buf[20];
@@ -709,7 +687,7 @@ player_type getPlayerType(int fd, int64_t offset, int64_t length)
// Ogg vorbis?
if (ident == 0x5367674f) // 'OggS'
- return OverrideStagefrightForVorbis(VORBIS_PLAYER);
+ return STAGEFRIGHT_PLAYER;
#ifndef NO_OPENCORE
if (ident == 0x75b22630) {
@@ -745,13 +723,6 @@ player_type getPlayerType(const char* url)
return TEST_PLAYER;
}
- bool useStagefrightForHTTP = false;
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-http", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- useStagefrightForHTTP = true;
- }
-
// use MidiFile for MIDI extensions
int lenURL = strlen(url);
for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
@@ -759,27 +730,21 @@ player_type getPlayerType(const char* url)
int start = lenURL - len;
if (start > 0) {
if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {
- if (FILE_EXTS[i].playertype == VORBIS_PLAYER
- && !strncasecmp(url, "http://", 7)
- && useStagefrightForHTTP) {
- return STAGEFRIGHT_PLAYER;
- }
- return OverrideStagefrightForVorbis(FILE_EXTS[i].playertype);
+ return FILE_EXTS[i].playertype;
}
}
}
- if (!strncasecmp(url, "http://", 7)) {
- if (!useStagefrightForHTTP) {
+ if (!strncasecmp(url, "rtsp://", 7)) {
+ char value[PROPERTY_VALUE_MAX];
+ if (!property_get("media.stagefright.enable-rtsp", value, NULL)
+ || (strcmp(value, "1") && strcasecmp(value, "true"))) {
+ // For now, we're going to use PV for rtsp-based playback
+ // by default until we can clear up a few more issues.
return PV_PLAYER;
}
}
- // Use PV_PLAYER for rtsp for now
- if (!strncasecmp(url, "rtsp://", 7)) {
- return PV_PLAYER;
- }
-
return getDefaultPlayerType();
}
@@ -798,16 +763,10 @@ static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
LOGV(" create MidiFile");
p = new MidiFile();
break;
- case VORBIS_PLAYER:
- LOGV(" create VorbisPlayer");
- p = new VorbisPlayer();
- break;
-#if BUILD_WITH_FULL_STAGEFRIGHT
case STAGEFRIGHT_PLAYER:
LOGV(" create StagefrightPlayer");
p = new StagefrightPlayer;
break;
-#endif
case TEST_PLAYER:
LOGV("Create Test Player stub");
p = new TestPlayerStub();
@@ -870,7 +829,7 @@ status_t MediaPlayerService::Client::setDataSource(
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
- mAudioOutput = new AudioOutput();
+ mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@@ -920,7 +879,7 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
if (p == NULL) return NO_INIT;
if (!p->hardwareOutput()) {
- mAudioOutput = new AudioOutput();
+ mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}
@@ -1138,6 +1097,21 @@ status_t MediaPlayerService::Client::setVolume(float leftVolume, float rightVolu
return NO_ERROR;
}
+status_t MediaPlayerService::Client::setAuxEffectSendLevel(float level)
+{
+ LOGV("[%d] setAuxEffectSendLevel(%f)", mConnId, level);
+ Mutex::Autolock l(mLock);
+ if (mAudioOutput != 0) return mAudioOutput->setAuxEffectSendLevel(level);
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::Client::attachAuxEffect(int effectId)
+{
+ LOGV("[%d] attachAuxEffect(%d)", mConnId, effectId);
+ Mutex::Autolock l(mLock);
+ if (mAudioOutput != 0) return mAudioOutput->attachAuxEffect(effectId);
+ return NO_ERROR;
+}
void MediaPlayerService::Client::notify(void* cookie, int msg, int ext1, int ext2)
{
@@ -1316,111 +1290,22 @@ Exit:
return mem;
}
-/*
- * Avert your eyes, ugly hack ahead.
- * The following is to support music visualizations.
- */
-
-static const int NUMVIZBUF = 32;
-static const int VIZBUFFRAMES = 1024;
-static const int BUFTIMEMSEC = NUMVIZBUF * VIZBUFFRAMES * 1000 / 44100;
-static const int TOTALBUFTIMEMSEC = NUMVIZBUF * BUFTIMEMSEC;
-
-static bool gotMem = false;
-static sp<MemoryHeapBase> heap;
-static sp<MemoryBase> mem[NUMVIZBUF];
-static uint64_t endTime;
-static uint64_t lastReadTime;
-static uint64_t lastWriteTime;
-static int writeIdx = 0;
-
-static void allocVizBufs() {
- if (!gotMem) {
- heap = new MemoryHeapBase(NUMVIZBUF * VIZBUFFRAMES * 2, 0, "snooper");
- for (int i=0;i<NUMVIZBUF;i++) {
- mem[i] = new MemoryBase(heap, VIZBUFFRAMES * 2 * i, VIZBUFFRAMES * 2);
- }
- endTime = 0;
- gotMem = true;
- }
-}
-
-
-/*
- * Get a buffer of audio data that is about to be played.
- * We don't synchronize this because in practice the writer
- * is ahead of the reader, and even if we did happen to catch
- * a buffer while it's being written, it's just a visualization,
- * so no harm done.
- */
-static sp<MemoryBase> getVizBuffer() {
-
- allocVizBufs();
-
- lastReadTime = uptimeMillis();
-
- // if there is no recent buffer (yet), just return empty handed
- if (lastWriteTime + TOTALBUFTIMEMSEC < lastReadTime) {
- //LOGI("@@@@ no audio data to look at yet: %d + %d < %d", (int)lastWriteTime, TOTALBUFTIMEMSEC, (int)lastReadTime);
- return NULL;
- }
-
- int timedelta = endTime - lastReadTime;
- if (timedelta < 0) timedelta = 0;
- int framedelta = timedelta * 44100 / 1000;
- int headIdx = (writeIdx - framedelta) / VIZBUFFRAMES - 1;
- while (headIdx < 0) {
- headIdx += NUMVIZBUF;
- }
- return mem[headIdx];
-}
-
-// Append the data to the vizualization buffer
-static void makeVizBuffers(const char *data, int len, uint64_t time) {
-
- allocVizBufs();
-
- uint64_t startTime = time;
- const int frameSize = 4; // 16 bit stereo sample is 4 bytes
- int offset = writeIdx;
- int maxoff = heap->getSize() / 2; // in shorts
- short *base = (short*)heap->getBase();
- short *src = (short*)data;
- while (len > 0) {
-
- // Degrade quality by mixing to mono and clearing the lowest 3 bits.
- // This should still be good enough for a visualization
- base[offset++] = ((int(src[0]) + int(src[1])) >> 1) & ~0x7;
- src += 2;
- len -= frameSize;
- if (offset >= maxoff) {
- offset = 0;
- }
- }
- writeIdx = offset;
- endTime = time + (len / frameSize) / 44;
- //LOGI("@@@ stored buffers from %d to %d", uint32_t(startTime), uint32_t(time));
-}
-
-sp<IMemory> MediaPlayerService::snoop()
-{
- sp<MemoryBase> mem = getVizBuffer();
- return mem;
-}
-
#undef LOG_TAG
#define LOG_TAG "AudioSink"
-MediaPlayerService::AudioOutput::AudioOutput()
+MediaPlayerService::AudioOutput::AudioOutput(int sessionId)
: mCallback(NULL),
- mCallbackCookie(NULL) {
+ mCallbackCookie(NULL),
+ mSessionId(sessionId) {
+ LOGV("AudioOutput(%d)", sessionId);
mTrack = 0;
mStreamType = AudioSystem::MUSIC;
mLeftVolume = 1.0;
mRightVolume = 1.0;
mLatency = 0;
mMsecsPerFrame = 0;
- mNumFramesWritten = 0;
+ mAuxEffectId = 0;
+ mSendLevel = 0.0;
setMinBufferCount();
}
@@ -1503,7 +1388,7 @@ status_t MediaPlayerService::AudioOutput::open(
bufferCount = mMinBufferCount;
}
- LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+ LOGV("open(%u, %d, %d, %d, %d)", sampleRate, channelCount, format, bufferCount,mSessionId);
if (mTrack) close();
int afSampleRate;
int afFrameCount;
@@ -1528,14 +1413,21 @@ status_t MediaPlayerService::AudioOutput::open(
frameCount,
0 /* flags */,
CallbackWrapper,
- this);
+ this,
+ 0,
+ mSessionId);
} else {
t = new AudioTrack(
mStreamType,
sampleRate,
format,
(channelCount == 2) ? AudioSystem::CHANNEL_OUT_STEREO : AudioSystem::CHANNEL_OUT_MONO,
- frameCount);
+ frameCount,
+ 0,
+ NULL,
+ NULL,
+ 0,
+ mSessionId);
}
if ((t == 0) || (t->initCheck() != NO_ERROR)) {
@@ -1546,10 +1438,13 @@ status_t MediaPlayerService::AudioOutput::open(
LOGV("setVolume");
t->setVolume(mLeftVolume, mRightVolume);
+
mMsecsPerFrame = 1.e3 / (float) sampleRate;
mLatency = t->latency();
mTrack = t;
- return NO_ERROR;
+
+ t->setAuxEffectSendLevel(mSendLevel);
+ return t->attachAuxEffect(mAuxEffectId);;
}
void MediaPlayerService::AudioOutput::start()
@@ -1557,31 +1452,11 @@ void MediaPlayerService::AudioOutput::start()
LOGV("start");
if (mTrack) {
mTrack->setVolume(mLeftVolume, mRightVolume);
+ mTrack->setAuxEffectSendLevel(mSendLevel);
mTrack->start();
- mTrack->getPosition(&mNumFramesWritten);
}
}
-void MediaPlayerService::AudioOutput::snoopWrite(const void* buffer, size_t size) {
- // Only make visualization buffers if anyone recently requested visualization data
- uint64_t now = uptimeMillis();
- if (lastReadTime + TOTALBUFTIMEMSEC >= now) {
- // Based on the current play counter, the number of frames written and
- // the current real time we can calculate the approximate real start
- // time of the buffer we're about to write.
- uint32_t pos;
- mTrack->getPosition(&pos);
-
- // we're writing ahead by this many frames:
- int ahead = mNumFramesWritten - pos;
- //LOGI("@@@ written: %d, playpos: %d, latency: %d", mNumFramesWritten, pos, mTrack->latency());
- // which is this many milliseconds, assuming 44100 Hz:
- ahead /= 44;
-
- makeVizBuffers((const char*)buffer, size, now + ahead + mTrack->latency());
- lastWriteTime = now;
- }
-}
ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
@@ -1590,9 +1465,7 @@ ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size)
//LOGV("write(%p, %u)", buffer, size);
if (mTrack) {
- snoopWrite(buffer, size);
ssize_t ret = mTrack->write(buffer, size);
- mNumFramesWritten += ret / 4; // assume 16 bit stereo
return ret;
}
return NO_INIT;
@@ -1602,7 +1475,6 @@ void MediaPlayerService::AudioOutput::stop()
{
LOGV("stop");
if (mTrack) mTrack->stop();
- lastWriteTime = 0;
}
void MediaPlayerService::AudioOutput::flush()
@@ -1615,7 +1487,6 @@ void MediaPlayerService::AudioOutput::pause()
{
LOGV("pause");
if (mTrack) mTrack->pause();
- lastWriteTime = 0;
}
void MediaPlayerService::AudioOutput::close()
@@ -1635,6 +1506,26 @@ void MediaPlayerService::AudioOutput::setVolume(float left, float right)
}
}
+status_t MediaPlayerService::AudioOutput::setAuxEffectSendLevel(float level)
+{
+ LOGV("setAuxEffectSendLevel(%f)", level);
+ mSendLevel = level;
+ if (mTrack) {
+ return mTrack->setAuxEffectSendLevel(level);
+ }
+ return NO_ERROR;
+}
+
+status_t MediaPlayerService::AudioOutput::attachAuxEffect(int effectId)
+{
+ LOGV("attachAuxEffect(%d)", effectId);
+ mAuxEffectId = effectId;
+ if (mTrack) {
+ return mTrack->attachAuxEffect(effectId);
+ }
+ return NO_ERROR;
+}
+
// static
void MediaPlayerService::AudioOutput::CallbackWrapper(
int event, void *cookie, void *info) {
@@ -1651,9 +1542,6 @@ void MediaPlayerService::AudioOutput::CallbackWrapper(
buffer->size = actualSize;
- if (actualSize > 0) {
- me->snoopWrite(buffer->raw, actualSize);
- }
}
#undef LOG_TAG
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 2408c62..a967ee2 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -65,7 +65,7 @@ class MediaPlayerService : public BnMediaPlayerService
class AudioOutput : public MediaPlayerBase::AudioSink
{
public:
- AudioOutput();
+ AudioOutput(int sessionId);
virtual ~AudioOutput();
virtual bool ready() const { return mTrack != NULL; }
@@ -91,6 +91,8 @@ class MediaPlayerService : public BnMediaPlayerService
virtual void close();
void setAudioStreamType(int streamType) { mStreamType = streamType; }
void setVolume(float left, float right);
+ status_t setAuxEffectSendLevel(float level);
+ status_t attachAuxEffect(int effectId);
virtual status_t dump(int fd, const Vector<String16>& args) const;
static bool isOnEmulator();
@@ -108,13 +110,12 @@ class MediaPlayerService : public BnMediaPlayerService
float mRightVolume;
float mMsecsPerFrame;
uint32_t mLatency;
-
+ int mSessionId;
+ float mSendLevel;
+ int mAuxEffectId;
static bool mIsOnEmulator;
static int mMinBufferCount; // 12 for emulator; otherwise 4
- public: // visualization hack support
- uint32_t mNumFramesWritten;
- void snoopWrite(const void*, size_t);
};
class AudioCache : public MediaPlayerBase::AudioSink
@@ -185,12 +186,11 @@ public:
// House keeping for media player clients
virtual sp<IMediaPlayer> create(
pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- const KeyedVector<String8, String8> *headers);
+ const KeyedVector<String8, String8> *headers, int audioSessionId);
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length);
+ virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length, int audioSessionId);
virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
- virtual sp<IMemory> snoop();
virtual sp<IOMX> getOMX();
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -224,6 +224,8 @@ private:
Parcel *reply);
virtual status_t suspend();
virtual status_t resume();
+ virtual status_t setAuxEffectSendLevel(float level);
+ virtual status_t attachAuxEffect(int effectId);
sp<MediaPlayerBase> createPlayer(player_type playerType);
@@ -237,12 +239,15 @@ private:
pid_t pid() const { return mPid; }
virtual status_t dump(int fd, const Vector<String16>& args) const;
+ int getAudioSessionId() { return mAudioSessionId; }
+
private:
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
pid_t pid,
int32_t connId,
- const sp<IMediaPlayerClient>& client);
+ const sp<IMediaPlayerClient>& client,
+ int audioSessionId);
Client();
virtual ~Client();
@@ -271,6 +276,7 @@ private:
status_t mStatus;
bool mLoop;
int32_t mConnId;
+ int mAudioSessionId;
// Metadata filters.
media::Metadata::Filter mMetadataAllow; // protected by mLock
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 12de0d9..73862c3 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -294,13 +294,11 @@ MediaRecorderClient::MediaRecorderClient(const sp<MediaPlayerService>& service,
LOGV("Client constructor");
mPid = pid;
-#if BUILD_WITH_FULL_STAGEFRIGHT
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.enable-record", value, NULL)
&& (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
mRecorder = new StagefrightRecorder;
} else
-#endif
#ifndef NO_OPENCORE
{
mRecorder = new PVMediaRecorder();
@@ -320,7 +318,7 @@ MediaRecorderClient::~MediaRecorderClient()
release();
}
-status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener)
+status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
{
LOGV("setListener");
Mutex::Autolock lock(mLock);
@@ -331,5 +329,12 @@ status_t MediaRecorderClient::setListener(const sp<IMediaPlayerClient>& listener
return mRecorder->setListener(listener);
}
+status_t MediaRecorderClient::dump(int fd, const Vector<String16>& args) const {
+ if (mRecorder != NULL) {
+ return mRecorder->dump(fd, args);
+ }
+ return OK;
+}
+
}; // namespace android
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 805005d..1d1913d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -28,7 +28,7 @@ class MediaPlayerService;
class MediaRecorderClient : public BnMediaRecorder
{
public:
- virtual status_t setCamera(const sp<ICamera>& camera);
+ virtual status_t setCamera(const sp<ICamera>& camera);
virtual status_t setPreviewSurface(const sp<ISurface>& surface);
virtual status_t setVideoSource(int vs);
virtual status_t setAudioSource(int as);
@@ -40,26 +40,27 @@ public:
virtual status_t setVideoSize(int width, int height);
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setParameters(const String8& params);
- virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
+ virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
virtual status_t prepare();
virtual status_t getMaxAmplitude(int* max);
virtual status_t start();
virtual status_t stop();
- virtual status_t reset();
+ virtual status_t reset();
virtual status_t init();
virtual status_t close();
virtual status_t release();
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
private:
- friend class MediaPlayerService; // for accessing private constructor
+ friend class MediaPlayerService; // for accessing private constructor
- MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
- virtual ~MediaRecorderClient();
+ MediaRecorderClient(const sp<MediaPlayerService>& service, pid_t pid);
+ virtual ~MediaRecorderClient();
- pid_t mPid;
- Mutex mLock;
- MediaRecorderBase *mRecorder;
- sp<MediaPlayerService> mMediaPlayerService;
+ pid_t mPid;
+ Mutex mLock;
+ MediaRecorderBase *mRecorder;
+ sp<MediaPlayerService> mMediaPlayerService;
};
}; // namespace android
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index 550b84d..ca229fa 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,7 +37,6 @@
#include <media/MediaPlayerInterface.h>
#include <media/PVMetadataRetriever.h>
#include <private/media/VideoFrame.h>
-#include "VorbisMetadataRetriever.h"
#include "MidiMetadataRetriever.h"
#include "MetadataRetrieverClient.h"
#include "StagefrightMetadataRetriever.h"
@@ -103,30 +102,17 @@ static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
{
sp<MediaMetadataRetrieverBase> p;
switch (playerType) {
-#if BUILD_WITH_FULL_STAGEFRIGHT
case STAGEFRIGHT_PLAYER:
{
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.enable-meta", value, NULL)
- && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
- LOGV("create StagefrightMetadataRetriever");
- p = new StagefrightMetadataRetriever;
- break;
- }
-
- // fall through
+ p = new StagefrightMetadataRetriever;
+ break;
}
-#endif
#ifndef NO_OPENCORE
case PV_PLAYER:
LOGV("create pv metadata retriever");
p = new PVMetadataRetriever();
break;
#endif
- case VORBIS_PLAYER:
- LOGV("create vorbis metadata retriever");
- p = new VorbisMetadataRetriever();
- break;
case SONIVOX_PLAYER:
LOGV("create midi metadata retriever");
p = new MidiMetadataRetriever();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 531fd11..f26676d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -20,6 +20,7 @@
#include "StagefrightRecorder.h"
+#include <binder/IPCThreadState.h>
#include <media/stagefright/AudioSource.h>
#include <media/stagefright/AMRWriter.h>
#include <media/stagefright/CameraSource.h>
@@ -29,17 +30,28 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/OMXClient.h>
#include <media/stagefright/OMXCodec.h>
+#include <media/MediaProfiles.h>
#include <camera/ICamera.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
#include <surfaceflinger/ISurface.h>
#include <utils/Errors.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
namespace android {
-StagefrightRecorder::StagefrightRecorder() {
+StagefrightRecorder::StagefrightRecorder()
+ : mWriter(NULL),
+ mOutputFd(-1) {
+
+ LOGV("Constructor");
reset();
}
StagefrightRecorder::~StagefrightRecorder() {
+ LOGV("Destructor");
stop();
if (mOutputFd >= 0) {
@@ -49,40 +61,103 @@ StagefrightRecorder::~StagefrightRecorder() {
}
status_t StagefrightRecorder::init() {
+ LOGV("init");
return OK;
}
status_t StagefrightRecorder::setAudioSource(audio_source as) {
- mAudioSource = as;
+ LOGV("setAudioSource: %d", as);
+ if (as < AUDIO_SOURCE_DEFAULT ||
+ as >= AUDIO_SOURCE_LIST_END) {
+ LOGE("Invalid audio source: %d", as);
+ return BAD_VALUE;
+ }
+
+ if (as == AUDIO_SOURCE_DEFAULT) {
+ mAudioSource = AUDIO_SOURCE_MIC;
+ } else {
+ mAudioSource = as;
+ }
return OK;
}
status_t StagefrightRecorder::setVideoSource(video_source vs) {
- mVideoSource = vs;
+ LOGV("setVideoSource: %d", vs);
+ if (vs < VIDEO_SOURCE_DEFAULT ||
+ vs >= VIDEO_SOURCE_LIST_END) {
+ LOGE("Invalid video source: %d", vs);
+ return BAD_VALUE;
+ }
+
+ if (vs == VIDEO_SOURCE_DEFAULT) {
+ mVideoSource = VIDEO_SOURCE_CAMERA;
+ } else {
+ mVideoSource = vs;
+ }
return OK;
}
status_t StagefrightRecorder::setOutputFormat(output_format of) {
- mOutputFormat = of;
+ LOGV("setOutputFormat: %d", of);
+ if (of < OUTPUT_FORMAT_DEFAULT ||
+ of >= OUTPUT_FORMAT_LIST_END) {
+ LOGE("Invalid output format: %d", of);
+ return BAD_VALUE;
+ }
+
+ if (of == OUTPUT_FORMAT_DEFAULT) {
+ mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
+ } else {
+ mOutputFormat = of;
+ }
return OK;
}
status_t StagefrightRecorder::setAudioEncoder(audio_encoder ae) {
- mAudioEncoder = ae;
+ LOGV("setAudioEncoder: %d", ae);
+ if (ae < AUDIO_ENCODER_DEFAULT ||
+ ae >= AUDIO_ENCODER_LIST_END) {
+ LOGE("Invalid audio encoder: %d", ae);
+ return BAD_VALUE;
+ }
+
+ if (ae == AUDIO_ENCODER_DEFAULT) {
+ mAudioEncoder = AUDIO_ENCODER_AMR_NB;
+ } else {
+ mAudioEncoder = ae;
+ }
return OK;
}
status_t StagefrightRecorder::setVideoEncoder(video_encoder ve) {
- mVideoEncoder = ve;
+ LOGV("setVideoEncoder: %d", ve);
+ if (ve < VIDEO_ENCODER_DEFAULT ||
+ ve >= VIDEO_ENCODER_LIST_END) {
+ LOGE("Invalid video encoder: %d", ve);
+ return BAD_VALUE;
+ }
+
+ if (ve == VIDEO_ENCODER_DEFAULT) {
+ mVideoEncoder = VIDEO_ENCODER_H263;
+ } else {
+ mVideoEncoder = ve;
+ }
return OK;
}
status_t StagefrightRecorder::setVideoSize(int width, int height) {
+ LOGV("setVideoSize: %dx%d", width, height);
+ if (width <= 0 || height <= 0) {
+ LOGE("Invalid video size: %dx%d", width, height);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the dimension will be performed later
mVideoWidth = width;
mVideoHeight = height;
@@ -90,35 +165,70 @@ status_t StagefrightRecorder::setVideoSize(int width, int height) {
}
status_t StagefrightRecorder::setVideoFrameRate(int frames_per_second) {
+ LOGV("setVideoFrameRate: %d", frames_per_second);
+ if (frames_per_second <= 0 || frames_per_second > 30) {
+ LOGE("Invalid video frame rate: %d", frames_per_second);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the frame rate will be performed later
mFrameRate = frames_per_second;
return OK;
}
status_t StagefrightRecorder::setCamera(const sp<ICamera> &camera) {
- mCamera = camera;
+ LOGV("setCamera");
+ if (camera == 0) {
+ LOGE("camera is NULL");
+ return BAD_VALUE;
+ }
+
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mFlags &= ~FLAGS_HOT_CAMERA;
+ mCamera = Camera::create(camera);
+ if (mCamera == 0) {
+ LOGE("Unable to connect to camera");
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ return -EBUSY;
+ }
+
+ LOGV("Connected to camera");
+ if (mCamera->previewEnabled()) {
+ LOGV("camera is hot");
+ mFlags |= FLAGS_HOT_CAMERA;
+ }
+ IPCThreadState::self()->restoreCallingIdentity(token);
return OK;
}
status_t StagefrightRecorder::setPreviewSurface(const sp<ISurface> &surface) {
+ LOGV("setPreviewSurface: %p", surface.get());
mPreviewSurface = surface;
return OK;
}
status_t StagefrightRecorder::setOutputFile(const char *path) {
+ LOGE("setOutputFile(const char*) must not be called");
// We don't actually support this at all, as the media_server process
// no longer has permissions to create files.
- return UNKNOWN_ERROR;
+ return -EPERM;
}
status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t length) {
+ LOGV("setOutputFile: %d, %lld, %lld", fd, offset, length);
// These don't make any sense, do they?
CHECK_EQ(offset, 0);
CHECK_EQ(length, 0);
+ if (fd < 0) {
+ LOGE("Invalid file descriptor: %d", fd);
+ return -EBADF;
+ }
+
if (mOutputFd >= 0) {
::close(mOutputFd);
}
@@ -127,13 +237,366 @@ status_t StagefrightRecorder::setOutputFile(int fd, int64_t offset, int64_t leng
return OK;
}
-status_t StagefrightRecorder::setParameters(const String8 &params) {
- mParams = params;
+// Attempt to parse an int64 literal optionally surrounded by whitespace,
+// returns true on success, false otherwise.
+static bool safe_strtoi64(const char *s, int64_t *val) {
+ char *end;
+ *val = strtoll(s, &end, 10);
+
+ if (end == s || errno == ERANGE) {
+ return false;
+ }
+
+ // Skip trailing whitespace
+ while (isspace(*end)) {
+ ++end;
+ }
+
+ // For a successful return, the string must contain nothing but a valid
+ // int64 literal optionally surrounded by whitespace.
+
+ return *end == '\0';
+}
+
+// Return true if the value is in [0, 0x007FFFFFFF]
+static bool safe_strtoi32(const char *s, int32_t *val) {
+ int64_t temp;
+ if (safe_strtoi64(s, &temp)) {
+ if (temp >= 0 && temp <= 0x007FFFFFFF) {
+ *val = static_cast<int32_t>(temp);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Trim both leading and trailing whitespace from the given string.
+static void TrimString(String8 *s) {
+ size_t num_bytes = s->bytes();
+ const char *data = s->string();
+
+ size_t leading_space = 0;
+ while (leading_space < num_bytes && isspace(data[leading_space])) {
+ ++leading_space;
+ }
+
+ size_t i = num_bytes;
+ while (i > leading_space && isspace(data[i - 1])) {
+ --i;
+ }
+
+ s->setTo(String8(&data[leading_space], i - leading_space));
+}
+
+status_t StagefrightRecorder::setParamAudioSamplingRate(int32_t sampleRate) {
+ LOGV("setParamAudioSamplingRate: %d", sampleRate);
+ if (sampleRate <= 0) {
+ LOGE("Invalid audio sampling rate: %d", sampleRate);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the sample rate will be performed later.
+ mSampleRate = sampleRate;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioNumberOfChannels(int32_t channels) {
+ LOGV("setParamAudioNumberOfChannels: %d", channels);
+ if (channels <= 0 || channels >= 3) {
+ LOGE("Invalid number of audio channels: %d", channels);
+ return BAD_VALUE;
+ }
+
+ // Additional check on the number of channels will be performed later.
+ mAudioChannels = channels;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioEncodingBitRate(int32_t bitRate) {
+ LOGV("setParamAudioEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ LOGE("Invalid audio encoding bit rate: %d", bitRate);
+ return BAD_VALUE;
+ }
+
+ // The target bit rate may not be exactly the same as the requested.
+ // It depends on many factors, such as rate control, and the bit rate
+ // range that a specific encoder supports. The mismatch between the
+ // the target and requested bit rate will NOT be treated as an error.
+ mAudioBitRate = bitRate;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
+ LOGV("setParamVideoEncodingBitRate: %d", bitRate);
+ if (bitRate <= 0) {
+ LOGE("Invalid video encoding bit rate: %d", bitRate);
+ return BAD_VALUE;
+ }
+
+ // The target bit rate may not be exactly the same as the requested.
+ // It depends on many factors, such as rate control, and the bit rate
+ // range that a specific encoder supports. The mismatch between the
+ // the target and requested bit rate will NOT be treated as an error.
+ mVideoBitRate = bitRate;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
+ LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
+ if (timeUs <= 1000000LL) { // XXX: 1 second
+ LOGE("Max file duration is too short: %lld us", timeUs);
+ return BAD_VALUE;
+ }
+ mMaxFileDurationUs = timeUs;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamMaxFileSizeBytes(int64_t bytes) {
+ LOGV("setParamMaxFileSizeBytes: %lld bytes", bytes);
+ if (bytes <= 1024) { // XXX: 1 kB
+ LOGE("Max file size is too small: %lld bytes", bytes);
+ return BAD_VALUE;
+ }
+ mMaxFileSizeBytes = bytes;
+ return OK;
+}
+status_t StagefrightRecorder::setParamInterleaveDuration(int32_t durationUs) {
+ LOGV("setParamInterleaveDuration: %d", durationUs);
+ if (durationUs <= 500000) { // 500 ms
+ // If interleave duration is too small, it is very inefficient to do
+ // interleaving since the metadata overhead will count for a significant
+ // portion of the saved contents
+ LOGE("Audio/video interleave duration is too small: %d us", durationUs);
+ return BAD_VALUE;
+ } else if (durationUs >= 10000000) { // 10 seconds
+ // If interleaving duration is too large, it can cause the recording
+ // session to use too much memory since we have to save the output
+ // data before we write them out
+ LOGE("Audio/video interleave duration is too large: %d us", durationUs);
+ return BAD_VALUE;
+ }
+ mInterleaveDurationUs = durationUs;
+ return OK;
+}
+
+// If seconds < 0, only the first frame is I frame, and rest are all P frames
+// If seconds == 0, all frames are encoded as I frames. No P frames
+// If seconds > 0, it is the time spacing (seconds) between 2 neighboring I frames
+status_t StagefrightRecorder::setParamVideoIFramesInterval(int32_t seconds) {
+ LOGV("setParamVideoIFramesInterval: %d seconds", seconds);
+ mIFramesIntervalSec = seconds;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParam64BitFileOffset(bool use64Bit) {
+ LOGV("setParam64BitFileOffset: %s",
+ use64Bit? "use 64 bit file offset": "use 32 bit file offset");
+ mUse64BitFileOffset = use64Bit;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoCameraId(int32_t cameraId) {
+ LOGV("setParamVideoCameraId: %d", cameraId);
+ if (cameraId < 0) {
+ return BAD_VALUE;
+ }
+ mCameraId = cameraId;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamTrackTimeStatus(int64_t timeDurationUs) {
+ LOGV("setParamTrackTimeStatus: %lld", timeDurationUs);
+ if (timeDurationUs < 20000) { // Infeasible if shorter than 20 ms?
+ LOGE("Tracking time duration too short: %lld us", timeDurationUs);
+ return BAD_VALUE;
+ }
+ mTrackEveryTimeDurationUs = timeDurationUs;
return OK;
}
-status_t StagefrightRecorder::setListener(const sp<IMediaPlayerClient> &listener) {
+status_t StagefrightRecorder::setParamVideoEncoderProfile(int32_t profile) {
+ LOGV("setParamVideoEncoderProfile: %d", profile);
+
+ // Additional check will be done later when we load the encoder.
+ // For now, we are accepting values defined in OpenMAX IL.
+ mVideoEncoderProfile = profile;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoEncoderLevel(int32_t level) {
+ LOGV("setParamVideoEncoderLevel: %d", level);
+
+ // Additional check will be done later when we load the encoder.
+ // For now, we are accepting values defined in OpenMAX IL.
+ mVideoEncoderLevel = level;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamMovieTimeScale(int32_t timeScale) {
+ LOGV("setParamMovieTimeScale: %d", timeScale);
+
+ // The range is set to be the same as the audio's time scale range
+ // since audio's time scale has a wider range.
+ if (timeScale < 600 || timeScale > 96000) {
+ LOGE("Time scale (%d) for movie is out of range [600, 96000]", timeScale);
+ return BAD_VALUE;
+ }
+ mMovieTimeScale = timeScale;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamVideoTimeScale(int32_t timeScale) {
+ LOGV("setParamVideoTimeScale: %d", timeScale);
+
+ // 60000 is chosen to make sure that each video frame from a 60-fps
+ // video has 1000 ticks.
+ if (timeScale < 600 || timeScale > 60000) {
+ LOGE("Time scale (%d) for video is out of range [600, 60000]", timeScale);
+ return BAD_VALUE;
+ }
+ mVideoTimeScale = timeScale;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParamAudioTimeScale(int32_t timeScale) {
+ LOGV("setParamAudioTimeScale: %d", timeScale);
+
+ // 96000 Hz is the highest sampling rate support in AAC.
+ if (timeScale < 600 || timeScale > 96000) {
+ LOGE("Time scale (%d) for audio is out of range [600, 96000]", timeScale);
+ return BAD_VALUE;
+ }
+ mAudioTimeScale = timeScale;
+ return OK;
+}
+
+status_t StagefrightRecorder::setParameter(
+ const String8 &key, const String8 &value) {
+ LOGV("setParameter: key (%s) => value (%s)", key.string(), value.string());
+ if (key == "max-duration") {
+ int64_t max_duration_ms;
+ if (safe_strtoi64(value.string(), &max_duration_ms)) {
+ return setParamMaxFileDurationUs(1000LL * max_duration_ms);
+ }
+ } else if (key == "max-filesize") {
+ int64_t max_filesize_bytes;
+ if (safe_strtoi64(value.string(), &max_filesize_bytes)) {
+ return setParamMaxFileSizeBytes(max_filesize_bytes);
+ }
+ } else if (key == "interleave-duration-us") {
+ int32_t durationUs;
+ if (safe_strtoi32(value.string(), &durationUs)) {
+ return setParamInterleaveDuration(durationUs);
+ }
+ } else if (key == "param-movie-time-scale") {
+ int32_t timeScale;
+ if (safe_strtoi32(value.string(), &timeScale)) {
+ return setParamMovieTimeScale(timeScale);
+ }
+ } else if (key == "param-use-64bit-offset") {
+ int32_t use64BitOffset;
+ if (safe_strtoi32(value.string(), &use64BitOffset)) {
+ return setParam64BitFileOffset(use64BitOffset != 0);
+ }
+ } else if (key == "param-track-time-status") {
+ int64_t timeDurationUs;
+ if (safe_strtoi64(value.string(), &timeDurationUs)) {
+ return setParamTrackTimeStatus(timeDurationUs);
+ }
+ } else if (key == "audio-param-sampling-rate") {
+ int32_t sampling_rate;
+ if (safe_strtoi32(value.string(), &sampling_rate)) {
+ return setParamAudioSamplingRate(sampling_rate);
+ }
+ } else if (key == "audio-param-number-of-channels") {
+ int32_t number_of_channels;
+ if (safe_strtoi32(value.string(), &number_of_channels)) {
+ return setParamAudioNumberOfChannels(number_of_channels);
+ }
+ } else if (key == "audio-param-encoding-bitrate") {
+ int32_t audio_bitrate;
+ if (safe_strtoi32(value.string(), &audio_bitrate)) {
+ return setParamAudioEncodingBitRate(audio_bitrate);
+ }
+ } else if (key == "audio-param-time-scale") {
+ int32_t timeScale;
+ if (safe_strtoi32(value.string(), &timeScale)) {
+ return setParamAudioTimeScale(timeScale);
+ }
+ } else if (key == "video-param-encoding-bitrate") {
+ int32_t video_bitrate;
+ if (safe_strtoi32(value.string(), &video_bitrate)) {
+ return setParamVideoEncodingBitRate(video_bitrate);
+ }
+ } else if (key == "video-param-i-frames-interval") {
+ int32_t seconds;
+ if (safe_strtoi32(value.string(), &seconds)) {
+ return setParamVideoIFramesInterval(seconds);
+ }
+ } else if (key == "video-param-encoder-profile") {
+ int32_t profile;
+ if (safe_strtoi32(value.string(), &profile)) {
+ return setParamVideoEncoderProfile(profile);
+ }
+ } else if (key == "video-param-encoder-level") {
+ int32_t level;
+ if (safe_strtoi32(value.string(), &level)) {
+ return setParamVideoEncoderLevel(level);
+ }
+ } else if (key == "video-param-camera-id") {
+ int32_t cameraId;
+ if (safe_strtoi32(value.string(), &cameraId)) {
+ return setParamVideoCameraId(cameraId);
+ }
+ } else if (key == "video-param-time-scale") {
+ int32_t timeScale;
+ if (safe_strtoi32(value.string(), &timeScale)) {
+ return setParamVideoTimeScale(timeScale);
+ }
+ } else {
+ LOGE("setParameter: failed to find key %s", key.string());
+ }
+ return BAD_VALUE;
+}
+
+status_t StagefrightRecorder::setParameters(const String8 &params) {
+ LOGV("setParameters: %s", params.string());
+ const char *cparams = params.string();
+ const char *key_start = cparams;
+ for (;;) {
+ const char *equal_pos = strchr(key_start, '=');
+ if (equal_pos == NULL) {
+ LOGE("Parameters %s miss a value", cparams);
+ return BAD_VALUE;
+ }
+ String8 key(key_start, equal_pos - key_start);
+ TrimString(&key);
+ if (key.length() == 0) {
+ LOGE("Parameters %s contains an empty key", cparams);
+ return BAD_VALUE;
+ }
+ const char *value_start = equal_pos + 1;
+ const char *semicolon_pos = strchr(value_start, ';');
+ String8 value;
+ if (semicolon_pos == NULL) {
+ value.setTo(value_start);
+ } else {
+ value.setTo(value_start, semicolon_pos - value_start);
+ }
+ if (setParameter(key, value) != OK) {
+ return BAD_VALUE;
+ }
+ if (semicolon_pos == NULL) {
+ break; // Reaches the end
+ }
+ key_start = semicolon_pos + 1;
+ }
+ return OK;
+}
+
+status_t StagefrightRecorder::setListener(const sp<IMediaRecorderClient> &listener) {
mListener = listener;
return OK;
@@ -144,7 +607,10 @@ status_t StagefrightRecorder::prepare() {
}
status_t StagefrightRecorder::start() {
+ CHECK(mOutputFd >= 0);
+
if (mWriter != NULL) {
+ LOGE("File writer is not avaialble");
return UNKNOWN_ERROR;
}
@@ -158,40 +624,58 @@ status_t StagefrightRecorder::start() {
case OUTPUT_FORMAT_AMR_WB:
return startAMRRecording();
+ case OUTPUT_FORMAT_AAC_ADIF:
+ case OUTPUT_FORMAT_AAC_ADTS:
+ return startAACRecording();
+
default:
+ LOGE("Unsupported output file format: %d", mOutputFormat);
return UNKNOWN_ERROR;
}
}
-sp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
- uint32_t sampleRate =
- mAudioEncoder == AUDIO_ENCODER_AMR_NB ? 8000 : 16000;
-
+sp<MediaSource> StagefrightRecorder::createAudioSource() {
sp<AudioSource> audioSource =
new AudioSource(
mAudioSource,
- sampleRate,
- AudioSystem::CHANNEL_IN_MONO);
+ mSampleRate,
+ mAudioChannels);
status_t err = audioSource->initCheck();
if (err != OK) {
+ LOGE("audio source is not initialized");
return NULL;
}
sp<MetaData> encMeta = new MetaData;
- encMeta->setCString(
- kKeyMIMEType,
- mAudioEncoder == AUDIO_ENCODER_AMR_NB
- ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);
+ const char *mime;
+ switch (mAudioEncoder) {
+ case AUDIO_ENCODER_AMR_NB:
+ case AUDIO_ENCODER_DEFAULT:
+ mime = MEDIA_MIMETYPE_AUDIO_AMR_NB;
+ break;
+ case AUDIO_ENCODER_AMR_WB:
+ mime = MEDIA_MIMETYPE_AUDIO_AMR_WB;
+ break;
+ case AUDIO_ENCODER_AAC:
+ mime = MEDIA_MIMETYPE_AUDIO_AAC;
+ break;
+ default:
+ LOGE("Unknown audio encoder: %d", mAudioEncoder);
+ return NULL;
+ }
+ encMeta->setCString(kKeyMIMEType, mime);
int32_t maxInputSize;
CHECK(audioSource->getFormat()->findInt32(
kKeyMaxInputSize, &maxInputSize));
encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
- encMeta->setInt32(kKeyChannelCount, 1);
- encMeta->setInt32(kKeySampleRate, sampleRate);
+ encMeta->setInt32(kKeyChannelCount, mAudioChannels);
+ encMeta->setInt32(kKeySampleRate, mSampleRate);
+ encMeta->setInt32(kKeyBitRate, mAudioBitRate);
+ encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
OMXClient client;
CHECK_EQ(client.connect(), OK);
@@ -199,144 +683,481 @@ sp<MediaSource> StagefrightRecorder::createAMRAudioSource() {
sp<MediaSource> audioEncoder =
OMXCodec::Create(client.interface(), encMeta,
true /* createEncoder */, audioSource);
+ mAudioSourceNode = audioSource;
return audioEncoder;
}
+status_t StagefrightRecorder::startAACRecording() {
+ CHECK(mOutputFormat == OUTPUT_FORMAT_AAC_ADIF ||
+ mOutputFormat == OUTPUT_FORMAT_AAC_ADTS);
+
+ CHECK(mAudioEncoder == AUDIO_ENCODER_AAC);
+ CHECK(mAudioSource != AUDIO_SOURCE_LIST_END);
+
+ CHECK(0 == "AACWriter is not implemented yet");
+
+ return OK;
+}
+
status_t StagefrightRecorder::startAMRRecording() {
- if (mAudioSource == AUDIO_SOURCE_LIST_END
- || mVideoSource != VIDEO_SOURCE_LIST_END) {
- return UNKNOWN_ERROR;
+ CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB ||
+ mOutputFormat == OUTPUT_FORMAT_AMR_WB);
+
+ if (mOutputFormat == OUTPUT_FORMAT_AMR_NB) {
+ if (mAudioEncoder != AUDIO_ENCODER_DEFAULT &&
+ mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
+ LOGE("Invalid encoder %d used for AMRNB recording",
+ mAudioEncoder);
+ return BAD_VALUE;
+ }
+ if (mSampleRate != 8000) {
+ LOGE("Invalid sampling rate %d used for AMRNB recording",
+ mSampleRate);
+ return BAD_VALUE;
+ }
+ } else { // mOutputFormat must be OUTPUT_FORMAT_AMR_WB
+ if (mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
+ LOGE("Invlaid encoder %d used for AMRWB recording",
+ mAudioEncoder);
+ return BAD_VALUE;
+ }
+ if (mSampleRate != 16000) {
+ LOGE("Invalid sample rate %d used for AMRWB recording",
+ mSampleRate);
+ return BAD_VALUE;
+ }
+ }
+ if (mAudioChannels != 1) {
+ LOGE("Invalid number of audio channels %d used for amr recording",
+ mAudioChannels);
+ return BAD_VALUE;
}
- if (mOutputFormat == OUTPUT_FORMAT_AMR_NB
- && mAudioEncoder != AUDIO_ENCODER_DEFAULT
- && mAudioEncoder != AUDIO_ENCODER_AMR_NB) {
- return UNKNOWN_ERROR;
- } else if (mOutputFormat == OUTPUT_FORMAT_AMR_WB
- && mAudioEncoder != AUDIO_ENCODER_AMR_WB) {
- return UNKNOWN_ERROR;
+ if (mAudioSource >= AUDIO_SOURCE_LIST_END) {
+ LOGE("Invalid audio source: %d", mAudioSource);
+ return BAD_VALUE;
}
- sp<MediaSource> audioEncoder = createAMRAudioSource();
+ sp<MediaSource> audioEncoder = createAudioSource();
if (audioEncoder == NULL) {
return UNKNOWN_ERROR;
}
- CHECK(mOutputFd >= 0);
mWriter = new AMRWriter(dup(mOutputFd));
mWriter->addSource(audioEncoder);
+
+ if (mMaxFileDurationUs != 0) {
+ mWriter->setMaxFileDuration(mMaxFileDurationUs);
+ }
+ if (mMaxFileSizeBytes != 0) {
+ mWriter->setMaxFileSize(mMaxFileSizeBytes);
+ }
+ mWriter->setListener(mListener);
mWriter->start();
return OK;
}
-status_t StagefrightRecorder::startMPEG4Recording() {
- mWriter = new MPEG4Writer(dup(mOutputFd));
+void StagefrightRecorder::clipVideoFrameRate() {
+ LOGV("clipVideoFrameRate: encoder %d", mVideoEncoder);
+ int minFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.fps.min", mVideoEncoder);
+ int maxFrameRate = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.fps.max", mVideoEncoder);
+ if (mFrameRate < minFrameRate) {
+ LOGW("Intended video encoding frame rate (%d fps) is too small"
+ " and will be set to (%d fps)", mFrameRate, minFrameRate);
+ mFrameRate = minFrameRate;
+ } else if (mFrameRate > maxFrameRate) {
+ LOGW("Intended video encoding frame rate (%d fps) is too large"
+ " and will be set to (%d fps)", mFrameRate, maxFrameRate);
+ mFrameRate = maxFrameRate;
+ }
+}
- if (mVideoSource == VIDEO_SOURCE_DEFAULT
- || mVideoSource == VIDEO_SOURCE_CAMERA) {
- CHECK(mCamera != NULL);
+void StagefrightRecorder::clipVideoBitRate() {
+ LOGV("clipVideoBitRate: encoder %d", mVideoEncoder);
+ int minBitRate = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.bps.min", mVideoEncoder);
+ int maxBitRate = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.bps.max", mVideoEncoder);
+ if (mVideoBitRate < minBitRate) {
+ LOGW("Intended video encoding bit rate (%d bps) is too small"
+ " and will be set to (%d bps)", mVideoBitRate, minBitRate);
+ mVideoBitRate = minBitRate;
+ } else if (mVideoBitRate > maxBitRate) {
+ LOGW("Intended video encoding bit rate (%d bps) is too large"
+ " and will be set to (%d bps)", mVideoBitRate, maxBitRate);
+ mVideoBitRate = maxBitRate;
+ }
+}
- sp<CameraSource> cameraSource =
- CameraSource::CreateFromICamera(mCamera);
+void StagefrightRecorder::clipVideoFrameWidth() {
+ LOGV("clipVideoFrameWidth: encoder %d", mVideoEncoder);
+ int minFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.width.min", mVideoEncoder);
+ int maxFrameWidth = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.width.max", mVideoEncoder);
+ if (mVideoWidth < minFrameWidth) {
+ LOGW("Intended video encoding frame width (%d) is too small"
+ " and will be set to (%d)", mVideoWidth, minFrameWidth);
+ mVideoWidth = minFrameWidth;
+ } else if (mVideoWidth > maxFrameWidth) {
+ LOGW("Intended video encoding frame width (%d) is too large"
+ " and will be set to (%d)", mVideoWidth, maxFrameWidth);
+ mVideoWidth = maxFrameWidth;
+ }
+}
- CHECK(cameraSource != NULL);
+status_t StagefrightRecorder::setupCameraSource() {
+ clipVideoBitRate();
+ clipVideoFrameRate();
+ clipVideoFrameWidth();
+ clipVideoFrameHeight();
+
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ if (mCamera == 0) {
+ mCamera = Camera::connect(mCameraId);
+ if (mCamera == 0) {
+ LOGE("Camera connection could not be established.");
+ return -EBUSY;
+ }
+ mFlags &= ~FLAGS_HOT_CAMERA;
+ mCamera->lock();
+ }
- cameraSource->setPreviewSurface(mPreviewSurface);
+ // Set the actual video recording frame size
+ CameraParameters params(mCamera->getParameters());
+ params.setPreviewSize(mVideoWidth, mVideoHeight);
+ params.setPreviewFrameRate(mFrameRate);
+ String8 s = params.flatten();
+ CHECK_EQ(OK, mCamera->setParameters(s));
+ CameraParameters newCameraParams(mCamera->getParameters());
+
+ // Check on video frame size
+ int frameWidth = 0, frameHeight = 0;
+ newCameraParams.getPreviewSize(&frameWidth, &frameHeight);
+ if (frameWidth < 0 || frameWidth != mVideoWidth ||
+ frameHeight < 0 || frameHeight != mVideoHeight) {
+ LOGE("Failed to set the video frame size to %dx%d",
+ mVideoWidth, mVideoHeight);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ return UNKNOWN_ERROR;
+ }
- sp<MetaData> enc_meta = new MetaData;
- switch (mVideoEncoder) {
- case VIDEO_ENCODER_H263:
- enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
- break;
+ // Check on video frame rate
+ int frameRate = newCameraParams.getPreviewFrameRate();
+ if (frameRate < 0 || (frameRate - mFrameRate) != 0) {
+ LOGE("Failed to set frame rate to %d fps. The actual "
+ "frame rate is %d", mFrameRate, frameRate);
+ }
- case VIDEO_ENCODER_MPEG_4_SP:
- enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
- break;
+ CHECK_EQ(OK, mCamera->setPreviewDisplay(mPreviewSurface));
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ return OK;
+}
- case VIDEO_ENCODER_H264:
- enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
- break;
+void StagefrightRecorder::clipVideoFrameHeight() {
+ LOGV("clipVideoFrameHeight: encoder %d", mVideoEncoder);
+ int minFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.height.min", mVideoEncoder);
+ int maxFrameHeight = mEncoderProfiles->getVideoEncoderParamByName(
+ "enc.vid.height.max", mVideoEncoder);
+ if (mVideoHeight < minFrameHeight) {
+ LOGW("Intended video encoding frame height (%d) is too small"
+ " and will be set to (%d)", mVideoHeight, minFrameHeight);
+ mVideoHeight = minFrameHeight;
+ } else if (mVideoHeight > maxFrameHeight) {
+ LOGW("Intended video encoding frame height (%d) is too large"
+ " and will be set to (%d)", mVideoHeight, maxFrameHeight);
+ mVideoHeight = maxFrameHeight;
+ }
+}
- default:
- CHECK(!"Should not be here, unsupported video encoding.");
- break;
- }
+status_t StagefrightRecorder::setupVideoEncoder(const sp<MediaWriter>& writer) {
+ status_t err = setupCameraSource();
+ if (err != OK) return err;
- sp<MetaData> meta = cameraSource->getFormat();
+ sp<CameraSource> cameraSource = CameraSource::CreateFromCamera(mCamera);
+ CHECK(cameraSource != NULL);
- int32_t width, height;
- CHECK(meta->findInt32(kKeyWidth, &width));
- CHECK(meta->findInt32(kKeyHeight, &height));
+ sp<MetaData> enc_meta = new MetaData;
+ enc_meta->setInt32(kKeyBitRate, mVideoBitRate);
+ enc_meta->setInt32(kKeySampleRate, mFrameRate);
- enc_meta->setInt32(kKeyWidth, width);
- enc_meta->setInt32(kKeyHeight, height);
+ switch (mVideoEncoder) {
+ case VIDEO_ENCODER_H263:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
+ break;
- OMXClient client;
- CHECK_EQ(client.connect(), OK);
+ case VIDEO_ENCODER_MPEG_4_SP:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ break;
- sp<MediaSource> encoder =
- OMXCodec::Create(
- client.interface(), enc_meta,
- true /* createEncoder */, cameraSource);
+ case VIDEO_ENCODER_H264:
+ enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ break;
- CHECK(mOutputFd >= 0);
- mWriter->addSource(encoder);
+ default:
+ CHECK(!"Should not be here, unsupported video encoding.");
+ break;
}
- if (mAudioSource != AUDIO_SOURCE_LIST_END) {
- sp<MediaSource> audioEncoder = createAMRAudioSource();
+ sp<MetaData> meta = cameraSource->getFormat();
+
+ int32_t width, height, stride, sliceHeight, colorFormat;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+ CHECK(meta->findInt32(kKeyStride, &stride));
+ CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight));
+ CHECK(meta->findInt32(kKeyColorFormat, &colorFormat));
+
+ enc_meta->setInt32(kKeyWidth, width);
+ enc_meta->setInt32(kKeyHeight, height);
+ enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec);
+ enc_meta->setInt32(kKeyStride, stride);
+ enc_meta->setInt32(kKeySliceHeight, sliceHeight);
+ enc_meta->setInt32(kKeyColorFormat, colorFormat);
+ enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
+ if (mVideoEncoderProfile != -1) {
+ enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
+ }
+ if (mVideoEncoderLevel != -1) {
+ enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel);
+ }
- if (audioEncoder == NULL) {
+ OMXClient client;
+ CHECK_EQ(client.connect(), OK);
+
+ sp<MediaSource> encoder = OMXCodec::Create(
+ client.interface(), enc_meta,
+ true /* createEncoder */, cameraSource);
+ if (encoder == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ writer->addSource(encoder);
+ return OK;
+}
+
+status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
+ sp<MediaSource> audioEncoder;
+ switch(mAudioEncoder) {
+ case AUDIO_ENCODER_AMR_NB:
+ case AUDIO_ENCODER_AMR_WB:
+ case AUDIO_ENCODER_AAC:
+ audioEncoder = createAudioSource();
+ break;
+ default:
+ LOGE("Unsupported audio encoder: %d", mAudioEncoder);
return UNKNOWN_ERROR;
- }
+ }
- mWriter->addSource(audioEncoder);
+ if (audioEncoder == NULL) {
+ return UNKNOWN_ERROR;
}
- mWriter->start();
+ writer->addSource(audioEncoder);
return OK;
}
-status_t StagefrightRecorder::stop() {
+status_t StagefrightRecorder::startMPEG4Recording() {
+ int32_t totalBitRate = 0;
+ status_t err = OK;
+ sp<MediaWriter> writer = new MPEG4Writer(dup(mOutputFd));
+
+ // Add audio source first if it exists
+ if (mAudioSource != AUDIO_SOURCE_LIST_END) {
+ err = setupAudioEncoder(writer);
+ if (err != OK) return err;
+ totalBitRate += mAudioBitRate;
+ }
+ if (mVideoSource == VIDEO_SOURCE_DEFAULT
+ || mVideoSource == VIDEO_SOURCE_CAMERA) {
+ err = setupVideoEncoder(writer);
+ if (err != OK) return err;
+ totalBitRate += mVideoBitRate;
+ }
+
+ if (mInterleaveDurationUs > 0) {
+ reinterpret_cast<MPEG4Writer *>(writer.get())->
+ setInterleaveDuration(mInterleaveDurationUs);
+ }
+
+ if (mMaxFileDurationUs != 0) {
+ writer->setMaxFileDuration(mMaxFileDurationUs);
+ }
+ if (mMaxFileSizeBytes != 0) {
+ writer->setMaxFileSize(mMaxFileSizeBytes);
+ }
+ sp<MetaData> meta = new MetaData;
+ meta->setInt64(kKeyTime, systemTime() / 1000);
+ meta->setInt32(kKeyFileType, mOutputFormat);
+ meta->setInt32(kKeyBitRate, totalBitRate);
+ meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
+ meta->setInt32(kKeyTimeScale, mMovieTimeScale);
+ if (mTrackEveryTimeDurationUs > 0) {
+ meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
+ }
+ writer->setListener(mListener);
+ mWriter = writer;
+ return mWriter->start(meta.get());
+}
+
+status_t StagefrightRecorder::pause() {
+ LOGV("pause");
if (mWriter == NULL) {
return UNKNOWN_ERROR;
}
+ mWriter->pause();
+ return OK;
+}
- mWriter->stop();
- mWriter = NULL;
+status_t StagefrightRecorder::stop() {
+ LOGV("stop");
+ if (mWriter != NULL) {
+ mWriter->stop();
+ mWriter.clear();
+ }
+
+ if (mCamera != 0) {
+ LOGV("Disconnect camera");
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ if ((mFlags & FLAGS_HOT_CAMERA) == 0) {
+ LOGV("Camera was cold when we started, stopping preview");
+ mCamera->stopPreview();
+ }
+ mCamera->unlock();
+ mCamera.clear();
+ IPCThreadState::self()->restoreCallingIdentity(token);
+ mFlags = 0;
+ }
return OK;
}
status_t StagefrightRecorder::close() {
+ LOGV("close");
stop();
return OK;
}
status_t StagefrightRecorder::reset() {
+ LOGV("reset");
stop();
+ // No audio or video source by default
mAudioSource = AUDIO_SOURCE_LIST_END;
mVideoSource = VIDEO_SOURCE_LIST_END;
- mOutputFormat = OUTPUT_FORMAT_LIST_END;
- mAudioEncoder = AUDIO_ENCODER_LIST_END;
- mVideoEncoder = VIDEO_ENCODER_LIST_END;
- mVideoWidth = -1;
- mVideoHeight = -1;
- mFrameRate = -1;
+
+ // Default parameters
+ mOutputFormat = OUTPUT_FORMAT_THREE_GPP;
+ mAudioEncoder = AUDIO_ENCODER_AMR_NB;
+ mVideoEncoder = VIDEO_ENCODER_H263;
+ mVideoWidth = 176;
+ mVideoHeight = 144;
+ mFrameRate = 20;
+ mVideoBitRate = 192000;
+ mSampleRate = 8000;
+ mAudioChannels = 1;
+ mAudioBitRate = 12200;
+ mInterleaveDurationUs = 0;
+ mIFramesIntervalSec = 1;
+ mAudioSourceNode = 0;
+ mUse64BitFileOffset = false;
+ mMovieTimeScale = 1000;
+ mAudioTimeScale = 1000;
+ mVideoTimeScale = 1000;
+ mCameraId = 0;
+ mVideoEncoderProfile = -1;
+ mVideoEncoderLevel = -1;
+ mMaxFileDurationUs = 0;
+ mMaxFileSizeBytes = 0;
+ mTrackEveryTimeDurationUs = 0;
+ mEncoderProfiles = MediaProfiles::getInstance();
+
mOutputFd = -1;
+ mFlags = 0;
return OK;
}
status_t StagefrightRecorder::getMaxAmplitude(int *max) {
- *max = 0;
+ LOGV("getMaxAmplitude");
+
+ if (max == NULL) {
+ LOGE("Null pointer argument");
+ return BAD_VALUE;
+ }
+
+ if (mAudioSourceNode != 0) {
+ *max = mAudioSourceNode->getMaxAmplitude();
+ } else {
+ *max = 0;
+ }
return OK;
}
+status_t StagefrightRecorder::dump(int fd, const Vector<String16>& args) const {
+ const size_t SIZE = 256;
+ char buffer[SIZE];
+ String8 result;
+ snprintf(buffer, SIZE, " Recorder: %p", this);
+ snprintf(buffer, SIZE, " Output file (fd %d):\n", mOutputFd);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " File format: %d\n", mOutputFormat);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Max file size (bytes): %lld\n", mMaxFileSizeBytes);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Max file duration (us): %lld\n", mMaxFileDurationUs);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " File offset length (bits): %d\n", mUse64BitFileOffset? 64: 32);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Interleave duration (us): %d\n", mInterleaveDurationUs);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Progress notification: %lld us\n", mTrackEveryTimeDurationUs);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Audio\n");
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Source: %d\n", mAudioSource);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Encoder: %d\n", mAudioEncoder);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mAudioBitRate);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Sampling rate (hz): %d\n", mSampleRate);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Number of channels: %d\n", mAudioChannels);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Max amplitude: %d\n", mAudioSourceNode == 0? 0: mAudioSourceNode->getMaxAmplitude());
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Video\n");
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Source: %d\n", mVideoSource);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Camera Id: %d\n", mCameraId);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Camera flags: %d\n", mFlags);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Encoder: %d\n", mVideoEncoder);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Encoder profile: %d\n", mVideoEncoderProfile);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Encoder level: %d\n", mVideoEncoderLevel);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " I frames interval (s): %d\n", mIFramesIntervalSec);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Frame size (pixels): %dx%d\n", mVideoWidth, mVideoHeight);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Frame rate (fps): %d\n", mFrameRate);
+ result.append(buffer);
+ snprintf(buffer, SIZE, " Bit rate (bps): %d\n", mVideoBitRate);
+ result.append(buffer);
+ ::write(fd, result.string(), result.size());
+ return OK;
+}
} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 7ec412d..b4c5900 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -23,8 +23,11 @@
namespace android {
+class Camera;
struct MediaSource;
struct MediaWriter;
+struct AudioSource;
+class MediaProfiles;
struct StagefrightRecorder : public MediaRecorderBase {
StagefrightRecorder();
@@ -43,33 +46,88 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual status_t setOutputFile(const char *path);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8& params);
- virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
+ virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
virtual status_t prepare();
virtual status_t start();
+ virtual status_t pause();
virtual status_t stop();
virtual status_t close();
virtual status_t reset();
virtual status_t getMaxAmplitude(int *max);
+ virtual status_t dump(int fd, const Vector<String16>& args) const;
private:
- sp<ICamera> mCamera;
+ enum CameraFlags {
+ FLAGS_SET_CAMERA = 1L << 0,
+ FLAGS_HOT_CAMERA = 1L << 1,
+ };
+
+ sp<Camera> mCamera;
sp<ISurface> mPreviewSurface;
- sp<IMediaPlayerClient> mListener;
+ sp<IMediaRecorderClient> mListener;
sp<MediaWriter> mWriter;
+ sp<AudioSource> mAudioSourceNode;
audio_source mAudioSource;
video_source mVideoSource;
output_format mOutputFormat;
audio_encoder mAudioEncoder;
video_encoder mVideoEncoder;
- int mVideoWidth, mVideoHeight;
- int mFrameRate;
+ bool mUse64BitFileOffset;
+ int32_t mVideoWidth, mVideoHeight;
+ int32_t mFrameRate;
+ int32_t mVideoBitRate;
+ int32_t mAudioBitRate;
+ int32_t mAudioChannels;
+ int32_t mSampleRate;
+ int32_t mInterleaveDurationUs;
+ int32_t mIFramesIntervalSec;
+ int32_t mCameraId;
+ int32_t mVideoEncoderProfile;
+ int32_t mVideoEncoderLevel;
+ int32_t mMovieTimeScale;
+ int32_t mVideoTimeScale;
+ int32_t mAudioTimeScale;
+ int64_t mMaxFileSizeBytes;
+ int64_t mMaxFileDurationUs;
+ int64_t mTrackEveryTimeDurationUs;
+
String8 mParams;
int mOutputFd;
+ int32_t mFlags;
+
+ MediaProfiles *mEncoderProfiles;
status_t startMPEG4Recording();
status_t startAMRRecording();
- sp<MediaSource> createAMRAudioSource();
+ status_t startAACRecording();
+ sp<MediaSource> createAudioSource();
+ status_t setupCameraSource();
+ status_t setupAudioEncoder(const sp<MediaWriter>& writer);
+ status_t setupVideoEncoder(const sp<MediaWriter>& writer);
+
+ // Encoding parameter handling utilities
+ status_t setParameter(const String8 &key, const String8 &value);
+ status_t setParamAudioEncodingBitRate(int32_t bitRate);
+ status_t setParamAudioNumberOfChannels(int32_t channles);
+ status_t setParamAudioSamplingRate(int32_t sampleRate);
+ status_t setParamAudioTimeScale(int32_t timeScale);
+ status_t setParamVideoEncodingBitRate(int32_t bitRate);
+ status_t setParamVideoIFramesInterval(int32_t seconds);
+ status_t setParamVideoEncoderProfile(int32_t profile);
+ status_t setParamVideoEncoderLevel(int32_t level);
+ status_t setParamVideoCameraId(int32_t cameraId);
+ status_t setParamVideoTimeScale(int32_t timeScale);
+ status_t setParamTrackTimeStatus(int64_t timeDurationUs);
+ status_t setParamInterleaveDuration(int32_t durationUs);
+ status_t setParam64BitFileOffset(bool use64BitFileOffset);
+ status_t setParamMaxFileDurationUs(int64_t timeUs);
+ status_t setParamMaxFileSizeBytes(int64_t bytes);
+ status_t setParamMovieTimeScale(int32_t timeScale);
+ void clipVideoBitRate();
+ void clipVideoFrameRate();
+ void clipVideoFrameWidth();
+ void clipVideoFrameHeight();
StagefrightRecorder(const StagefrightRecorder &);
StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
deleted file mode 100644
index eac74fc..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
-**
-** Copyright 2009, 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.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisMetadataRetriever"
-#include <utils/Log.h>
-
-#include "VorbisMetadataRetriever.h"
-#include <media/mediametadataretriever.h>
-#
-
-namespace android {
-
-void VorbisMetadataRetriever::clearMetadataValues()
-{
- LOGV("cleearMetadataValues");
- mMetadataValues[0][0] = '\0';
-}
-
-status_t VorbisMetadataRetriever::setDataSource(const char *url)
-{
- LOGV("setDataSource: url(%s)", url? url: "NULL pointer");
- Mutex::Autolock lock(mLock);
- clearMetadataValues();
- if (mVorbisPlayer == 0) {
- mVorbisPlayer = new VorbisPlayer();
- }
- // TODO: support headers in MetadataRetriever interface!
- return mVorbisPlayer->setDataSource(url, NULL /* headers */);
-}
-
-status_t VorbisMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
-{
- LOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
- Mutex::Autolock lock(mLock);
- clearMetadataValues();
- if (mVorbisPlayer == 0) {
- mVorbisPlayer = new VorbisPlayer();
- }
- return mVorbisPlayer->setDataSource(fd, offset, length);
-}
-
-const char* VorbisMetadataRetriever::extractMetadata(int keyCode)
-{
- LOGV("extractMetadata: key(%d)", keyCode);
- Mutex::Autolock lock(mLock);
- if (mVorbisPlayer == 0 || mVorbisPlayer->initCheck() != NO_ERROR) {
- LOGE("no vorbis player is initialized yet");
- return NULL;
- }
- switch (keyCode) {
- case METADATA_KEY_DURATION:
- {
- if (mMetadataValues[0][0] == '\0') {
- int duration = -1;
- if (mVorbisPlayer->getDuration(&duration) != NO_ERROR) {
- LOGE("failed to get duration");
- return NULL;
- }
- snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
- }
- LOGV("duration: %s ms", mMetadataValues[0]);
- return mMetadataValues[0];
- }
- default:
- LOGE("Unsupported key code (%d)", keyCode);
- return NULL;
- }
- return NULL;
-}
-
-};
-
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.h b/media/libmediaplayerservice/VorbisMetadataRetriever.h
deleted file mode 100644
index 1c57fe3..0000000
--- a/media/libmediaplayerservice/VorbisMetadataRetriever.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-**
-** Copyright 2009, 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.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_VORBISMETADATARETRIEVER_H
-#define ANDROID_VORBISMETADATARETRIEVER_H
-
-#include <utils/threads.h>
-#include <utils/Errors.h>
-#include <media/MediaMetadataRetrieverInterface.h>
-
-#include "VorbisPlayer.h"
-
-namespace android {
-
-class VorbisMetadataRetriever : public MediaMetadataRetrieverInterface {
-public:
- VorbisMetadataRetriever() {}
- ~VorbisMetadataRetriever() {}
-
- virtual status_t setDataSource(const char *url);
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual const char* extractMetadata(int keyCode);
-
-private:
- static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
- void clearMetadataValues();
-
- Mutex mLock;
- sp<VorbisPlayer> mVorbisPlayer;
- char mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
deleted file mode 100644
index 8181999..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
-** Copyright 2007, 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.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "VorbisPlayer"
-#include "utils/Log.h"
-
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-
-#include "VorbisPlayer.h"
-
-#ifdef HAVE_GETTID
-static pid_t myTid() { return gettid(); }
-#else
-static pid_t myTid() { return getpid(); }
-#endif
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-// TODO: Determine appropriate return codes
-static status_t ERROR_NOT_OPEN = -1;
-static status_t ERROR_OPEN_FAILED = -2;
-static status_t ERROR_ALLOCATE_FAILED = -4;
-static status_t ERROR_NOT_SUPPORTED = -8;
-static status_t ERROR_NOT_READY = -16;
-static status_t STATE_INIT = 0;
-static status_t STATE_ERROR = 1;
-static status_t STATE_OPEN = 2;
-
-
-VorbisPlayer::VorbisPlayer() :
- mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
- mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
- mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
-{
- LOGV("constructor\n");
- memset(&mVorbisFile, 0, sizeof mVorbisFile);
-}
-
-void VorbisPlayer::onFirstRef()
-{
- LOGV("onFirstRef");
- // create playback thread
- Mutex::Autolock l(mMutex);
- createThreadEtc(renderThread, this, "vorbis decoder", ANDROID_PRIORITY_AUDIO);
- mCondition.wait(mMutex);
- if (mRenderTid > 0) {
- LOGV("render thread(%d) started", mRenderTid);
- mState = STATE_INIT;
- }
-}
-
-status_t VorbisPlayer::initCheck()
-{
- if (mState != STATE_ERROR) return NO_ERROR;
- return ERROR_NOT_READY;
-}
-
-VorbisPlayer::~VorbisPlayer() {
- LOGV("VorbisPlayer destructor\n");
- release();
-}
-
-status_t VorbisPlayer::setDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers) {
- return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
-}
-
-status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length)
-{
- return setdatasource(NULL, fd, offset, length);
-}
-
-size_t VorbisPlayer::vp_fread(void *buf, size_t size, size_t nmemb, void *me) {
- VorbisPlayer *self = (VorbisPlayer*) me;
-
- long curpos = vp_ftell(me);
- while (nmemb != 0 && (curpos + size * nmemb) > self->mLength) {
- nmemb--;
- }
- return fread(buf, size, nmemb, self->mFile);
-}
-
-int VorbisPlayer::vp_fseek(void *me, ogg_int64_t off, int whence) {
- VorbisPlayer *self = (VorbisPlayer*) me;
- if (whence == SEEK_SET)
- return fseek(self->mFile, off + self->mOffset, whence);
- else if (whence == SEEK_CUR)
- return fseek(self->mFile, off, whence);
- else if (whence == SEEK_END)
- return fseek(self->mFile, self->mOffset + self->mLength + off, SEEK_SET);
- return -1;
-}
-
-int VorbisPlayer::vp_fclose(void *me) {
- LOGV("vp_fclose");
- VorbisPlayer *self = (VorbisPlayer*) me;
- int ret = fclose (self->mFile);
- self->mFile = NULL;
- return ret;
-}
-
-long VorbisPlayer::vp_ftell(void *me) {
- VorbisPlayer *self = (VorbisPlayer*) me;
- return ftell(self->mFile) - self->mOffset;
-}
-
-status_t VorbisPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
-{
- LOGV("setDataSource url=%s, fd=%d\n", path, fd);
-
- // file still open?
- Mutex::Autolock l(mMutex);
- if (mState == STATE_OPEN) {
- reset_nosync();
- }
-
- // open file and set paused state
- if (path) {
- mFile = fopen(path, "r");
- } else {
- mFile = fdopen(dup(fd), "r");
- }
- if (mFile == NULL) {
- return ERROR_OPEN_FAILED;
- }
-
- struct stat sb;
- int ret;
- if (path) {
- ret = stat(path, &sb);
- } else {
- ret = fstat(fd, &sb);
- }
- if (ret != 0) {
- mState = STATE_ERROR;
- fclose(mFile);
- return ERROR_OPEN_FAILED;
- }
- if (sb.st_size > (length + offset)) {
- mLength = length;
- } else {
- mLength = sb.st_size - offset;
- }
-
- ov_callbacks callbacks = {
- (size_t (*)(void *, size_t, size_t, void *)) vp_fread,
- (int (*)(void *, ogg_int64_t, int)) vp_fseek,
- (int (*)(void *)) vp_fclose,
- (long (*)(void *)) vp_ftell
- };
-
- mOffset = offset;
- fseek(mFile, offset, SEEK_SET);
-
- int result = ov_open_callbacks(this, &mVorbisFile, NULL, 0, callbacks);
- if (result < 0) {
- LOGE("ov_open() failed: [%d]\n", (int)result);
- mState = STATE_ERROR;
- fclose(mFile);
- return ERROR_OPEN_FAILED;
- }
-
- // look for the android loop tag (for ringtones)
- char **ptr = ov_comment(&mVorbisFile,-1)->user_comments;
- while(*ptr) {
- // does the comment start with ANDROID_LOOP_TAG
- if(strncmp(*ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
- // read the value of the tag
- char *val = *ptr + strlen(ANDROID_LOOP_TAG) + 1;
- mAndroidLoop = (strncmp(val, "true", 4) == 0);
- }
- // we keep parsing even after finding one occurence of ANDROID_LOOP_TAG,
- // as we could find another one (the tag might have been appended more than once).
- ++ptr;
- }
- LOGV_IF(mAndroidLoop, "looped sound");
-
- mState = STATE_OPEN;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepare()
-{
- LOGV("prepare\n");
- if (mState != STATE_OPEN ) {
- return ERROR_NOT_OPEN;
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::prepareAsync() {
- LOGV("prepareAsync\n");
- // can't hold the lock here because of the callback
- // it's safe because we don't change state
- if (mState != STATE_OPEN ) {
- sendEvent(MEDIA_ERROR);
- return NO_ERROR;
- }
- sendEvent(MEDIA_PREPARED);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::start()
-{
- LOGV("start\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- mPaused = false;
- mRender = true;
-
- // wake up render thread
- LOGV(" wakeup render thread\n");
- mCondition.signal();
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::stop()
-{
- LOGV("stop\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
- mPaused = true;
- mRender = false;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::seekTo(int position)
-{
- LOGV("seekTo %d\n", position);
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- int result = ov_time_seek(&mVorbisFile, position);
- if (result != 0) {
- LOGE("ov_time_seek() returned %d\n", result);
- return result;
- }
- sendEvent(MEDIA_SEEK_COMPLETE);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::pause()
-{
- LOGV("pause\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
- mPaused = true;
- return NO_ERROR;
-}
-
-bool VorbisPlayer::isPlaying()
-{
- LOGV("isPlaying\n");
- if (mState == STATE_OPEN) {
- return mRender;
- }
- return false;
-}
-
-status_t VorbisPlayer::getCurrentPosition(int* position)
-{
- LOGV("getCurrentPosition\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- LOGE("getCurrentPosition(): file not open");
- return ERROR_NOT_OPEN;
- }
- *position = ov_time_tell(&mVorbisFile);
- if (*position < 0) {
- LOGE("getCurrentPosition(): ov_time_tell returned %d", *position);
- return *position;
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::getDuration(int* duration)
-{
- LOGV("getDuration\n");
- Mutex::Autolock l(mMutex);
- if (mState != STATE_OPEN) {
- return ERROR_NOT_OPEN;
- }
-
- int ret = ov_time_total(&mVorbisFile, -1);
- if (ret == OV_EINVAL) {
- return -1;
- }
-
- *duration = ret;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::release()
-{
- LOGV("release\n");
- Mutex::Autolock l(mMutex);
- reset_nosync();
-
- // TODO: timeout when thread won't exit
- // wait for render thread to exit
- if (mRenderTid > 0) {
- mExit = true;
- mCondition.signal();
- mCondition.wait(mMutex);
- }
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::reset()
-{
- LOGV("reset\n");
- Mutex::Autolock l(mMutex);
- return reset_nosync();
-}
-
-// always call with lock held
-status_t VorbisPlayer::reset_nosync()
-{
- // close file
- if (mFile != NULL) {
- ov_clear(&mVorbisFile); // this also closes the FILE
- if (mFile != NULL) {
- LOGV("OOPS! Vorbis didn't close the file");
- fclose(mFile);
- mFile = NULL;
- }
- }
- mState = STATE_ERROR;
-
- mPlayTime = -1;
- mDuration = -1;
- mLoop = false;
- mAndroidLoop = false;
- mPaused = false;
- mRender = false;
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::setLooping(int loop)
-{
- LOGV("setLooping\n");
- Mutex::Autolock l(mMutex);
- mLoop = (loop != 0);
- return NO_ERROR;
-}
-
-status_t VorbisPlayer::createOutputTrack() {
- // open audio track
- vorbis_info *vi = ov_info(&mVorbisFile, -1);
-
- LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
- vi->rate, vi->channels);
- if (mAudioSink->open(vi->rate, vi->channels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
- LOGE("mAudioSink open failed");
- return ERROR_OPEN_FAILED;
- }
- return NO_ERROR;
-}
-
-int VorbisPlayer::renderThread(void* p) {
- return ((VorbisPlayer*)p)->render();
-}
-
-#define AUDIOBUFFER_SIZE 4096
-
-int VorbisPlayer::render() {
- int result = -1;
- int temp;
- int current_section = 0;
- bool audioStarted = false;
-
- LOGV("render\n");
-
- // allocate render buffer
- mAudioBuffer = new char[AUDIOBUFFER_SIZE];
- if (!mAudioBuffer) {
- LOGE("mAudioBuffer allocate failed\n");
- goto threadExit;
- }
-
- // let main thread know we're ready
- {
- Mutex::Autolock l(mMutex);
- mRenderTid = myTid();
- mCondition.signal();
- }
-
- while (1) {
- long numread = 0;
- {
- Mutex::Autolock l(mMutex);
-
- // pausing?
- if (mPaused) {
- if (mAudioSink->ready()) mAudioSink->pause();
- mRender = false;
- audioStarted = false;
- }
-
- // nothing to render, wait for client thread to wake us up
- if (!mExit && !mRender) {
- LOGV("render - signal wait\n");
- mCondition.wait(mMutex);
- LOGV("render - signal rx'd\n");
- }
- if (mExit) break;
-
- // We could end up here if start() is called, and before we get a
- // chance to run, the app calls stop() or reset(). Re-check render
- // flag so we don't try to render in stop or reset state.
- if (!mRender) continue;
-
- // render vorbis data into the input buffer
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
- if (numread == 0) {
- // end of file, do we need to loop?
- // ...
- if (mLoop || mAndroidLoop) {
- ov_time_seek(&mVorbisFile, 0);
- current_section = 0;
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
- } else {
- mAudioSink->stop();
- audioStarted = false;
- mRender = false;
- mPaused = true;
- int endpos = ov_time_tell(&mVorbisFile);
-
- LOGV("send MEDIA_PLAYBACK_COMPLETE");
- sendEvent(MEDIA_PLAYBACK_COMPLETE);
-
- // wait until we're started again
- LOGV("playback complete - wait for signal");
- mCondition.wait(mMutex);
- LOGV("playback complete - signal rx'd");
- if (mExit) break;
-
- // if we're still at the end, restart from the beginning
- if (mState == STATE_OPEN) {
- int curpos = ov_time_tell(&mVorbisFile);
- if (curpos == endpos) {
- ov_time_seek(&mVorbisFile, 0);
- }
- current_section = 0;
- numread = ov_read(&mVorbisFile, mAudioBuffer, AUDIOBUFFER_SIZE, &current_section);
- }
- }
- }
- }
-
- // codec returns negative number on error
- if (numread < 0) {
- LOGE("Error in Vorbis decoder");
- sendEvent(MEDIA_ERROR);
- break;
- }
-
- // create audio output track if necessary
- if (!mAudioSink->ready()) {
- LOGV("render - create output track\n");
- if (createOutputTrack() != NO_ERROR)
- break;
- }
-
- // Write data to the audio hardware
- if ((temp = mAudioSink->write(mAudioBuffer, numread)) < 0) {
- LOGE("Error in writing:%d",temp);
- result = temp;
- break;
- }
-
- // start audio output if necessary
- if (!audioStarted && !mPaused && !mExit) {
- LOGV("render - starting audio\n");
- mAudioSink->start();
- audioStarted = true;
- }
- }
-
-threadExit:
- mAudioSink.clear();
- if (mAudioBuffer) {
- delete [] mAudioBuffer;
- mAudioBuffer = NULL;
- }
-
- // tell main thread goodbye
- Mutex::Autolock l(mMutex);
- mRenderTid = -1;
- mCondition.signal();
- return result;
-}
-
-} // end namespace android
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
deleted file mode 100644
index 4a50835..0000000
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-**
-** Copyright 2008, 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.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_VORBISPLAYER_H
-#define ANDROID_VORBISPLAYER_H
-
-#include <utils/threads.h>
-
-#include <media/MediaPlayerInterface.h>
-#include <media/AudioTrack.h>
-
-#include "ivorbiscodec.h"
-#include "ivorbisfile.h"
-
-#define ANDROID_LOOP_TAG "ANDROID_LOOP"
-
-namespace android {
-
-class VorbisPlayer : public MediaPlayerInterface {
-public:
- VorbisPlayer();
- ~VorbisPlayer();
-
- virtual void onFirstRef();
- virtual status_t initCheck();
-
- virtual status_t setDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers);
-
- virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
- virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
- virtual status_t prepare();
- virtual status_t prepareAsync();
- virtual status_t start();
- virtual status_t stop();
- virtual status_t seekTo(int msec);
- virtual status_t pause();
- virtual bool isPlaying();
- virtual status_t getCurrentPosition(int* msec);
- virtual status_t getDuration(int* msec);
- virtual status_t release();
- virtual status_t reset();
- virtual status_t setLooping(int loop);
- virtual player_type playerType() { return VORBIS_PLAYER; }
- virtual status_t invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
-
-private:
- status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length);
- status_t reset_nosync();
- status_t createOutputTrack();
- static int renderThread(void*);
- int render();
-
- static size_t vp_fread(void *, size_t, size_t, void *);
- static int vp_fseek(void *, ogg_int64_t, int);
- static int vp_fclose(void *);
- static long vp_ftell(void *);
-
- Mutex mMutex;
- Condition mCondition;
- FILE* mFile;
- int64_t mOffset;
- int64_t mLength;
- OggVorbis_File mVorbisFile;
- char* mAudioBuffer;
- int mPlayTime;
- int mDuration;
- status_t mState;
- int mStreamType;
- bool mLoop;
- bool mAndroidLoop;
- volatile bool mExit;
- bool mPaused;
- volatile bool mRender;
- pid_t mRenderTid;
-};
-
-}; // namespace android
-
-#endif // ANDROID_VORBISPLAYER_H
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 0fea72e..9fc1d27 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -212,7 +212,8 @@ status_t AMRSource::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame.
mCurrentTimeUs = seekFrame * 20000ll;
mOffset = seekFrame * mFrameSize + (mIsWide ? 9 : 6);
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index bf4424b..c71743e 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -22,19 +22,24 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
+#include <media/mediarecorder.h>
namespace android {
AMRWriter::AMRWriter(const char *filename)
: mFile(fopen(filename, "wb")),
mInitCheck(mFile != NULL ? OK : NO_INIT),
- mStarted(false) {
+ mStarted(false),
+ mPaused(false),
+ mResumed(false) {
}
AMRWriter::AMRWriter(int fd)
: mFile(fdopen(fd, "wb")),
mInitCheck(mFile != NULL ? OK : NO_INIT),
- mStarted(false) {
+ mStarted(false),
+ mPaused(false),
+ mResumed(false) {
}
AMRWriter::~AMRWriter() {
@@ -53,8 +58,6 @@ status_t AMRWriter::initCheck() const {
}
status_t AMRWriter::addSource(const sp<MediaSource> &source) {
- Mutex::Autolock autoLock(mLock);
-
if (mInitCheck != OK) {
return mInitCheck;
}
@@ -94,17 +97,24 @@ status_t AMRWriter::addSource(const sp<MediaSource> &source) {
return OK;
}
-status_t AMRWriter::start() {
- Mutex::Autolock autoLock(mLock);
-
+status_t AMRWriter::start(MetaData *params) {
if (mInitCheck != OK) {
return mInitCheck;
}
- if (mStarted || mSource == NULL) {
+ if (mSource == NULL) {
return UNKNOWN_ERROR;
}
+ if (mStarted && mPaused) {
+ mPaused = false;
+ mResumed = true;
+ return OK;
+ } else if (mStarted) {
+ // Already started, does nothing
+ return OK;
+ }
+
status_t err = mSource->start();
if (err != OK) {
@@ -126,17 +136,20 @@ status_t AMRWriter::start() {
return OK;
}
-void AMRWriter::stop() {
- {
- Mutex::Autolock autoLock(mLock);
-
- if (!mStarted) {
- return;
- }
+void AMRWriter::pause() {
+ if (!mStarted) {
+ return;
+ }
+ mPaused = true;
+}
- mDone = true;
+void AMRWriter::stop() {
+ if (!mStarted) {
+ return;
}
+ mDone = true;
+
void *dummy;
pthread_join(mThread, &dummy);
@@ -145,6 +158,20 @@ void AMRWriter::stop() {
mStarted = false;
}
+bool AMRWriter::exceedsFileSizeLimit() {
+ if (mMaxFileSizeLimitBytes == 0) {
+ return false;
+ }
+ return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes;
+}
+
+bool AMRWriter::exceedsFileDurationLimit() {
+ if (mMaxFileDurationLimitUs == 0) {
+ return false;
+ }
+ return mEstimatedDurationUs >= mMaxFileDurationLimitUs;
+}
+
// static
void *AMRWriter::ThreadWrapper(void *me) {
static_cast<AMRWriter *>(me)->threadFunc();
@@ -153,13 +180,13 @@ void *AMRWriter::ThreadWrapper(void *me) {
}
void AMRWriter::threadFunc() {
- for (;;) {
- Mutex::Autolock autoLock(mLock);
-
- if (mDone) {
- break;
- }
+ mEstimatedDurationUs = 0;
+ mEstimatedSizeBytes = 0;
+ bool stoppedPrematurely = true;
+ int64_t previousPausedDurationUs = 0;
+ int64_t maxTimestampUs = 0;
+ while (!mDone) {
MediaBuffer *buffer;
status_t err = mSource->read(&buffer);
@@ -167,6 +194,42 @@ void AMRWriter::threadFunc() {
break;
}
+ if (mPaused) {
+ buffer->release();
+ buffer = NULL;
+ continue;
+ }
+
+ mEstimatedSizeBytes += buffer->range_length();
+ if (exceedsFileSizeLimit()) {
+ buffer->release();
+ buffer = NULL;
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+ break;
+ }
+
+ int64_t timestampUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+ if (timestampUs > mEstimatedDurationUs) {
+ mEstimatedDurationUs = timestampUs;
+ }
+ if (mResumed) {
+ previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
+ mResumed = false;
+ }
+ timestampUs -= previousPausedDurationUs;
+ LOGV("time stamp: %lld, previous paused duration: %lld",
+ timestampUs, previousPausedDurationUs);
+ if (timestampUs > maxTimestampUs) {
+ maxTimestampUs = timestampUs;
+ }
+
+ if (exceedsFileDurationLimit()) {
+ buffer->release();
+ buffer = NULL;
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+ break;
+ }
ssize_t n = fwrite(
(const uint8_t *)buffer->data() + buffer->range_offset(),
1,
@@ -180,16 +243,26 @@ void AMRWriter::threadFunc() {
break;
}
+ // XXX: How to tell it is stopped prematurely?
+ if (stoppedPrematurely) {
+ stoppedPrematurely = false;
+ }
+
buffer->release();
buffer = NULL;
}
- Mutex::Autolock autoLock(mLock);
+ if (stoppedPrematurely) {
+ notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
+ }
+
+ fflush(mFile);
+ fclose(mFile);
+ mFile = NULL;
mReachedEOS = true;
}
bool AMRWriter::reachedEOS() {
- Mutex::Autolock autoLock(mLock);
return mReachedEOS;
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 81f995b..89bfc1f 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -1,51 +1,46 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES:= \
- ESDS.cpp \
- MediaBuffer.cpp \
- MediaBufferGroup.cpp \
- MediaDefs.cpp \
- MediaSource.cpp \
- MetaData.cpp \
- OMXCodec.cpp \
- Utils.cpp \
- OMXClient.cpp
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_SRC_FILES += \
- AMRExtractor.cpp \
- AMRWriter.cpp \
- AudioPlayer.cpp \
- AudioSource.cpp \
- AwesomePlayer.cpp \
- CachingDataSource.cpp \
- CameraSource.cpp \
- DataSource.cpp \
- FileSource.cpp \
- HTTPDataSource.cpp \
- HTTPStream.cpp \
- JPEGSource.cpp \
- MP3Extractor.cpp \
- MPEG4Extractor.cpp \
- MPEG4Writer.cpp \
- MediaExtractor.cpp \
- OggExtractor.cpp \
- Prefetcher.cpp \
- SampleIterator.cpp \
- SampleTable.cpp \
- ShoutcastSource.cpp \
- StagefrightMediaScanner.cpp \
- StagefrightMetadataRetriever.cpp \
- TimeSource.cpp \
- TimedEventQueue.cpp \
- WAVExtractor.cpp \
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+LOCAL_SRC_FILES:= \
+ AMRExtractor.cpp \
+ AMRWriter.cpp \
+ AudioPlayer.cpp \
+ AudioSource.cpp \
+ AwesomePlayer.cpp \
+ CameraSource.cpp \
+ DataSource.cpp \
+ ESDS.cpp \
+ FileSource.cpp \
+ HTTPStream.cpp \
+ JPEGSource.cpp \
+ MP3Extractor.cpp \
+ MPEG4Extractor.cpp \
+ MPEG4Writer.cpp \
+ MediaBuffer.cpp \
+ MediaBufferGroup.cpp \
+ MediaDefs.cpp \
+ MediaExtractor.cpp \
+ MediaSource.cpp \
+ MetaData.cpp \
+ NuCachedSource2.cpp \
+ NuHTTPDataSource.cpp \
+ OMXClient.cpp \
+ OMXCodec.cpp \
+ OggExtractor.cpp \
+ SampleIterator.cpp \
+ SampleTable.cpp \
+ ShoutcastSource.cpp \
+ StagefrightMediaScanner.cpp \
+ StagefrightMetadataRetriever.cpp \
+ ThrottledSource.cpp \
+ TimeSource.cpp \
+ TimedEventQueue.cpp \
+ Utils.cpp \
+ WAVExtractor.cpp \
string.cpp
-LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT
-endif
-
LOCAL_C_INCLUDES:= \
$(JNI_H_INCLUDE) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
@@ -65,24 +60,30 @@ LOCAL_SHARED_LIBRARIES := \
LOCAL_STATIC_LIBRARIES := \
libstagefright_aacdec \
+ libstagefright_aacenc \
libstagefright_amrnbdec \
libstagefright_amrnbenc \
libstagefright_amrwbdec \
+ libstagefright_amrwbenc \
libstagefright_avcdec \
+ libstagefright_avcenc \
libstagefright_m4vh263dec \
+ libstagefright_m4vh263enc \
libstagefright_mp3dec \
- libstagefright_vorbisdec
+ libstagefright_vorbisdec \
+ libstagefright_matroska \
+ libstagefright_vpxdec \
+ libvpx \
+ libstagefright_mpeg2ts \
+ libstagefright_httplive \
+ libstagefright_rtsp \
+ libstagefright_id3 \
LOCAL_SHARED_LIBRARIES += \
libstagefright_amrnb_common \
- libstagefright_avc_common
-
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
-LOCAL_STATIC_LIBRARIES += \
- libstagefright_id3
-
-LOCAL_SHARED_LIBRARIES += \
+ libstagefright_enc_common \
+ libstagefright_avc_common \
+ libstagefright_foundation \
libstagefright_color_conversion
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
@@ -95,8 +96,6 @@ ifneq ($(TARGET_SIMULATOR),true)
LOCAL_SHARED_LIBRARIES += libdl
endif
-endif
-
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
LOCAL_LDLIBS += -lpthread
endif
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index bcf2463..c27cfc8 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
@@ -41,6 +42,9 @@ AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
mReachedEOS(false),
mFinalStatus(OK),
mStarted(false),
+ mIsFirstBuffer(false),
+ mFirstBufferResult(OK),
+ mFirstBuffer(NULL),
mAudioSink(audioSink) {
}
@@ -68,6 +72,24 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
}
}
+ // We allow an optional INFO_FORMAT_CHANGED at the very beginning
+ // of playback, if there is one, getFormat below will retrieve the
+ // updated format, if there isn't, we'll stash away the valid buffer
+ // of data to be used on the first audio callback.
+
+ CHECK(mFirstBuffer == NULL);
+
+ mFirstBufferResult = mSource->read(&mFirstBuffer);
+ if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+ LOGV("INFO_FORMAT_CHANGED!!!");
+
+ CHECK(mFirstBuffer == NULL);
+ mFirstBufferResult = OK;
+ mIsFirstBuffer = false;
+ } else {
+ mIsFirstBuffer = true;
+ }
+
sp<MetaData> format = mSource->getFormat();
const char *mime;
bool success = format->findCString(kKeyMIMEType, &mime);
@@ -87,7 +109,14 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
DEFAULT_AUDIOSINK_BUFFERCOUNT,
&AudioPlayer::AudioSinkCallback, this);
if (err != OK) {
- mSource->stop();
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
+ if (!sourceAlreadyStarted) {
+ mSource->stop();
+ }
return err;
}
@@ -108,7 +137,14 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
delete mAudioTrack;
mAudioTrack = NULL;
- mSource->stop();
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
+ if (!sourceAlreadyStarted) {
+ mSource->stop();
+ }
return err;
}
@@ -159,6 +195,12 @@ void AudioPlayer::stop() {
// Make sure to release any buffer we hold onto so that the
// source is able to stop().
+
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
if (mInputBuffer != NULL) {
LOGV("AudioPlayer releasing input buffer.");
@@ -243,6 +285,14 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
if (mSeeking) {
+ if (mIsFirstBuffer) {
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+ mIsFirstBuffer = false;
+ }
+
options.setSeekTo(mSeekTimeUs);
if (mInputBuffer != NULL) {
@@ -255,7 +305,17 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
}
if (mInputBuffer == NULL) {
- status_t err = mSource->read(&mInputBuffer, &options);
+ status_t err;
+
+ if (mIsFirstBuffer) {
+ mInputBuffer = mFirstBuffer;
+ mFirstBuffer = NULL;
+ err = mFirstBufferResult;
+
+ mIsFirstBuffer = false;
+ } else {
+ err = mSource->read(&mInputBuffer, &options);
+ }
CHECK((err == OK && mInputBuffer != NULL)
|| (err != OK && mInputBuffer == NULL));
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index edabaf9..50c0edc 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioSource"
+#include <utils/Log.h>
+
#include <media/stagefright/AudioSource.h>
#include <media/AudioRecord.h>
@@ -21,16 +25,33 @@
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
+#include <cutils/properties.h>
+#include <sys/time.h>
+#include <time.h>
namespace android {
AudioSource::AudioSource(
int inputSource, uint32_t sampleRate, uint32_t channels)
- : mRecord(new AudioRecord(
- inputSource, sampleRate, AudioSystem::PCM_16_BIT, channels)),
- mInitCheck(mRecord->initCheck()),
- mStarted(false),
+ : mStarted(false),
+ mCollectStats(false),
+ mTotalReadTimeUs(0),
+ mTotalReadBytes(0),
+ mTotalReads(0),
mGroup(NULL) {
+
+ LOGV("sampleRate: %d, channels: %d", sampleRate, channels);
+ uint32_t flags = AudioRecord::RECORD_AGC_ENABLE |
+ AudioRecord::RECORD_NS_ENABLE |
+ AudioRecord::RECORD_IIR_ENABLE;
+
+ mRecord = new AudioRecord(
+ inputSource, sampleRate, AudioSystem::PCM_16_BIT,
+ channels > 1? AudioSystem::CHANNEL_IN_STEREO: AudioSystem::CHANNEL_IN_MONO,
+ 4 * kMaxBufferSize / sizeof(int16_t), /* Enable ping-pong buffers */
+ flags);
+
+ mInitCheck = mRecord->initCheck();
}
AudioSource::~AudioSource() {
@@ -51,6 +72,19 @@ status_t AudioSource::start(MetaData *params) {
return UNKNOWN_ERROR;
}
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-stats", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ mCollectStats = true;
+ }
+
+ mTrackMaxAmplitude = false;
+ mMaxAmplitude = 0;
+ mStartTimeUs = 0;
+ int64_t startTimeUs;
+ if (params && params->findInt64(kKeyTime, &startTimeUs)) {
+ mStartTimeUs = startTimeUs;
+ }
status_t err = mRecord->start();
if (err == OK) {
@@ -75,6 +109,13 @@ status_t AudioSource::stop() {
mStarted = false;
+ if (mCollectStats) {
+ LOGI("%lld reads: %.2f bps in %lld us",
+ mTotalReads,
+ (mTotalReadBytes * 8000000.0) / mTotalReadTimeUs,
+ mTotalReadTimeUs);
+ }
+
return OK;
}
@@ -91,32 +132,105 @@ sp<MetaData> AudioSource::getFormat() {
status_t AudioSource::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
+ ++mTotalReads;
MediaBuffer *buffer;
CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
- uint32_t numFramesRecorded;
- mRecord->getPosition(&numFramesRecorded);
-
- buffer->meta_data()->setInt64(
- kKeyTime,
- (1000000ll * numFramesRecorded) / mRecord->getSampleRate()
- - mRecord->latency() * 1000);
-
- ssize_t n = mRecord->read(buffer->data(), buffer->size());
-
- if (n < 0) {
- buffer->release();
- buffer = NULL;
-
- return (status_t)n;
+ while (mStarted) {
+ uint32_t numFramesRecorded;
+ mRecord->getPosition(&numFramesRecorded);
+ int64_t latency = mRecord->latency() * 1000;
+
+ int64_t readTime = systemTime() / 1000;
+
+ if (numFramesRecorded == 0) {
+ // Initial delay
+ if (mStartTimeUs > 0) {
+ mStartTimeUs = readTime - mStartTimeUs;
+ } else {
+ mStartTimeUs += latency;
+ }
+ }
+
+ ssize_t n = 0;
+ if (mCollectStats) {
+ n = mRecord->read(buffer->data(), buffer->size());
+ int64_t endTime = systemTime() / 1000;
+ mTotalReadTimeUs += (endTime - readTime);
+ if (n >= 0) {
+ mTotalReadBytes += n;
+ }
+ } else {
+ n = mRecord->read(buffer->data(), buffer->size());
+ }
+
+ if (n < 0) {
+ buffer->release();
+ buffer = NULL;
+
+ return (status_t)n;
+ }
+
+ uint32_t sampleRate = mRecord->getSampleRate();
+ int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate +
+ mStartTimeUs;
+ int64_t skipFrameUs;
+ if (!options || !options->getSkipFrame(&skipFrameUs)) {
+ skipFrameUs = timestampUs; // Don't skip frame
+ }
+
+ if (skipFrameUs > timestampUs) {
+ // Safe guard against the abuse of the kSkipFrame_Option.
+ if (skipFrameUs - timestampUs >= 1E6) {
+ LOGE("Frame skipping requested is way too long: %lld us",
+ skipFrameUs - timestampUs);
+ buffer->release();
+ return UNKNOWN_ERROR;
+ }
+ LOGV("skipFrame: %lld us > timestamp: %lld us, samples %d",
+ skipFrameUs, timestampUs, numFramesRecorded);
+ continue;
+ }
+
+ if (mTrackMaxAmplitude) {
+ trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
+ }
+
+ buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+ LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
+ mStartTimeUs, sampleRate, timestampUs);
+
+ buffer->set_range(0, n);
+
+ *out = buffer;
+ return OK;
}
- buffer->set_range(0, n);
+ return OK;
+}
- *out = buffer;
+void AudioSource::trackMaxAmplitude(int16_t *data, int nSamples) {
+ for (int i = nSamples; i > 0; --i) {
+ int16_t value = *data++;
+ if (value < 0) {
+ value = -value;
+ }
+ if (mMaxAmplitude < value) {
+ mMaxAmplitude = value;
+ }
+ }
+}
- return OK;
+int16_t AudioSource::getMaxAmplitude() {
+ // First call activates the tracking.
+ if (!mTrackMaxAmplitude) {
+ mTrackMaxAmplitude = true;
+ }
+ int16_t value = mMaxAmplitude;
+ mMaxAmplitude = 0;
+ LOGV("max amplitude since last call: %d", value);
+ return value;
}
} // namespace android
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 274dad9..236a62b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -20,13 +20,15 @@
#include <dlfcn.h>
+#include "include/ARTSPController.h"
#include "include/AwesomePlayer.h"
-#include "include/Prefetcher.h"
+#include "include/LiveSource.h"
#include "include/SoftwareRenderer.h"
+#include "include/NuCachedSource2.h"
+#include "include/ThrottledSource.h"
#include <binder/IPCThreadState.h>
#include <media/stagefright/AudioPlayer.h>
-#include <media/stagefright/CachingDataSource.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBuffer.h>
@@ -39,6 +41,8 @@
#include <surfaceflinger/ISurface.h>
+#include <media/stagefright/foundation/ALooper.h>
+
namespace android {
struct AwesomeEvent : public TimedEventQueue::Event {
@@ -261,6 +265,16 @@ status_t AwesomePlayer::setDataSource_l(
status_t AwesomePlayer::setDataSource(
int fd, int64_t offset, int64_t length) {
+#if 0
+ // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_96.m3u8");
+ // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/nasatv/nasatv_1500.m3u8");
+ return setDataSource("httplive://iphone.video.hsn.com/iPhone_high.m3u8");
+ // return setDataSource("httplive://iphoned5.akamai.com.edgesuite.net/mhbarron/iphonewebcast/webcast090209_all/webcast090209_all.m3u8");
+ // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_062209_iphone/hi/prog_index.m3u8");
+ // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/usat/tt_googmaps/hi/prog_index.m3u8");
+ // return setDataSource("httplive://qthttp.akamai.com.edgesuite.net/iphone_demo/Video_Content/mtv/ni_spo_25a_rt74137_clip_syn/hi/prog_index.m3u8");
+#endif
+
Mutex::Autolock autoLock(mLock);
reset_l();
@@ -340,11 +354,7 @@ void AwesomePlayer::reset_l() {
cancelPlayerEvents();
- if (mPrefetcher != NULL) {
- CHECK_EQ(mPrefetcher->getStrongCount(), 1);
- }
- mPrefetcher.clear();
-
+ mCachedSource.clear();
mAudioTrack.clear();
mVideoTrack.clear();
@@ -361,9 +371,6 @@ void AwesomePlayer::reset_l() {
}
mAudioSource.clear();
- if (mTimeSource != mAudioPlayer) {
- delete mTimeSource;
- }
mTimeSource = NULL;
delete mAudioPlayer;
@@ -381,6 +388,8 @@ void AwesomePlayer::reset_l() {
mVideoBuffer = NULL;
}
+ mRTSPController.clear();
+
if (mVideoSource != NULL) {
mVideoSource->stop();
@@ -432,29 +441,45 @@ void AwesomePlayer::onBufferingUpdate() {
}
mBufferingEventPending = false;
- int64_t durationUs;
- {
- Mutex::Autolock autoLock(mMiscStateLock);
- durationUs = mDurationUs;
+ if (mCachedSource == NULL) {
+ return;
}
- if (durationUs >= 0) {
- int64_t cachedDurationUs = mPrefetcher->getCachedDurationUs();
+ size_t lowWatermark = 400000;
+ size_t highWatermark = 1000000;
- LOGV("cache holds %.2f secs worth of data.", cachedDurationUs / 1E6);
+ off_t size;
+ if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
+ int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
- int64_t positionUs;
- getPosition(&positionUs);
+ size_t cachedSize = mCachedSource->cachedSize();
+ int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
- cachedDurationUs += positionUs;
+ double percentage = (double)cachedDurationUs / mDurationUs;
- double percentage = (double)cachedDurationUs / durationUs;
notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
- postBufferingEvent_l();
- } else {
- LOGE("Not sending buffering status because duration is unknown.");
+ lowWatermark = 2 * bitrate / 8; // 2 secs
+ highWatermark = 10 * bitrate / 8; // 10 secs
}
+
+ bool eos;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
+
+ if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
+ LOGI("cache is running low (< %d) , pausing.", lowWatermark);
+ mFlags |= CACHE_UNDERRUN;
+ pause_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
+ } else if ((mFlags & CACHE_UNDERRUN)
+ && (eos || cachedDataRemaining > highWatermark)) {
+ LOGI("cache has filled up (> %d), resuming.", highWatermark);
+ mFlags &= ~CACHE_UNDERRUN;
+ play_l();
+ notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
+ }
+
+ postBufferingEvent_l();
}
void AwesomePlayer::onStreamDone() {
@@ -466,22 +491,35 @@ void AwesomePlayer::onStreamDone() {
}
mStreamDoneEventPending = false;
- if (mStreamDoneStatus == ERROR_END_OF_STREAM && (mFlags & LOOPING)) {
+ if (mStreamDoneStatus != ERROR_END_OF_STREAM) {
+ LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
+
+ notifyListener_l(
+ MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
+
+ pause_l();
+
+ mFlags |= AT_EOS;
+ return;
+ }
+
+ const bool allDone =
+ (mVideoSource == NULL || (mFlags & VIDEO_AT_EOS))
+ && (mAudioSource == NULL || (mFlags & AUDIO_AT_EOS));
+
+ if (!allDone) {
+ return;
+ }
+
+ if (mFlags & LOOPING) {
seekTo_l(0);
if (mVideoSource != NULL) {
postVideoEvent_l();
}
} else {
- if (mStreamDoneStatus == ERROR_END_OF_STREAM) {
- LOGV("MEDIA_PLAYBACK_COMPLETE");
- notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
- } else {
- LOGV("MEDIA_ERROR %d", mStreamDoneStatus);
-
- notifyListener_l(
- MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, mStreamDoneStatus);
- }
+ LOGV("MEDIA_PLAYBACK_COMPLETE");
+ notifyListener_l(MEDIA_PLAYBACK_COMPLETE);
pause_l();
@@ -491,6 +529,9 @@ void AwesomePlayer::onStreamDone() {
status_t AwesomePlayer::play() {
Mutex::Autolock autoLock(mLock);
+
+ mFlags &= ~CACHE_UNDERRUN;
+
return play_l();
}
@@ -532,7 +573,6 @@ status_t AwesomePlayer::play_l() {
return err;
}
- delete mTimeSource;
mTimeSource = mAudioPlayer;
deferredAudioSeek = true;
@@ -548,7 +588,7 @@ status_t AwesomePlayer::play_l() {
}
if (mTimeSource == NULL && mAudioPlayer == NULL) {
- mTimeSource = new SystemTimeSource;
+ mTimeSource = &mSystemTimeSource;
}
if (mVideoSource != NULL) {
@@ -615,6 +655,9 @@ void AwesomePlayer::initRenderer_l() {
status_t AwesomePlayer::pause() {
Mutex::Autolock autoLock(mLock);
+
+ mFlags &= ~CACHE_UNDERRUN;
+
return pause_l();
}
@@ -635,7 +678,7 @@ status_t AwesomePlayer::pause_l() {
}
bool AwesomePlayer::isPlaying() const {
- return mFlags & PLAYING;
+ return (mFlags & PLAYING) || (mFlags & CACHE_UNDERRUN);
}
void AwesomePlayer::setISurface(const sp<ISurface> &isurface) {
@@ -702,10 +745,15 @@ status_t AwesomePlayer::seekTo(int64_t timeUs) {
}
status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
+ if (mFlags & CACHE_UNDERRUN) {
+ mFlags &= ~CACHE_UNDERRUN;
+ play_l();
+ }
+
mSeeking = true;
mSeekNotificationSent = false;
mSeekTimeUs = timeUs;
- mFlags &= ~AT_EOS;
+ mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
seekAudioIfNecessary_l();
@@ -747,10 +795,6 @@ status_t AwesomePlayer::getVideoDimensions(
void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
CHECK(source != NULL);
- if (mPrefetcher != NULL) {
- source = mPrefetcher->addSource(source);
- }
-
mAudioTrack = source;
}
@@ -797,10 +841,6 @@ status_t AwesomePlayer::initAudioDecoder() {
void AwesomePlayer::setVideoSource(sp<MediaSource> source) {
CHECK(source != NULL);
- if (mPrefetcher != NULL) {
- source = mPrefetcher->addSource(source);
- }
-
mVideoTrack = source;
}
@@ -852,6 +892,21 @@ void AwesomePlayer::onVideoEvent() {
mVideoBuffer->release();
mVideoBuffer = NULL;
}
+
+ if (mCachedSource != NULL && mAudioSource != NULL) {
+ // We're going to seek the video source first, followed by
+ // the audio source.
+ // In order to avoid jumps in the DataSource offset caused by
+ // the audio codec prefetching data from the old locations
+ // while the video codec is already reading data from the new
+ // locations, we'll "pause" the audio source, causing it to
+ // stop reading input data until a subsequent seek.
+
+ if (mAudioPlayer != NULL) {
+ mAudioPlayer->pause();
+ }
+ mAudioSource->pause();
+ }
}
if (!mVideoBuffer) {
@@ -859,7 +914,8 @@ void AwesomePlayer::onVideoEvent() {
if (mSeeking) {
LOGV("seeking to %lld us (%.2f secs)", mSeekTimeUs, mSeekTimeUs / 1E6);
- options.setSeekTo(mSeekTimeUs);
+ options.setSeekTo(
+ mSeekTimeUs, MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
}
for (;;) {
status_t err = mVideoSource->read(&mVideoBuffer, &options);
@@ -878,6 +934,7 @@ void AwesomePlayer::onVideoEvent() {
continue;
}
+ mFlags |= VIDEO_AT_EOS;
postStreamDoneEvent_l(err);
return;
}
@@ -908,6 +965,7 @@ void AwesomePlayer::onVideoEvent() {
LOGV("seeking audio to %lld us (%.2f secs).", timeUs, timeUs / 1E6);
mAudioPlayer->seekTo(timeUs);
+ mAudioPlayer->resume();
mWatchForAudioSeekComplete = true;
mWatchForAudioEOS = true;
} else if (!mSeekNotificationSent) {
@@ -921,19 +979,21 @@ void AwesomePlayer::onVideoEvent() {
mSeekNotificationSent = false;
}
+ TimeSource *ts = (mFlags & AUDIO_AT_EOS) ? &mSystemTimeSource : mTimeSource;
+
if (mFlags & FIRST_FRAME) {
mFlags &= ~FIRST_FRAME;
- mTimeSourceDeltaUs = mTimeSource->getRealTimeUs() - timeUs;
+ mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
}
int64_t realTimeUs, mediaTimeUs;
- if (mAudioPlayer != NULL
+ if (!(mFlags & AUDIO_AT_EOS) && mAudioPlayer != NULL
&& mAudioPlayer->getMediaTimeMapping(&realTimeUs, &mediaTimeUs)) {
mTimeSourceDeltaUs = realTimeUs - mediaTimeUs;
}
- int64_t nowUs = mTimeSource->getRealTimeUs() - mTimeSourceDeltaUs;
+ int64_t nowUs = ts->getRealTimeUs() - mTimeSourceDeltaUs;
int64_t latenessUs = nowUs - timeUs;
@@ -995,10 +1055,6 @@ void AwesomePlayer::postStreamDoneEvent_l(status_t status) {
}
void AwesomePlayer::postBufferingEvent_l() {
- if (mPrefetcher == NULL) {
- return;
- }
-
if (mBufferingEventPending) {
return;
}
@@ -1038,6 +1094,8 @@ void AwesomePlayer::onCheckAudioStatus() {
status_t finalStatus;
if (mWatchForAudioEOS && mAudioPlayer->reachedEOS(&finalStatus)) {
mWatchForAudioEOS = false;
+ mFlags |= AUDIO_AT_EOS;
+ mFlags |= FIRST_FRAME;
postStreamDoneEvent_l(finalStatus);
}
@@ -1106,10 +1164,10 @@ status_t AwesomePlayer::finishSetDataSource_l() {
sp<DataSource> dataSource;
if (!strncasecmp("http://", mUri.string(), 7)) {
- mConnectingDataSource = new HTTPDataSource(mUri, &mUriHeaders);
+ mConnectingDataSource = new NuHTTPDataSource;
mLock.unlock();
- status_t err = mConnectingDataSource->connect();
+ status_t err = mConnectingDataSource->connect(mUri, &mUriHeaders);
mLock.lock();
if (err != OK) {
@@ -1119,10 +1177,46 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return err;
}
- dataSource = new CachingDataSource(
- mConnectingDataSource, 64 * 1024, 10);
-
+#if 0
+ mCachedSource = new NuCachedSource2(
+ new ThrottledSource(
+ mConnectingDataSource, 50 * 1024 /* bytes/sec */));
+#else
+ mCachedSource = new NuCachedSource2(mConnectingDataSource);
+#endif
mConnectingDataSource.clear();
+
+ dataSource = mCachedSource;
+ } else if (!strncasecmp(mUri.string(), "httplive://", 11)) {
+ String8 uri("http://");
+ uri.append(mUri.string() + 11);
+
+ dataSource = new LiveSource(uri.string());
+
+ mCachedSource = new NuCachedSource2(dataSource);
+ dataSource = mCachedSource;
+
+ sp<MediaExtractor> extractor =
+ MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+ return setDataSource_l(extractor);
+ } else if (!strncasecmp("rtsp://", mUri.string(), 7)) {
+ if (mLooper == NULL) {
+ mLooper = new ALooper;
+ mLooper->start();
+ }
+ mRTSPController = new ARTSPController(mLooper);
+ status_t err = mRTSPController->connect(mUri.string());
+
+ LOGI("ARTSPController::connect returned %d", err);
+
+ if (err != OK) {
+ mRTSPController.clear();
+ return err;
+ }
+
+ sp<MediaExtractor> extractor = mRTSPController.get();
+ return setDataSource_l(extractor);
} else {
dataSource = DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
}
@@ -1137,10 +1231,6 @@ status_t AwesomePlayer::finishSetDataSource_l() {
return UNKNOWN_ERROR;
}
- if (dataSource->flags() & DataSource::kWantsPrefetching) {
- mPrefetcher = new Prefetcher;
- }
-
return setDataSource_l(extractor);
}
@@ -1165,8 +1255,6 @@ bool AwesomePlayer::ContinuePreparation(void *cookie) {
}
void AwesomePlayer::onPrepareAsyncEvent() {
- sp<Prefetcher> prefetcher;
-
{
Mutex::Autolock autoLock(mLock);
@@ -1202,39 +1290,6 @@ void AwesomePlayer::onPrepareAsyncEvent() {
return;
}
}
-
- prefetcher = mPrefetcher;
- }
-
- if (prefetcher != NULL) {
- {
- Mutex::Autolock autoLock(mLock);
- if (mFlags & PREPARE_CANCELLED) {
- LOGI("prepare was cancelled before preparing the prefetcher");
-
- prefetcher.clear();
- abortPrepare(UNKNOWN_ERROR);
- return;
- }
- }
-
- LOGI("calling prefetcher->prepare()");
- status_t result =
- prefetcher->prepare(&AwesomePlayer::ContinuePreparation, this);
-
- prefetcher.clear();
-
- if (result == OK) {
- LOGI("prefetcher is done preparing");
- } else {
- Mutex::Autolock autoLock(mLock);
-
- CHECK_EQ(result, -EINTR);
-
- LOGI("prefetcher->prepare() was cancelled early.");
- abortPrepare(UNKNOWN_ERROR);
- return;
- }
}
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/CachingDataSource.cpp b/media/libstagefright/CachingDataSource.cpp
deleted file mode 100644
index 1ca463e..0000000
--- a/media/libstagefright/CachingDataSource.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <media/stagefright/CachingDataSource.h>
-#include <media/stagefright/MediaDebug.h>
-
-namespace android {
-
-CachingDataSource::CachingDataSource(
- const sp<DataSource> &source, size_t pageSize, int numPages)
- : mSource(source),
- mData(malloc(pageSize * numPages)),
- mPageSize(pageSize),
- mFirst(NULL),
- mLast(NULL) {
- for (int i = 0; i < numPages; ++i) {
- Page *page = new Page;
- page->mPrev = mLast;
- page->mNext = NULL;
-
- if (mLast == NULL) {
- mFirst = page;
- } else {
- mLast->mNext = page;
- }
-
- mLast = page;
-
- page->mOffset = -1;
- page->mLength = 0;
- page->mData = (char *)mData + mPageSize * i;
- }
-}
-
-CachingDataSource::~CachingDataSource() {
- Page *page = mFirst;
- while (page != NULL) {
- Page *next = page->mNext;
- delete page;
- page = next;
- }
- mFirst = mLast = NULL;
-
- free(mData);
- mData = NULL;
-}
-
-status_t CachingDataSource::initCheck() const {
- return mSource->initCheck();
-}
-
-status_t CachingDataSource::getSize(off_t *size) {
- return mSource->getSize(size);
-}
-
-uint32_t CachingDataSource::flags() {
- return mSource->flags();
-}
-
-ssize_t CachingDataSource::readAt(off_t offset, void *data, size_t size) {
- Mutex::Autolock autoLock(mLock);
-
- size_t total = 0;
- while (size > 0) {
- Page *page = mFirst;
- while (page != NULL) {
- if (page->mOffset >= 0 && offset >= page->mOffset
- && offset < page->mOffset + (off_t)page->mLength) {
- break;
- }
- page = page->mNext;
- }
-
- if (page == NULL) {
- page = allocate_page();
- page->mOffset = offset - offset % mPageSize;
- ssize_t n = mSource->readAt(page->mOffset, page->mData, mPageSize);
- if (n < 0) {
- page->mLength = 0;
- } else {
- page->mLength = (size_t)n;
- }
- mFirst->mPrev = page;
- page->mNext = mFirst;
- page->mPrev = NULL;
- mFirst = page;
-
- if (n < 0) {
- return n;
- }
-
- if (offset >= page->mOffset + (off_t)page->mLength) {
- break;
- }
- } else {
- // Move "page" to the front in LRU order.
- if (page->mNext != NULL) {
- page->mNext->mPrev = page->mPrev;
- } else {
- mLast = page->mPrev;
- }
-
- if (page->mPrev != NULL) {
- page->mPrev->mNext = page->mNext;
- } else {
- mFirst = page->mNext;
- }
-
- mFirst->mPrev = page;
- page->mNext = mFirst;
- page->mPrev = NULL;
- mFirst = page;
- }
-
- size_t copy = page->mLength - (offset - page->mOffset);
- if (copy > size) {
- copy = size;
- }
- memcpy(data,(const char *)page->mData + (offset - page->mOffset),
- copy);
-
- total += copy;
-
- if (page->mLength < mPageSize) {
- // This was the final page. There is no more data beyond it.
- break;
- }
-
- offset += copy;
- size -= copy;
- data = (char *)data + copy;
- }
-
- return total;
-}
-
-CachingDataSource::Page *CachingDataSource::allocate_page() {
- // The last page is the least recently used, i.e. oldest.
-
- Page *page = mLast;
-
- page->mPrev->mNext = NULL;
- mLast = page->mPrev;
- page->mPrev = NULL;
-
- return page;
-}
-
-} // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 075b1e3..9c48daf 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-#include <sys/time.h>
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CameraSource"
+#include <utils/Log.h>
#include <OMX_Component.h>
-
-#include <binder/IServiceManager.h>
-#include <cutils/properties.h> // for property_get
+#include <binder/IPCThreadState.h>
#include <media/stagefright/CameraSource.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
@@ -27,46 +27,11 @@
#include <media/stagefright/MetaData.h>
#include <camera/Camera.h>
#include <camera/CameraParameters.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/Overlay.h>
-#include <surfaceflinger/ISurface.h>
#include <utils/String8.h>
+#include <cutils/properties.h>
namespace android {
-static int64_t getNowUs() {
- struct timeval tv;
- gettimeofday(&tv, NULL);
-
- return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
-}
-
-struct DummySurface : public BnSurface {
- DummySurface() {}
-
- virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage) {
- return NULL;
- }
-
- virtual status_t registerBuffers(const BufferHeap &buffers) {
- return OK;
- }
-
- virtual void postBuffer(ssize_t offset) {}
- virtual void unregisterBuffers() {}
-
- virtual sp<OverlayRef> createOverlay(
- uint32_t w, uint32_t h, int32_t format, int32_t orientation) {
- return NULL;
- }
-
-protected:
- virtual ~DummySurface() {}
-
- DummySurface(const DummySurface &);
- DummySurface &operator=(const DummySurface &);
-};
-
struct CameraSourceListener : public CameraListener {
CameraSourceListener(const sp<CameraSource> &source);
@@ -100,22 +65,40 @@ void CameraSourceListener::notify(int32_t msgType, int32_t ext1, int32_t ext2) {
void CameraSourceListener::postData(int32_t msgType, const sp<IMemory> &dataPtr) {
LOGV("postData(%d, ptr:%p, size:%d)",
msgType, dataPtr->pointer(), dataPtr->size());
+}
+
+void CameraSourceListener::postDataTimestamp(
+ nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
sp<CameraSource> source = mSource.promote();
if (source.get() != NULL) {
- source->dataCallback(msgType, dataPtr);
+ source->dataCallbackTimestamp(timestamp/1000, msgType, dataPtr);
}
}
-void CameraSourceListener::postDataTimestamp(
- nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr) {
- LOGV("postDataTimestamp(%lld, %d, ptr:%p, size:%d)",
- timestamp, msgType, dataPtr->pointer(), dataPtr->size());
+static int32_t getColorFormat(const char* colorFormat) {
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422SP)) {
+ return OMX_COLOR_FormatYUV422SemiPlanar;
+ }
+
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV420SP)) {
+ return OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_YUV422I)) {
+ return OMX_COLOR_FormatYCbYCr;
+ }
+
+ if (!strcmp(colorFormat, CameraParameters::PIXEL_FORMAT_RGB565)) {
+ return OMX_COLOR_Format16bitRGB565;
+ }
+
+ CHECK_EQ(0, "Unknown color format");
}
// static
CameraSource *CameraSource::Create() {
- sp<Camera> camera = Camera::connect();
+ sp<Camera> camera = Camera::connect(0);
if (camera.get() == NULL) {
return NULL;
@@ -125,9 +108,7 @@ CameraSource *CameraSource::Create() {
}
// static
-CameraSource *CameraSource::CreateFromICamera(const sp<ICamera> &icamera) {
- sp<Camera> camera = Camera::create(icamera);
-
+CameraSource *CameraSource::CreateFromCamera(const sp<Camera> &camera) {
if (camera.get() == NULL) {
return NULL;
}
@@ -137,23 +118,50 @@ CameraSource *CameraSource::CreateFromICamera(const sp<ICamera> &icamera) {
CameraSource::CameraSource(const sp<Camera> &camera)
: mCamera(camera),
- mWidth(0),
- mHeight(0),
mFirstFrameTimeUs(0),
- mNumFrames(0),
+ mLastFrameTimestampUs(0),
+ mNumFramesReceived(0),
+ mNumFramesEncoded(0),
+ mNumFramesDropped(0),
+ mNumGlitches(0),
+ mGlitchDurationThresholdUs(200000),
+ mCollectStats(false),
mStarted(false) {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("ro.hardware", value, NULL) && !strcmp(value, "sholes")) {
- // The hardware encoder(s) do not support yuv420, but only YCbYCr,
- // fortunately the camera also supports this, so we needn't transcode.
- mCamera->setParameters(String8("preview-format=yuv422i-yuyv"));
- }
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
String8 s = mCamera->getParameters();
+ IPCThreadState::self()->restoreCallingIdentity(token);
+
printf("params: \"%s\"\n", s.string());
+ int32_t width, height, stride, sliceHeight;
CameraParameters params(s);
- params.getPreviewSize(&mWidth, &mHeight);
+ params.getPreviewSize(&width, &height);
+
+ // Calculate glitch duraton threshold based on frame rate
+ int32_t frameRate = params.getPreviewFrameRate();
+ int64_t glitchDurationUs = (1000000LL / frameRate);
+ if (glitchDurationUs > mGlitchDurationThresholdUs) {
+ mGlitchDurationThresholdUs = glitchDurationUs;
+ }
+
+ const char *colorFormatStr = params.get(CameraParameters::KEY_VIDEO_FRAME_FORMAT);
+ CHECK(colorFormatStr != NULL);
+ int32_t colorFormat = getColorFormat(colorFormatStr);
+
+ // XXX: query camera for the stride and slice height
+ // when the capability becomes available.
+ stride = width;
+ sliceHeight = height;
+
+ mMeta = new MetaData;
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ mMeta->setInt32(kKeyColorFormat, colorFormat);
+ mMeta->setInt32(kKeyWidth, width);
+ mMeta->setInt32(kKeyHeight, height);
+ mMeta->setInt32(kKeyStride, stride);
+ mMeta->setInt32(kKeySliceHeight, sliceHeight);
+
}
CameraSource::~CameraSource() {
@@ -162,60 +170,105 @@ CameraSource::~CameraSource() {
}
}
-void CameraSource::setPreviewSurface(const sp<ISurface> &surface) {
- mPreviewSurface = surface;
-}
-
-status_t CameraSource::start(MetaData *) {
+status_t CameraSource::start(MetaData *meta) {
CHECK(!mStarted);
- mCamera->setListener(new CameraSourceListener(this));
-
- status_t err =
- mCamera->setPreviewDisplay(
- mPreviewSurface != NULL ? mPreviewSurface : new DummySurface);
- CHECK_EQ(err, OK);
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-stats", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ mCollectStats = true;
+ }
- mCamera->setPreviewCallbackFlags(
- FRAME_CALLBACK_FLAG_ENABLE_MASK
- | FRAME_CALLBACK_FLAG_COPY_OUT_MASK);
+ mStartTimeUs = 0;
+ int64_t startTimeUs;
+ if (meta && meta->findInt64(kKeyTime, &startTimeUs)) {
+ mStartTimeUs = startTimeUs;
+ }
- err = mCamera->startPreview();
- CHECK_EQ(err, OK);
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mCamera->setListener(new CameraSourceListener(this));
+ CHECK_EQ(OK, mCamera->startRecording());
+ IPCThreadState::self()->restoreCallingIdentity(token);
mStarted = true;
-
return OK;
}
status_t CameraSource::stop() {
- CHECK(mStarted);
+ LOGV("stop");
+ Mutex::Autolock autoLock(mLock);
+ mStarted = false;
+ mFrameAvailableCondition.signal();
- mCamera->stopPreview();
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mCamera->setListener(NULL);
+ mCamera->stopRecording();
+ releaseQueuedFrames();
+ while (!mFramesBeingEncoded.empty()) {
+ LOGI("Waiting for outstanding frames being encoded: %d",
+ mFramesBeingEncoded.size());
+ mFrameCompleteCondition.wait(mLock);
+ }
+ mCamera = NULL;
+ IPCThreadState::self()->restoreCallingIdentity(token);
- mStarted = false;
+ if (mCollectStats) {
+ LOGI("Frames received/encoded/dropped: %d/%d/%d in %lld us",
+ mNumFramesReceived, mNumFramesEncoded, mNumFramesDropped,
+ mLastFrameTimestampUs - mFirstFrameTimeUs);
+ }
+ CHECK_EQ(mNumFramesReceived, mNumFramesEncoded + mNumFramesDropped);
return OK;
}
+void CameraSource::releaseQueuedFrames() {
+ List<sp<IMemory> >::iterator it;
+ while (!mFramesReceived.empty()) {
+ it = mFramesReceived.begin();
+ mCamera->releaseRecordingFrame(*it);
+ mFramesReceived.erase(it);
+ ++mNumFramesDropped;
+ }
+}
+
sp<MetaData> CameraSource::getFormat() {
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
- meta->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420SemiPlanar);
- meta->setInt32(kKeyWidth, mWidth);
- meta->setInt32(kKeyHeight, mHeight);
+ return mMeta;
+}
- return meta;
+void CameraSource::releaseOneRecordingFrame(const sp<IMemory>& frame) {
+ int64_t token = IPCThreadState::self()->clearCallingIdentity();
+ mCamera->releaseRecordingFrame(frame);
+ IPCThreadState::self()->restoreCallingIdentity(token);
+}
+
+void CameraSource::signalBufferReturned(MediaBuffer *buffer) {
+ LOGV("signalBufferReturned: %p", buffer->data());
+ for (List<sp<IMemory> >::iterator it = mFramesBeingEncoded.begin();
+ it != mFramesBeingEncoded.end(); ++it) {
+ if ((*it)->pointer() == buffer->data()) {
+
+ releaseOneRecordingFrame((*it));
+ mFramesBeingEncoded.erase(it);
+ ++mNumFramesEncoded;
+ buffer->setObserver(0);
+ buffer->release();
+ mFrameCompleteCondition.signal();
+ return;
+ }
+ }
+ CHECK_EQ(0, "signalBufferReturned: bogus buffer");
}
status_t CameraSource::read(
MediaBuffer **buffer, const ReadOptions *options) {
- CHECK(mStarted);
+ LOGV("read");
*buffer = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
return ERROR_UNSUPPORTED;
}
@@ -224,38 +277,88 @@ status_t CameraSource::read(
{
Mutex::Autolock autoLock(mLock);
- while (mFrames.empty()) {
- mFrameAvailableCondition.wait(mLock);
+ while (mStarted) {
+ while(mFramesReceived.empty()) {
+ mFrameAvailableCondition.wait(mLock);
+ }
+
+ if (!mStarted) {
+ return OK;
+ }
+
+ frame = *mFramesReceived.begin();
+ mFramesReceived.erase(mFramesReceived.begin());
+
+ frameTime = *mFrameTimes.begin();
+ mFrameTimes.erase(mFrameTimes.begin());
+ int64_t skipTimeUs;
+ if (!options || !options->getSkipFrame(&skipTimeUs)) {
+ skipTimeUs = frameTime;
+ }
+ if (skipTimeUs > frameTime) {
+ LOGV("skipTimeUs: %lld us > frameTime: %lld us",
+ skipTimeUs, frameTime);
+ releaseOneRecordingFrame(frame);
+ ++mNumFramesDropped;
+ // Safeguard against the abuse of the kSkipFrame_Option.
+ if (skipTimeUs - frameTime >= 1E6) {
+ LOGE("Frame skipping requested is way too long: %lld us",
+ skipTimeUs - frameTime);
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ mFramesBeingEncoded.push_back(frame);
+ *buffer = new MediaBuffer(frame->pointer(), frame->size());
+ (*buffer)->setObserver(this);
+ (*buffer)->add_ref();
+ (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
+ return OK;
+ }
}
-
- frame = *mFrames.begin();
- mFrames.erase(mFrames.begin());
-
- frameTime = *mFrameTimes.begin();
- mFrameTimes.erase(mFrameTimes.begin());
}
-
- *buffer = new MediaBuffer(frame->size());
- memcpy((*buffer)->data(), frame->pointer(), frame->size());
- (*buffer)->set_range(0, frame->size());
-
- (*buffer)->meta_data()->clear();
- (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
-
return OK;
}
-void CameraSource::dataCallback(int32_t msgType, const sp<IMemory> &data) {
+void CameraSource::dataCallbackTimestamp(int64_t timestampUs,
+ int32_t msgType, const sp<IMemory> &data) {
+ LOGV("dataCallbackTimestamp: timestamp %lld us", timestampUs);
Mutex::Autolock autoLock(mLock);
+ if (!mStarted) {
+ releaseOneRecordingFrame(data);
+ ++mNumFramesReceived;
+ ++mNumFramesDropped;
+ return;
+ }
- int64_t nowUs = getNowUs();
- if (mNumFrames == 0) {
- mFirstFrameTimeUs = nowUs;
+ if (mNumFramesReceived > 0 &&
+ timestampUs - mLastFrameTimestampUs > mGlitchDurationThresholdUs) {
+ if (mNumGlitches % 10 == 0) { // Don't spam the log
+ LOGW("Long delay detected in video recording");
+ }
+ ++mNumGlitches;
+ }
+
+ mLastFrameTimestampUs = timestampUs;
+ if (mNumFramesReceived == 0) {
+ mFirstFrameTimeUs = timestampUs;
+ // Initial delay
+ if (mStartTimeUs > 0) {
+ if (timestampUs < mStartTimeUs) {
+ // Frame was captured before recording was started
+ // Drop it without updating the statistical data.
+ releaseOneRecordingFrame(data);
+ return;
+ }
+ mStartTimeUs = timestampUs - mStartTimeUs;
+ }
}
- ++mNumFrames;
+ ++mNumFramesReceived;
- mFrames.push_back(data);
- mFrameTimes.push_back(nowUs - mFirstFrameTimeUs);
+ mFramesReceived.push_back(data);
+ int64_t timeUs = mStartTimeUs + (timestampUs - mFirstFrameTimeUs);
+ mFrameTimes.push_back(timeUs);
+ LOGV("initial delay: %lld, current time stamp: %lld",
+ mStartTimeUs, timeUs);
mFrameAvailableCondition.signal();
}
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index a66f86b..90a596c 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -19,11 +19,14 @@
#include "include/MPEG4Extractor.h"
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
+#include "include/MPEG2TSExtractor.h"
+#include "include/NuCachedSource2.h"
+#include "include/NuHTTPDataSource.h"
+
+#include "matroska/MatroskaExtractor.h"
-#include <media/stagefright/CachingDataSource.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
-#include <media/stagefright/HTTPDataSource.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/String8.h>
@@ -94,6 +97,8 @@ void DataSource::RegisterDefaultSniffers() {
RegisterSniffer(SniffAMR);
RegisterSniffer(SniffWAV);
RegisterSniffer(SniffOgg);
+ RegisterSniffer(SniffMatroska);
+ RegisterSniffer(SniffMPEG2TS);
}
// static
@@ -103,11 +108,11 @@ sp<DataSource> DataSource::CreateFromURI(
if (!strncasecmp("file://", uri, 7)) {
source = new FileSource(uri + 7);
} else if (!strncasecmp("http://", uri, 7)) {
- sp<HTTPDataSource> httpSource = new HTTPDataSource(uri, headers);
- if (httpSource->connect() != OK) {
+ sp<NuHTTPDataSource> httpSource = new NuHTTPDataSource;
+ if (httpSource->connect(uri, headers) != OK) {
return NULL;
}
- source = new CachingDataSource(httpSource, 64 * 1024, 10);
+ source = new NuCachedSource2(httpSource);
} else {
// Assume it's a filename.
source = new FileSource(uri);
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index b6f1af2..dd2579b 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -45,6 +45,10 @@ status_t FileSource::initCheck() const {
}
ssize_t FileSource::readAt(off_t offset, void *data, size_t size) {
+ if (mFile == NULL) {
+ return NO_INIT;
+ }
+
Mutex::Autolock autoLock(mLock);
if (mLength >= 0) {
@@ -67,6 +71,10 @@ ssize_t FileSource::readAt(off_t offset, void *data, size_t size) {
}
status_t FileSource::getSize(off_t *size) {
+ if (mFile == NULL) {
+ return NO_INIT;
+ }
+
if (mLength >= 0) {
*size = mLength;
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
deleted file mode 100644
index f72a6cc..0000000
--- a/media/libstagefright/HTTPDataSource.cpp
+++ /dev/null
@@ -1,457 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "HTTPDataSource"
-#include <utils/Log.h>
-
-#include "include/stagefright_string.h"
-#include "include/HTTPStream.h"
-
-#include <stdlib.h>
-
-#include <cutils/properties.h>
-#include <media/stagefright/HTTPDataSource.h>
-#include <media/stagefright/MediaDebug.h>
-
-namespace android {
-
-status_t HTTPDataSource::connectWithRedirectsAndRange(off_t rangeStart) {
- string host = mStartingHost.string();
- string path = mStartingPath.string();
- int port = mStartingPort;
-
- LOGV("Connecting to host '%s', port %d, path '%s'",
- host.c_str(), port, path.c_str());
-
- int numRedirectsRemaining = 5;
- while (numRedirectsRemaining-- > 0) {
- {
- Mutex::Autolock autoLock(mStateLock);
- if (mState == DISCONNECTED) {
- return UNKNOWN_ERROR;
- }
- }
-
- status_t err = mHttp->connect(host.c_str(), port);
-
- if (err != OK) {
- return err;
- }
-
- String8 request;
- request.append("GET ");
- request.append(path.c_str());
- request.append(" HTTP/1.1\r\n");
- request.append(mHeaders);
- request.append("Host: ");
- request.append(host.c_str());
- request.append("\r\n");
-
- if (rangeStart > 0) {
- char range[128];
- sprintf(range, "Range: bytes=%ld-\r\n", rangeStart);
-
- request.append(range);
- }
-
- request.append("\r\n");
-
- err = mHttp->send(request.string());
-
- if (err != OK) {
- return err;
- }
-
- int httpStatus;
- err = mHttp->receive_header(&httpStatus);
-
- if (err != OK) {
- return err;
- }
-
- if (httpStatus >= 200 && httpStatus < 300) {
- applyTimeoutResponse();
- return OK;
- }
-
- if (httpStatus != 301 && httpStatus != 302) {
- LOGE("HTTP request failed w/ http status %d", httpStatus);
- return ERROR_IO;
- }
-
- string location;
- CHECK(mHttp->find_header_value("Location", &location));
-
- CHECK(string(location, 0, 7) == "http://");
- location.erase(0, 7);
- string::size_type slashPos = location.find('/');
- if (slashPos == string::npos) {
- slashPos = location.size();
- location += '/';
- }
-
- mHttp->disconnect();
-
- LOGV("Redirecting to %s\n", location.c_str());
-
- host = string(location, 0, slashPos);
-
- string::size_type colonPos = host.find(':');
- if (colonPos != string::npos) {
- const char *start = host.c_str() + colonPos + 1;
- char *end;
- long tmp = strtol(start, &end, 10);
- CHECK(end > start && (*end == '\0'));
-
- port = (tmp >= 0 && tmp < 65536) ? (int)tmp : 80;
-
- host.erase(colonPos, host.size() - colonPos);
- } else {
- port = 80;
- }
-
- path = string(location, slashPos);
-
- mStartingHost = host.c_str();
- mStartingPath = path.c_str();
- mStartingPort = port;
- }
-
- return ERROR_IO;
-}
-
-void HTTPDataSource::applyTimeoutResponse() {
- string timeout;
- if (mHttp->find_header_value("X-SocketTimeout", &timeout)) {
- const char *s = timeout.c_str();
- char *end;
- long tmp = strtol(s, &end, 10);
- if (end == s || *end != '\0') {
- LOGW("Illegal X-SocketTimeout value given.");
- return;
- }
-
- LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
- mHttp->setReceiveTimeout(tmp);
- }
-}
-
-HTTPDataSource::HTTPDataSource(
- const char *uri, const KeyedVector<String8, String8> *headers) {
- CHECK(!strncasecmp("http://", uri, 7));
-
- string host;
- string path;
- int port;
-
- char *slash = strchr(uri + 7, '/');
- if (slash == NULL) {
- host = uri + 7;
- path = "/";
- } else {
- host = string(uri + 7, slash - (uri + 7));
- path = slash;
- }
-
- char *colon = strchr(host.c_str(), ':');
- if (colon == NULL) {
- port = 80;
- } else {
- char *end;
- long tmp = strtol(colon + 1, &end, 10);
- CHECK(end > colon + 1);
- CHECK(tmp > 0 && tmp < 65536);
- port = tmp;
-
- host = string(host, 0, colon - host.c_str());
- }
-
- mStartingHost = host.c_str();
- mStartingPath = path.c_str();
- mStartingPort = port;
-
- init(headers);
-}
-
-HTTPDataSource::HTTPDataSource(
- const char *_host, int port, const char *_path,
- const KeyedVector<String8, String8> *headers) {
- mStartingHost = _host;
- mStartingPath = _path;
- mStartingPort = port;
-
- init(headers);
-}
-
-void HTTPDataSource::init(const KeyedVector<String8, String8> *headers) {
- mState = DISCONNECTED;
- mHttp = new HTTPStream;
-
- initHeaders(headers);
-
- mBuffer = malloc(kBufferSize);
-
- mNumRetriesLeft = kMaxNumRetries;
-}
-
-status_t HTTPDataSource::connect() {
- {
- Mutex::Autolock autoLock(mStateLock);
-
- if (mState != DISCONNECTED) {
- return ERROR_ALREADY_CONNECTED;
- }
-
- mState = CONNECTING;
- }
-
- mBufferLength = 0;
- mBufferOffset = 0;
- mContentLengthValid = false;
-
- status_t err = connectWithRedirectsAndRange(0);
-
- if (err != OK) {
- Mutex::Autolock autoLock(mStateLock);
-
- if (mState != CONNECTING) {
- LOGV("connect() cancelled");
- }
- mState = DISCONNECTED;
-
- return err;
- }
-
- string value;
- if (mHttp->find_header_value("Content-Length", &value)) {
- char *end;
- mContentLength = strtoull(value.c_str(), &end, 10);
- mContentLengthValid = true;
- }
-
- Mutex::Autolock autoLock(mStateLock);
-
- if (mState != CONNECTING) {
- // disconnect was called when we had just successfully connected.
- LOGV("connect() cancelled (we had just succeeded connecting)");
-
- mHttp->disconnect();
- return UNKNOWN_ERROR;
- }
-
- mState = CONNECTED;
-
- return OK;
-}
-
-void HTTPDataSource::disconnect() {
- Mutex::Autolock autoLock(mStateLock);
-
- if (mState == CONNECTING || mState == CONNECTED) {
- mHttp->disconnect();
- mState = DISCONNECTED;
- }
-}
-
-status_t HTTPDataSource::initCheck() const {
- Mutex::Autolock autoLock(mStateLock);
-
- return (mState == CONNECTED) ? (status_t)OK : ERROR_NOT_CONNECTED;
-}
-
-status_t HTTPDataSource::getSize(off_t *size) {
- *size = 0;
-
- {
- Mutex::Autolock autoLock(mStateLock);
- if (mState != CONNECTED) {
- return ERROR_NOT_CONNECTED;
- }
- }
-
- if (!mContentLengthValid) {
- return ERROR_UNSUPPORTED;
- }
-
- *size = mContentLength;
-
- return OK;
-}
-
-HTTPDataSource::~HTTPDataSource() {
- disconnect();
-
- delete mHttp;
- mHttp = NULL;
-
- free(mBuffer);
- mBuffer = NULL;
-}
-
-ssize_t HTTPDataSource::sendRangeRequest(size_t offset) {
- status_t err = connectWithRedirectsAndRange(offset);
-
- if (err != OK) {
- return err;
- }
-
- string value;
- if (!mHttp->find_header_value("Content-Length", &value)) {
- return kBufferSize;
- }
-
- char *end;
- unsigned long contentLength = strtoul(value.c_str(), &end, 10);
-
- return contentLength;
-}
-
-ssize_t HTTPDataSource::readAt(off_t offset, void *data, size_t size) {
- LOGV("readAt %ld, size %d", offset, size);
-
-rinse_repeat:
- {
- Mutex::Autolock autoLock(mStateLock);
- if (mState != CONNECTED) {
- return ERROR_NOT_CONNECTED;
- }
- }
-
- if (offset >= mBufferOffset
- && offset < (off_t)(mBufferOffset + mBufferLength)) {
- size_t num_bytes_available = mBufferLength - (offset - mBufferOffset);
-
- size_t copy = num_bytes_available;
- if (copy > size) {
- copy = size;
- }
-
- memcpy(data, (const char *)mBuffer + (offset - mBufferOffset), copy);
-
- if (copy < size) {
- LOGV("short read (1), returning %d vs. %d requested", copy, size);
- }
-
- return copy;
- }
-
- ssize_t contentLength = 0;
- if (offset != (off_t)(mBufferOffset + mBufferLength)) {
- LOGV("new range offset=%ld (old=%ld)",
- offset, mBufferOffset + mBufferLength);
-
- mHttp->disconnect();
-
- contentLength = sendRangeRequest(offset);
-
- if (contentLength > kBufferSize) {
- contentLength = kBufferSize;
- }
- } else {
- contentLength = kBufferSize;
- }
-
- mBufferOffset = offset;
-
- if (mContentLengthValid
- && mBufferOffset + contentLength >= (off_t)mContentLength) {
- // If we never triggered a range request but know the content length,
- // make sure to not read more data than there could be, otherwise
- // we'd block indefinitely if the server doesn't close the connection.
-
- contentLength = mContentLength - mBufferOffset;
- }
-
- if (contentLength <= 0) {
- return contentLength;
- }
-
- ssize_t num_bytes_received = mHttp->receive(mBuffer, contentLength);
-
- if (num_bytes_received < 0
- || (mContentLengthValid && num_bytes_received < contentLength)) {
- if (mNumRetriesLeft-- > 0) {
- mHttp->disconnect();
- mBufferLength = 0;
- num_bytes_received = connectWithRedirectsAndRange(mBufferOffset);
- if (num_bytes_received == OK) {
- LOGI("retrying connection succeeded.");
- goto rinse_repeat;
- }
- LOGE("retrying connection failed");
- }
-
- mBufferLength = 0;
-
- return num_bytes_received;
- }
-
- mBufferLength = (size_t)num_bytes_received;
-
- size_t copy = mBufferLength;
- if (copy > size) {
- copy = size;
- }
-
- memcpy(data, mBuffer, copy);
-
- return copy;
-}
-
-void HTTPDataSource::initHeaders(
- const KeyedVector<String8, String8> *overrides) {
- mHeaders = String8();
-
- mHeaders.append("User-Agent: stagefright/1.0 (Linux;Android ");
-
-#if (PROPERTY_VALUE_MAX < 8)
-#error "PROPERTY_VALUE_MAX must be at least 8"
-#endif
-
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.build.version.release", value, "Unknown");
- mHeaders.append(value);
- mHeaders.append(")\r\n");
-
- if (overrides == NULL) {
- return;
- }
-
- for (size_t i = 0; i < overrides->size(); ++i) {
- String8 line;
- line.append(overrides->keyAt(i));
- line.append(": ");
- line.append(overrides->valueAt(i));
- line.append("\r\n");
-
- mHeaders.append(line);
- }
-}
-
-uint32_t HTTPDataSource::flags() {
- uint32_t f = kWantsPrefetching;
-
- if (!strcasecmp(mStartingHost.string(), "localhost")
- || !strcmp(mStartingHost.string(), "127.0.0.1")) {
- f |= kStreamedFromLocalHost;
- }
-
- return f;
-}
-
-} // namespace android
-
diff --git a/media/libstagefright/JPEGSource.cpp b/media/libstagefright/JPEGSource.cpp
index a4be2dd..ec81097 100644
--- a/media/libstagefright/JPEGSource.cpp
+++ b/media/libstagefright/JPEGSource.cpp
@@ -112,7 +112,8 @@ status_t JPEGSource::read(
*out = NULL;
int64_t seekTimeUs;
- if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
return UNKNOWN_ERROR;
}
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index f9251e1..2248e23 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -586,7 +586,8 @@ status_t MP3Source::read(
*out = NULL;
int64_t seekTimeUs;
- if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
int32_t bitrate;
if (!mMeta->findInt32(kKeyBitRate, &bitrate)) {
// bitrate is in bits/sec.
@@ -634,6 +635,7 @@ status_t MP3Source::read(
}
size_t frame_size;
+ int bitrate;
for (;;) {
ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
if (n < 4) {
@@ -646,7 +648,7 @@ status_t MP3Source::read(
uint32_t header = U32_AT((const uint8_t *)buffer->data());
if ((header & kMask) == (mFixedHeader & kMask)
- && get_mp3_frame_size(header, &frame_size)) {
+ && get_mp3_frame_size(header, &frame_size, NULL, NULL, &bitrate)) {
break;
}
@@ -683,7 +685,7 @@ status_t MP3Source::read(
buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs);
mCurrentPos += frame_size;
- mCurrentTimeUs += 1152 * 1000000 / 44100;
+ mCurrentTimeUs += frame_size * 8000ll / bitrate;
*out = buffer;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index a41b2f4..7cea629 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -428,6 +428,14 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
}
chunk_size = ntoh64(chunk_size);
data_offset += 8;
+
+ if (chunk_size < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return ERROR_MALFORMED;
+ }
+ } else if (chunk_size < 8) {
+ // The smallest valid chunk is 8 bytes long.
+ return ERROR_MALFORMED;
}
char chunk[5];
@@ -1460,12 +1468,45 @@ status_t MPEG4Source::read(
*out = NULL;
+ int64_t targetSampleTimeUs = -1;
+
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ uint32_t findFlags = 0;
+ switch (mode) {
+ case ReadOptions::SEEK_PREVIOUS_SYNC:
+ findFlags = SampleTable::kFlagBefore;
+ break;
+ case ReadOptions::SEEK_NEXT_SYNC:
+ findFlags = SampleTable::kFlagAfter;
+ break;
+ case ReadOptions::SEEK_CLOSEST_SYNC:
+ case ReadOptions::SEEK_CLOSEST:
+ findFlags = SampleTable::kFlagClosest;
+ break;
+ default:
+ CHECK(!"Should not be here.");
+ break;
+ }
+
uint32_t sampleIndex;
- status_t err = mSampleTable->findClosestSample(
+ status_t err = mSampleTable->findSampleAtTime(
seekTimeUs * mTimescale / 1000000,
- &sampleIndex, SampleTable::kSyncSample_Flag);
+ &sampleIndex, findFlags);
+
+ if (mode == ReadOptions::SEEK_CLOSEST) {
+ // We found the closest sample already, now we want the sync
+ // sample preceding it (or the sample itself of course), even
+ // if the subsequent sync sample is closer.
+ findFlags = SampleTable::kFlagBefore;
+ }
+
+ uint32_t syncSampleIndex;
+ if (err == OK) {
+ err = mSampleTable->findSyncSampleNear(
+ sampleIndex, &syncSampleIndex, findFlags);
+ }
if (err != OK) {
if (err == ERROR_OUT_OF_RANGE) {
@@ -1479,7 +1520,27 @@ status_t MPEG4Source::read(
return err;
}
- mCurrentSampleIndex = sampleIndex;
+ uint32_t sampleTime;
+ CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+ sampleIndex, NULL, NULL, &sampleTime));
+
+ if (mode == ReadOptions::SEEK_CLOSEST) {
+ targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
+ }
+
+#if 0
+ uint32_t syncSampleTime;
+ CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
+ syncSampleIndex, NULL, NULL, &syncSampleTime));
+
+ LOGI("seek to time %lld us => sample at time %lld us, "
+ "sync sample at time %lld us",
+ seekTimeUs,
+ sampleTime * 1000000ll / mTimescale,
+ syncSampleTime * 1000000ll / mTimescale);
+#endif
+
+ mCurrentSampleIndex = syncSampleIndex;
if (mBuffer != NULL) {
mBuffer->release();
mBuffer = NULL;
@@ -1528,6 +1589,12 @@ status_t MPEG4Source::read(
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
+
+ if (targetSampleTimeUs >= 0) {
+ mBuffer->meta_data()->setInt64(
+ kKeyTargetTime, targetSampleTimeUs);
+ }
+
++mCurrentSampleIndex;
}
@@ -1624,6 +1691,12 @@ status_t MPEG4Source::read(
mBuffer->meta_data()->clear();
mBuffer->meta_data()->setInt64(
kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
+
+ if (targetSampleTimeUs >= 0) {
+ mBuffer->meta_data()->setInt64(
+ kKeyTargetTime, targetSampleTimeUs);
+ }
+
++mCurrentSampleIndex;
*out = mBuffer;
@@ -1633,7 +1706,7 @@ status_t MPEG4Source::read(
}
}
-bool SniffMPEG4(
+static bool LegacySniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence) {
uint8_t header[8];
@@ -1657,5 +1730,83 @@ bool SniffMPEG4(
return false;
}
+static bool isCompatibleBrand(uint32_t fourcc) {
+ static const uint32_t kCompatibleBrands[] = {
+ FOURCC('i', 's', 'o', 'm'),
+ FOURCC('i', 's', 'o', '2'),
+ FOURCC('a', 'v', 'c', '1'),
+ FOURCC('3', 'g', 'p', '4'),
+ FOURCC('m', 'p', '4', '1'),
+ FOURCC('m', 'p', '4', '2'),
+ };
+
+ for (size_t i = 0;
+ i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
+ ++i) {
+ if (kCompatibleBrands[i] == fourcc) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Attempt to actually parse the 'ftyp' atom and determine if a suitable
+// compatible brand is present.
+static bool BetterSniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ uint8_t header[12];
+ if (source->readAt(0, header, 12) != 12
+ || memcmp("ftyp", &header[4], 4)) {
+ return false;
+ }
+
+ size_t atomSize = U32_AT(&header[0]);
+ if (atomSize < 16 || (atomSize % 4) != 0) {
+ return false;
+ }
+
+ bool success = false;
+ if (isCompatibleBrand(U32_AT(&header[8]))) {
+ success = true;
+ } else {
+ size_t numCompatibleBrands = (atomSize - 16) / 4;
+ for (size_t i = 0; i < numCompatibleBrands; ++i) {
+ uint8_t tmp[4];
+ if (source->readAt(16 + i * 4, tmp, 4) != 4) {
+ return false;
+ }
+
+ if (isCompatibleBrand(U32_AT(&tmp[0]))) {
+ success = true;
+ break;
+ }
+ }
+ }
+
+ if (!success) {
+ return false;
+ }
+
+ *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
+ *confidence = 0.3f;
+
+ return true;
+}
+
+bool SniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ if (BetterSniffMPEG4(source, mimeType, confidence)) {
+ return true;
+ }
+
+ if (LegacySniffMPEG4(source, mimeType, confidence)) {
+ LOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
+ return true;
+ }
+
+ return false;
+}
+
} // namespace android
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 2cf0ddf..baf9f4f 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MPEG4Writer"
+#include <utils/Log.h>
+
#include <arpa/inet.h>
#include <ctype.h>
@@ -24,62 +28,136 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/Utils.h>
+#include <media/mediarecorder.h>
+#include <cutils/properties.h>
+
+#include "include/ESDS.h"
namespace android {
class MPEG4Writer::Track {
public:
Track(MPEG4Writer *owner, const sp<MediaSource> &source);
+
~Track();
- status_t start();
+ status_t start(MetaData *params);
void stop();
+ void pause();
bool reachedEOS();
int64_t getDurationUs() const;
- void writeTrackHeader(int32_t trackID);
+ int64_t getEstimatedTrackSizeBytes() const;
+ void writeTrackHeader(int32_t trackID, bool use32BitOffset = true);
private:
MPEG4Writer *mOwner;
sp<MetaData> mMeta;
sp<MediaSource> mSource;
volatile bool mDone;
+ volatile bool mPaused;
+ volatile bool mResumed;
int64_t mMaxTimeStampUs;
+ int64_t mEstimatedTrackSizeBytes;
+ int32_t mTimeScale;
pthread_t mThread;
- struct SampleInfo {
- size_t size;
- off_t offset;
- int64_t timestamp;
+ // mNumSamples is used to track how many samples in mSampleSizes List.
+ // This is to reduce the cost associated with mSampleSizes.size() call,
+ // since it is O(n). Ideally, the fix should be in List class.
+ size_t mNumSamples;
+ List<size_t> mSampleSizes;
+ bool mSamplesHaveSameSize;
+
+ List<MediaBuffer *> mChunkSamples;
+ List<off_t> mChunkOffsets;
+
+ struct StscTableEntry {
+
+ StscTableEntry(uint32_t chunk, uint32_t samples, uint32_t id)
+ : firstChunk(chunk),
+ samplesPerChunk(samples),
+ sampleDescriptionId(id) {}
+
+ uint32_t firstChunk;
+ uint32_t samplesPerChunk;
+ uint32_t sampleDescriptionId;
};
- List<SampleInfo> mSampleInfos;
+ List<StscTableEntry> mStscTableEntries;
+
+ List<int32_t> mStssTableEntries;
+ List<int64_t> mChunkDurations;
+
+ struct SttsTableEntry {
+
+ SttsTableEntry(uint32_t count, uint32_t durationUs)
+ : sampleCount(count), sampleDurationUs(durationUs) {}
+
+ uint32_t sampleCount;
+ uint32_t sampleDurationUs;
+ };
+ List<SttsTableEntry> mSttsTableEntries;
void *mCodecSpecificData;
size_t mCodecSpecificDataSize;
+ bool mGotAllCodecSpecificData;
+ bool mTrackingProgressStatus;
bool mReachedEOS;
+ int64_t mStartTimestampUs;
+ int64_t mPreviousTrackTimeUs;
+ int64_t mTrackEveryTimeDurationUs;
static void *ThreadWrapper(void *me);
void threadEntry();
+ status_t makeAVCCodecSpecificData(
+ const uint8_t *data, size_t size);
+ void writeOneChunk(bool isAvc);
+
+ // Track authoring progress status
+ void trackProgressStatus(int64_t timeUs, status_t err = OK);
+ void initTrackingProgressStatus(MetaData *params);
+
+ // Utilities for collecting statistical data
+ void logStatisticalData(bool isAudio);
+ void findMinAvgMaxSampleDurationMs(
+ int32_t *min, int32_t *avg, int32_t *max);
+ void findMinMaxChunkDurations(int64_t *min, int64_t *max);
+
+ void getCodecSpecificDataFromInputFormatIfPossible();
+
Track(const Track &);
Track &operator=(const Track &);
};
+#define USE_NALLEN_FOUR 1
+
MPEG4Writer::MPEG4Writer(const char *filename)
: mFile(fopen(filename, "wb")),
+ mUse32BitOffset(true),
+ mPaused(false),
+ mStarted(false),
mOffset(0),
- mMdatOffset(0) {
+ mMdatOffset(0),
+ mEstimatedMoovBoxSize(0),
+ mInterleaveDurationUs(1000000) {
CHECK(mFile != NULL);
}
MPEG4Writer::MPEG4Writer(int fd)
: mFile(fdopen(fd, "wb")),
+ mUse32BitOffset(true),
+ mPaused(false),
+ mStarted(false),
mOffset(0),
- mMdatOffset(0) {
+ mMdatOffset(0),
+ mEstimatedMoovBoxSize(0),
+ mInterleaveDurationUs(1000000) {
CHECK(mFile != NULL);
}
@@ -100,23 +178,10 @@ status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
return OK;
}
-status_t MPEG4Writer::start() {
- if (mFile == NULL) {
- return UNKNOWN_ERROR;
- }
-
- beginBox("ftyp");
- writeFourcc("isom");
- writeInt32(0);
- writeFourcc("isom");
- endBox();
-
- mMdatOffset = mOffset;
- write("\x00\x00\x00\x01mdat????????", 16);
-
+status_t MPEG4Writer::startTracks(MetaData *params) {
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
- status_t err = (*it)->start();
+ status_t err = (*it)->start(params);
if (err != OK) {
for (List<Track *>::iterator it2 = mTracks.begin();
@@ -127,34 +192,190 @@ status_t MPEG4Writer::start() {
return err;
}
}
+ return OK;
+}
+
+int64_t MPEG4Writer::estimateMoovBoxSize(int32_t bitRate) {
+ // This implementation is highly experimental/heurisitic.
+ //
+ // Statistical analysis shows that metadata usually accounts
+ // for a small portion of the total file size, usually < 0.6%.
+ // Currently, lets set to 0.4% for now.
+
+ // The default MIN_MOOV_BOX_SIZE is set to 0.4% x 1MB,
+ // where 1MB is the common file size limit for MMS application.
+ // The default MAX _MOOV_BOX_SIZE value is based on about 4
+ // minute video recording with a bit rate about 3 Mbps, because
+ // statistics also show that most of the video captured are going
+ // to be less than 3 minutes.
+
+ // If the estimation is wrong, we will pay the price of wasting
+ // some reserved space. This should not happen so often statistically.
+ static const int32_t factor = mUse32BitOffset? 1: 2;
+ static const int64_t MIN_MOOV_BOX_SIZE = 4 * 1024; // 4 KB
+ static const int64_t MAX_MOOV_BOX_SIZE = (180 * 3000000 * 6LL / 8000);
+ int64_t size = MIN_MOOV_BOX_SIZE;
+
+ if (mMaxFileSizeLimitBytes != 0) {
+ size = mMaxFileSizeLimitBytes * 4 / 1000;
+ } else if (mMaxFileDurationLimitUs != 0) {
+ if (bitRate <= 0) {
+ // We could not estimate the file size since bitRate is not set.
+ size = MIN_MOOV_BOX_SIZE;
+ } else {
+ size = ((mMaxFileDurationLimitUs * bitRate * 4) / 1000 / 8000000);
+ }
+ }
+ if (size < MIN_MOOV_BOX_SIZE) {
+ size = MIN_MOOV_BOX_SIZE;
+ }
+
+ // Any long duration recording will be probably end up with
+ // non-streamable mp4 file.
+ if (size > MAX_MOOV_BOX_SIZE) {
+ size = MAX_MOOV_BOX_SIZE;
+ }
+
+ LOGI("limits: %lld/%lld bytes/us, bit rate: %d bps and the estimated"
+ " moov size %lld bytes",
+ mMaxFileSizeLimitBytes, mMaxFileDurationLimitUs, bitRate, size);
+ return factor * size;
+}
+
+status_t MPEG4Writer::start(MetaData *param) {
+ if (mFile == NULL) {
+ return UNKNOWN_ERROR;
+ }
+
+ int32_t use64BitOffset;
+ if (param &&
+ param->findInt32(kKey64BitFileOffset, &use64BitOffset) &&
+ use64BitOffset) {
+ mUse32BitOffset = false;
+ }
+ // System property can overwrite the file offset bits parameter
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-64bits", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ mUse32BitOffset = false;
+ }
+
+ mStartTimestampUs = -1;
+
+ if (mStarted) {
+ if (mPaused) {
+ mPaused = false;
+ return startTracks(param);
+ }
+ return OK;
+ }
+
+ if (!param ||
+ !param->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK(mTimeScale > 0);
+ LOGV("movie time scale: %d", mTimeScale);
+
+ mStreamableFile = true;
+ mWriteMoovBoxToMemory = false;
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+
+ beginBox("ftyp");
+ {
+ int32_t fileType;
+ if (param && param->findInt32(kKeyFileType, &fileType) &&
+ fileType != OUTPUT_FORMAT_MPEG_4) {
+ writeFourcc("3gp4");
+ } else {
+ writeFourcc("isom");
+ }
+ }
+ writeInt32(0);
+ writeFourcc("isom");
+ writeFourcc("3gp4");
+ endBox();
+
+ mFreeBoxOffset = mOffset;
+
+ if (mEstimatedMoovBoxSize == 0) {
+ int32_t bitRate = -1;
+ if (param) {
+ param->findInt32(kKeyBitRate, &bitRate);
+ }
+ mEstimatedMoovBoxSize = estimateMoovBoxSize(bitRate);
+ }
+ CHECK(mEstimatedMoovBoxSize >= 8);
+ fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ writeInt32(mEstimatedMoovBoxSize);
+ write("free", 4);
+
+ mMdatOffset = mFreeBoxOffset + mEstimatedMoovBoxSize;
+ mOffset = mMdatOffset;
+ fseeko(mFile, mMdatOffset, SEEK_SET);
+ if (mUse32BitOffset) {
+ write("????mdat", 8);
+ } else {
+ write("\x00\x00\x00\x01mdat????????", 16);
+ }
+ status_t err = startTracks(param);
+ if (err != OK) {
+ return err;
+ }
+ mStarted = true;
return OK;
}
+void MPEG4Writer::pause() {
+ if (mFile == NULL) {
+ return;
+ }
+ mPaused = true;
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ (*it)->pause();
+ }
+}
+
void MPEG4Writer::stop() {
if (mFile == NULL) {
return;
}
- int64_t max_duration = 0;
+ int64_t maxDurationUs = 0;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
(*it)->stop();
- int64_t duration = (*it)->getDurationUs();
- if (duration > max_duration) {
- max_duration = duration;
+ int64_t durationUs = (*it)->getDurationUs();
+ if (durationUs > maxDurationUs) {
+ maxDurationUs = durationUs;
}
}
+
// Fix up the size of the 'mdat' chunk.
- fseek(mFile, mMdatOffset + 8, SEEK_SET);
- int64_t size = mOffset - mMdatOffset;
- size = hton64(size);
- fwrite(&size, 1, 8, mFile);
- fseek(mFile, mOffset, SEEK_SET);
+ if (mUse32BitOffset) {
+ fseeko(mFile, mMdatOffset, SEEK_SET);
+ int32_t size = htonl(static_cast<int32_t>(mOffset - mMdatOffset));
+ fwrite(&size, 1, 4, mFile);
+ } else {
+ fseeko(mFile, mMdatOffset + 8, SEEK_SET);
+ int64_t size = mOffset - mMdatOffset;
+ size = hton64(size);
+ fwrite(&size, 1, 8, mFile);
+ }
+ fseeko(mFile, mOffset, SEEK_SET);
time_t now = time(NULL);
+ const off_t moovOffset = mOffset;
+ mWriteMoovBoxToMemory = true;
+ mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
+ mMoovBoxBufferOffset = 0;
+ CHECK(mMoovBoxBuffer != NULL);
+ int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
beginBox("moov");
@@ -162,9 +383,9 @@ void MPEG4Writer::stop() {
writeInt32(0); // version=0, flags=0
writeInt32(now); // creation time
writeInt32(now); // modification time
- writeInt32(1000); // timescale
- writeInt32(max_duration / 1000);
- writeInt32(0x10000); // rate
+ writeInt32(mTimeScale); // mvhd timescale
+ writeInt32(duration);
+ writeInt32(0x10000); // rate: 1.0
writeInt16(0x100); // volume
writeInt16(0); // reserved
writeInt32(0); // reserved
@@ -190,19 +411,54 @@ void MPEG4Writer::stop() {
int32_t id = 1;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it, ++id) {
- (*it)->writeTrackHeader(id);
+ (*it)->writeTrackHeader(id, mUse32BitOffset);
}
endBox(); // moov
+ mWriteMoovBoxToMemory = false;
+ if (mStreamableFile) {
+ CHECK(mMoovBoxBufferOffset + 8 <= mEstimatedMoovBoxSize);
+
+ // Moov box
+ fseeko(mFile, mFreeBoxOffset, SEEK_SET);
+ mOffset = mFreeBoxOffset;
+ write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
+
+ // Free box
+ fseeko(mFile, mOffset, SEEK_SET);
+ writeInt32(mEstimatedMoovBoxSize - mMoovBoxBufferOffset);
+ write("free", 4);
+
+ // Free temp memory
+ free(mMoovBoxBuffer);
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+ } else {
+ LOGI("The mp4 file will not be streamable.");
+ }
+
CHECK(mBoxes.empty());
+ fflush(mFile);
fclose(mFile);
mFile = NULL;
+ mStarted = false;
}
-off_t MPEG4Writer::addSample(MediaBuffer *buffer) {
- Mutex::Autolock autoLock(mLock);
+status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
+ mInterleaveDurationUs = durationUs;
+ return OK;
+}
+void MPEG4Writer::lock() {
+ mLock.lock();
+}
+
+void MPEG4Writer::unlock() {
+ mLock.unlock();
+}
+
+off_t MPEG4Writer::addSample_l(MediaBuffer *buffer) {
off_t old_offset = mOffset;
fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
@@ -213,31 +469,91 @@ off_t MPEG4Writer::addSample(MediaBuffer *buffer) {
return old_offset;
}
-off_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
- Mutex::Autolock autoLock(mLock);
+static void StripStartcode(MediaBuffer *buffer) {
+ if (buffer->range_length() < 4) {
+ return;
+ }
+
+ const uint8_t *ptr =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+
+ if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
+ buffer->set_range(
+ buffer->range_offset() + 4, buffer->range_length() - 4);
+ }
+}
+off_t MPEG4Writer::addLengthPrefixedSample_l(MediaBuffer *buffer) {
off_t old_offset = mOffset;
size_t length = buffer->range_length();
+
+#if USE_NALLEN_FOUR
+ uint8_t x = length >> 24;
+ fwrite(&x, 1, 1, mFile);
+ x = (length >> 16) & 0xff;
+ fwrite(&x, 1, 1, mFile);
+ x = (length >> 8) & 0xff;
+ fwrite(&x, 1, 1, mFile);
+ x = length & 0xff;
+ fwrite(&x, 1, 1, mFile);
+#else
CHECK(length < 65536);
uint8_t x = length >> 8;
fwrite(&x, 1, 1, mFile);
x = length & 0xff;
fwrite(&x, 1, 1, mFile);
+#endif
fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
1, length, mFile);
+#if USE_NALLEN_FOUR
+ mOffset += length + 4;
+#else
mOffset += length + 2;
+#endif
return old_offset;
}
+size_t MPEG4Writer::write(
+ const void *ptr, size_t size, size_t nmemb, FILE *stream) {
+
+ const size_t bytes = size * nmemb;
+ if (mWriteMoovBoxToMemory) {
+ off_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
+ if (moovBoxSize > mEstimatedMoovBoxSize) {
+ for (List<off_t>::iterator it = mBoxes.begin();
+ it != mBoxes.end(); ++it) {
+ (*it) += mOffset;
+ }
+ fseeko(mFile, mOffset, SEEK_SET);
+ fwrite(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, stream);
+ fwrite(ptr, size, nmemb, stream);
+ mOffset += (bytes + mMoovBoxBufferOffset);
+ free(mMoovBoxBuffer);
+ mMoovBoxBuffer = NULL;
+ mMoovBoxBufferOffset = 0;
+ mWriteMoovBoxToMemory = false;
+ mStreamableFile = false;
+ } else {
+ memcpy(mMoovBoxBuffer + mMoovBoxBufferOffset, ptr, bytes);
+ mMoovBoxBufferOffset += bytes;
+ }
+ } else {
+ fwrite(ptr, size, nmemb, stream);
+ mOffset += bytes;
+ }
+ return bytes;
+}
+
void MPEG4Writer::beginBox(const char *fourcc) {
CHECK_EQ(strlen(fourcc), 4);
- mBoxes.push_back(mOffset);
+ mBoxes.push_back(mWriteMoovBoxToMemory?
+ mMoovBoxBufferOffset: mOffset);
writeInt32(0);
writeFourcc(fourcc);
@@ -249,51 +565,77 @@ void MPEG4Writer::endBox() {
off_t offset = *--mBoxes.end();
mBoxes.erase(--mBoxes.end());
- fseek(mFile, offset, SEEK_SET);
- writeInt32(mOffset - offset);
- mOffset -= 4;
- fseek(mFile, mOffset, SEEK_SET);
+ if (mWriteMoovBoxToMemory) {
+ int32_t x = htonl(mMoovBoxBufferOffset - offset);
+ memcpy(mMoovBoxBuffer + offset, &x, 4);
+ } else {
+ fseeko(mFile, offset, SEEK_SET);
+ writeInt32(mOffset - offset);
+ mOffset -= 4;
+ fseeko(mFile, mOffset, SEEK_SET);
+ }
}
void MPEG4Writer::writeInt8(int8_t x) {
- fwrite(&x, 1, 1, mFile);
- ++mOffset;
+ write(&x, 1, 1, mFile);
}
void MPEG4Writer::writeInt16(int16_t x) {
x = htons(x);
- fwrite(&x, 1, 2, mFile);
- mOffset += 2;
+ write(&x, 1, 2, mFile);
}
void MPEG4Writer::writeInt32(int32_t x) {
x = htonl(x);
- fwrite(&x, 1, 4, mFile);
- mOffset += 4;
+ write(&x, 1, 4, mFile);
}
void MPEG4Writer::writeInt64(int64_t x) {
x = hton64(x);
- fwrite(&x, 1, 8, mFile);
- mOffset += 8;
+ write(&x, 1, 8, mFile);
}
void MPEG4Writer::writeCString(const char *s) {
size_t n = strlen(s);
-
- fwrite(s, 1, n + 1, mFile);
- mOffset += n + 1;
+ write(s, 1, n + 1, mFile);
}
void MPEG4Writer::writeFourcc(const char *s) {
CHECK_EQ(strlen(s), 4);
- fwrite(s, 1, 4, mFile);
- mOffset += 4;
+ write(s, 1, 4, mFile);
}
void MPEG4Writer::write(const void *data, size_t size) {
- fwrite(data, 1, size, mFile);
- mOffset += size;
+ write(data, 1, size, mFile);
+}
+
+bool MPEG4Writer::exceedsFileSizeLimit() {
+ // No limit
+ if (mMaxFileSizeLimitBytes == 0) {
+ return false;
+ }
+
+ int64_t nTotalBytesEstimate = static_cast<int64_t>(mEstimatedMoovBoxSize);
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes();
+ }
+ return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes);
+}
+
+bool MPEG4Writer::exceedsFileDurationLimit() {
+ // No limit
+ if (mMaxFileDurationLimitUs == 0) {
+ return false;
+ }
+
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it) {
+ if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) {
+ return true;
+ }
+ }
+ return false;
}
bool MPEG4Writer::reachedEOS() {
@@ -309,6 +651,26 @@ bool MPEG4Writer::reachedEOS() {
return allDone;
}
+void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
+ LOGI("setStartTimestampUs: %lld", timeUs);
+ CHECK(timeUs >= 0);
+ Mutex::Autolock autoLock(mLock);
+ if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
+ mStartTimestampUs = timeUs;
+ LOGI("Earliest track starting time: %lld", mStartTimestampUs);
+ }
+}
+
+int64_t MPEG4Writer::getStartTimestampUs() {
+ Mutex::Autolock autoLock(mLock);
+ return mStartTimestampUs;
+}
+
+size_t MPEG4Writer::numTracks() {
+ Mutex::Autolock autolock(mLock);
+ return mTracks.size();
+}
+
////////////////////////////////////////////////////////////////////////////////
MPEG4Writer::Track::Track(
@@ -317,10 +679,52 @@ MPEG4Writer::Track::Track(
mMeta(source->getFormat()),
mSource(source),
mDone(false),
+ mPaused(false),
+ mResumed(false),
mMaxTimeStampUs(0),
+ mEstimatedTrackSizeBytes(0),
+ mSamplesHaveSameSize(true),
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
+ mGotAllCodecSpecificData(false),
mReachedEOS(false) {
+ getCodecSpecificDataFromInputFormatIfPossible();
+
+ if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
+ mTimeScale = 1000;
+ }
+ CHECK(mTimeScale > 0);
+}
+
+void MPEG4Writer::Track::getCodecSpecificDataFromInputFormatIfPossible() {
+ const char *mime;
+ CHECK(mMeta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (mMeta->findData(kKeyAVCC, &type, &data, &size)) {
+ mCodecSpecificData = malloc(size);
+ mCodecSpecificDataSize = size;
+ memcpy(mCodecSpecificData, data, size);
+ mGotAllCodecSpecificData = true;
+ }
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
+ || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (mMeta->findData(kKeyESDS, &type, &data, &size)) {
+ ESDS esds(data, size);
+ if (esds.getCodecSpecificInfo(&data, &size) == OK) {
+ mCodecSpecificData = malloc(size);
+ mCodecSpecificDataSize = size;
+ memcpy(mCodecSpecificData, data, size);
+ mGotAllCodecSpecificData = true;
+ }
+ }
+ }
}
MPEG4Writer::Track::~Track() {
@@ -332,9 +736,38 @@ MPEG4Writer::Track::~Track() {
}
}
-status_t MPEG4Writer::Track::start() {
- status_t err = mSource->start();
+void MPEG4Writer::Track::initTrackingProgressStatus(MetaData *params) {
+ LOGV("initTrackingProgressStatus");
+ mPreviousTrackTimeUs = -1;
+ mTrackingProgressStatus = false;
+ mTrackEveryTimeDurationUs = 0;
+ {
+ int64_t timeUs;
+ if (params && params->findInt64(kKeyTrackTimeStatus, &timeUs)) {
+ LOGV("Receive request to track progress status for every %lld us", timeUs);
+ mTrackEveryTimeDurationUs = timeUs;
+ mTrackingProgressStatus = true;
+ }
+ }
+}
+status_t MPEG4Writer::Track::start(MetaData *params) {
+ if (!mDone && mPaused) {
+ mPaused = false;
+ mResumed = true;
+ return OK;
+ }
+
+ int64_t startTimeUs;
+ if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
+ startTimeUs = 0;
+ }
+
+ initTrackingProgressStatus(params);
+
+ sp<MetaData> meta = new MetaData;
+ meta->setInt64(kKeyTime, startTimeUs);
+ status_t err = mSource->start(meta.get());
if (err != OK) {
mDone = mReachedEOS = true;
return err;
@@ -347,6 +780,7 @@ status_t MPEG4Writer::Track::start() {
mDone = false;
mMaxTimeStampUs = 0;
mReachedEOS = false;
+ mEstimatedTrackSizeBytes = 0;
pthread_create(&mThread, &attr, ThreadWrapper, this);
pthread_attr_destroy(&attr);
@@ -354,6 +788,10 @@ status_t MPEG4Writer::Track::start() {
return OK;
}
+void MPEG4Writer::Track::pause() {
+ mPaused = true;
+}
+
void MPEG4Writer::Track::stop() {
if (mDone) {
return;
@@ -380,73 +818,186 @@ void *MPEG4Writer::Track::ThreadWrapper(void *me) {
return NULL;
}
+#include <ctype.h>
+static void hexdump(const void *_data, size_t size) {
+ const uint8_t *data = (const uint8_t *)_data;
+ size_t offset = 0;
+ while (offset < size) {
+ printf("0x%04x ", offset);
+
+ size_t n = size - offset;
+ if (n > 16) {
+ n = 16;
+ }
+
+ for (size_t i = 0; i < 16; ++i) {
+ if (i == 8) {
+ printf(" ");
+ }
+
+ if (offset + i < size) {
+ printf("%02x ", data[offset + i]);
+ } else {
+ printf(" ");
+ }
+ }
+
+ printf(" ");
+
+ for (size_t i = 0; i < n; ++i) {
+ if (isprint(data[offset + i])) {
+ printf("%c", data[offset + i]);
+ } else {
+ printf(".");
+ }
+ }
+
+ printf("\n");
+
+ offset += 16;
+ }
+}
+
+
+status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
+ const uint8_t *data, size_t size) {
+ // hexdump(data, size);
+
+ if (mCodecSpecificData != NULL) {
+ LOGE("Already have codec specific data");
+ return ERROR_MALFORMED;
+ }
+
+ if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
+ LOGE("Must start with a start code");
+ return ERROR_MALFORMED;
+ }
+
+ size_t picParamOffset = 4;
+ while (picParamOffset + 3 < size
+ && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
+ ++picParamOffset;
+ }
+
+ if (picParamOffset + 3 >= size) {
+ LOGE("Could not find start-code for pictureParameterSet");
+ return ERROR_MALFORMED;
+ }
+
+ size_t seqParamSetLength = picParamOffset - 4;
+ size_t picParamSetLength = size - picParamOffset - 4;
+
+ mCodecSpecificDataSize =
+ 6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;
+
+ mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ uint8_t *header = (uint8_t *)mCodecSpecificData;
+ header[0] = 1;
+ header[1] = 0x42; // profile
+ header[2] = 0x80;
+ header[3] = 0x1e; // level
+
+#if USE_NALLEN_FOUR
+ header[4] = 0xfc | 3; // length size == 4 bytes
+#else
+ header[4] = 0xfc | 1; // length size == 2 bytes
+#endif
+
+ header[5] = 0xe0 | 1;
+ header[6] = seqParamSetLength >> 8;
+ header[7] = seqParamSetLength & 0xff;
+ memcpy(&header[8], &data[4], seqParamSetLength);
+ header += 8 + seqParamSetLength;
+ header[0] = 1;
+ header[1] = picParamSetLength >> 8;
+ header[2] = picParamSetLength & 0xff;
+ memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);
+
+ return OK;
+}
+
+static bool collectStatisticalData() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.record-stats", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ return true;
+ }
+ return false;
+}
+
void MPEG4Writer::Track::threadEntry() {
sp<MetaData> meta = mSource->getFormat();
const char *mime;
meta->findCString(kKeyMIMEType, &mime);
- bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ bool is_mpeg4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+ !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
bool is_avc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
+ bool is_audio = !strncasecmp(mime, "audio/", 6);
int32_t count = 0;
-
+ const int64_t interleaveDurationUs = mOwner->interleaveDuration();
+ int64_t chunkTimestampUs = 0;
+ int32_t nChunks = 0;
+ int32_t nZeroLengthFrames = 0;
+ int64_t lastTimestampUs = 0; // Previous sample time stamp in ms
+ int64_t lastDurationUs = 0; // Between the previous two samples in ms
+ int32_t sampleCount = 1; // Sample count in the current stts table entry
+ uint32_t previousSampleSize = 0; // Size of the previous sample
+ int64_t previousPausedDurationUs = 0;
+ sp<MetaData> meta_data;
+ bool collectStats = collectStatisticalData();
+
+ mNumSamples = 0;
+ status_t err = OK;
MediaBuffer *buffer;
- while (!mDone && mSource->read(&buffer) == OK) {
+ while (!mDone && (err = mSource->read(&buffer)) == OK) {
if (buffer->range_length() == 0) {
buffer->release();
buffer = NULL;
+ ++nZeroLengthFrames;
+ continue;
+ }
+ // If the codec specific data has not been received yet, delay pause.
+ // After the codec specific data is received, discard what we received
+ // when the track is to be paused.
+ if (mPaused && !mResumed) {
+ buffer->release();
+ buffer = NULL;
continue;
}
++count;
- if (is_avc && count < 3) {
- size_t size = buffer->range_length();
-
- switch (count) {
- case 1:
- {
- CHECK_EQ(mCodecSpecificData, NULL);
- mCodecSpecificData = malloc(size + 8);
- uint8_t *header = (uint8_t *)mCodecSpecificData;
- header[0] = 1;
- header[1] = 0x42; // profile
- header[2] = 0x80;
- header[3] = 0x1e; // level
- header[4] = 0xfc | 3;
- header[5] = 0xe0 | 1;
- header[6] = size >> 8;
- header[7] = size & 0xff;
- memcpy(&header[8],
- (const uint8_t *)buffer->data() + buffer->range_offset(),
- size);
-
- mCodecSpecificDataSize = size + 8;
- break;
- }
-
- case 2:
- {
- size_t offset = mCodecSpecificDataSize;
- mCodecSpecificDataSize += size + 3;
- mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
- uint8_t *header = (uint8_t *)mCodecSpecificData;
- header[offset] = 1;
- header[offset + 1] = size >> 8;
- header[offset + 2] = size & 0xff;
- memcpy(&header[offset + 3],
- (const uint8_t *)buffer->data() + buffer->range_offset(),
- size);
- break;
- }
+ int32_t isCodecConfig;
+ if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
+ && isCodecConfig) {
+ CHECK(!mGotAllCodecSpecificData);
+
+ if (is_avc) {
+ status_t err = makeAVCCodecSpecificData(
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+ CHECK_EQ(OK, err);
+ } else if (is_mpeg4) {
+ mCodecSpecificDataSize = buffer->range_length();
+ mCodecSpecificData = malloc(mCodecSpecificDataSize);
+ memcpy(mCodecSpecificData,
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
}
buffer->release();
buffer = NULL;
+ mGotAllCodecSpecificData = true;
continue;
- }
+ } else if (!mGotAllCodecSpecificData &&
+ count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
+ // The TI mpeg4 encoder does not properly set the
+ // codec-specific-data flag.
- if (mCodecSpecificData == NULL && is_mpeg4) {
const uint8_t *data =
(const uint8_t *)buffer->data() + buffer->range_offset();
@@ -474,56 +1025,417 @@ void MPEG4Writer::Track::threadEntry() {
memcpy(mCodecSpecificData, data, offset);
buffer->set_range(buffer->range_offset() + offset, size - offset);
+
+ if (size == offset) {
+ buffer->release();
+ buffer = NULL;
+
+ continue;
+ }
+
+ mGotAllCodecSpecificData = true;
+ } else if (!mGotAllCodecSpecificData && is_avc && count < 3) {
+ // The TI video encoder does not flag codec specific data
+ // as such and also splits up SPS and PPS across two buffers.
+
+ const uint8_t *data =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+
+ size_t size = buffer->range_length();
+
+ CHECK(count == 2 || mCodecSpecificData == NULL);
+
+ size_t offset = mCodecSpecificDataSize;
+ mCodecSpecificDataSize += size + 4;
+ mCodecSpecificData =
+ realloc(mCodecSpecificData, mCodecSpecificDataSize);
+
+ memcpy((uint8_t *)mCodecSpecificData + offset,
+ "\x00\x00\x00\x01", 4);
+
+ memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);
+
+ buffer->release();
+ buffer = NULL;
+
+ if (count == 2) {
+ void *tmp = mCodecSpecificData;
+ size = mCodecSpecificDataSize;
+ mCodecSpecificData = NULL;
+ mCodecSpecificDataSize = 0;
+
+ status_t err = makeAVCCodecSpecificData(
+ (const uint8_t *)tmp, size);
+ free(tmp);
+ tmp = NULL;
+ CHECK_EQ(OK, err);
+
+ mGotAllCodecSpecificData = true;
+ }
+
+ continue;
}
- off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
- : mOwner->addSample(buffer);
+ if (!mGotAllCodecSpecificData) {
+ mGotAllCodecSpecificData = true;
+ }
+
+ // Make a deep copy of the MediaBuffer and Metadata and release
+ // the original as soon as we can
+ MediaBuffer *copy = new MediaBuffer(buffer->range_length());
+ memcpy(copy->data(), (uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+ copy->set_range(0, buffer->range_length());
+ meta_data = new MetaData(*buffer->meta_data().get());
+ buffer->release();
+ buffer = NULL;
+
+ if (is_avc) StripStartcode(copy);
+
+ size_t sampleSize;
+ sampleSize = is_avc
+#if USE_NALLEN_FOUR
+ ? copy->range_length() + 4
+#else
+ ? copy->range_length() + 2
+#endif
+ : copy->range_length();
+
+ // Max file size or duration handling
+ mEstimatedTrackSizeBytes += sampleSize;
+ if (mOwner->exceedsFileSizeLimit()) {
+ mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+ break;
+ }
+ if (mOwner->exceedsFileDurationLimit()) {
+ mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+ break;
+ }
- SampleInfo info;
- info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length();
- info.offset = offset;
+
+ int32_t isSync = false;
+ meta_data->findInt32(kKeyIsSyncFrame, &isSync);
int64_t timestampUs;
- CHECK(buffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+ CHECK(meta_data->findInt64(kKeyTime, &timestampUs));
+
+////////////////////////////////////////////////////////////////////////////////
+ if (mSampleSizes.empty()) {
+ mStartTimestampUs = timestampUs;
+ mOwner->setStartTimestampUs(mStartTimestampUs);
+ }
+
+ if (mResumed) {
+ previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - lastDurationUs);
+ mResumed = false;
+ }
+ timestampUs -= previousPausedDurationUs;
+ LOGV("time stamp: %lld and previous paused duration %lld",
+ timestampUs, previousPausedDurationUs);
if (timestampUs > mMaxTimeStampUs) {
mMaxTimeStampUs = timestampUs;
}
- // Our timestamp is in ms.
- info.timestamp = (timestampUs + 500) / 1000;
+ mSampleSizes.push_back(sampleSize);
+ ++mNumSamples;
+ if (mNumSamples > 2) {
+ if (lastDurationUs != timestampUs - lastTimestampUs) {
+ SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
+ mSttsTableEntries.push_back(sttsEntry);
+ sampleCount = 1;
+ } else {
+ ++sampleCount;
+ }
+ }
+ if (mSamplesHaveSameSize) {
+ if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
+ mSamplesHaveSameSize = false;
+ }
+ previousSampleSize = sampleSize;
+ }
+ lastDurationUs = timestampUs - lastTimestampUs;
+ lastTimestampUs = timestampUs;
- mSampleInfos.push_back(info);
+ if (isSync != 0) {
+ mStssTableEntries.push_back(mNumSamples);
+ }
+
+ if (mTrackingProgressStatus) {
+ if (mPreviousTrackTimeUs <= 0) {
+ mPreviousTrackTimeUs = mStartTimestampUs;
+ }
+ trackProgressStatus(timestampUs);
+ }
+ if (mOwner->numTracks() == 1) {
+ off_t offset = is_avc? mOwner->addLengthPrefixedSample_l(copy)
+ : mOwner->addSample_l(copy);
+ if (mChunkOffsets.empty()) {
+ mChunkOffsets.push_back(offset);
+ }
+ copy->release();
+ copy = NULL;
+ continue;
+ }
+
+ mChunkSamples.push_back(copy);
+ if (interleaveDurationUs == 0) {
+ StscTableEntry stscEntry(++nChunks, 1, 1);
+ mStscTableEntries.push_back(stscEntry);
+ writeOneChunk(is_avc);
+ } else {
+ if (chunkTimestampUs == 0) {
+ chunkTimestampUs = timestampUs;
+ } else {
+ if (timestampUs - chunkTimestampUs > interleaveDurationUs) {
+ ++nChunks;
+ if (collectStats) {
+ mChunkDurations.push_back(timestampUs - chunkTimestampUs);
+ }
+ if (nChunks == 1 || // First chunk
+ (--(mStscTableEntries.end()))->samplesPerChunk !=
+ mChunkSamples.size()) {
+ StscTableEntry stscEntry(nChunks,
+ mChunkSamples.size(), 1);
+ mStscTableEntries.push_back(stscEntry);
+ }
+ writeOneChunk(is_avc);
+ chunkTimestampUs = timestampUs;
+ }
+ }
+ }
- buffer->release();
- buffer = NULL;
}
+ if (mSampleSizes.empty()) {
+ err = UNKNOWN_ERROR;
+ }
+ mOwner->trackProgressStatus(this, -1, err);
+
+ // Last chunk
+ if (mOwner->numTracks() == 1) {
+ StscTableEntry stscEntry(1, mNumSamples, 1);
+ mStscTableEntries.push_back(stscEntry);
+ } else if (!mChunkSamples.empty()) {
+ ++nChunks;
+ StscTableEntry stscEntry(nChunks, mChunkSamples.size(), 1);
+ mStscTableEntries.push_back(stscEntry);
+ writeOneChunk(is_avc);
+ }
+
+ // We don't really know how long the last frame lasts, since
+ // there is no frame time after it, just repeat the previous
+ // frame's duration.
+ if (mNumSamples == 1) {
+ lastDurationUs = 0; // A single sample's duration
+ } else {
+ ++sampleCount; // Count for the last sample
+ }
+ SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
+ mSttsTableEntries.push_back(sttsEntry);
mReachedEOS = true;
+ LOGI("Received total/0-length (%d/%d) buffers and encoded %d frames - %s",
+ count, nZeroLengthFrames, mNumSamples, is_audio? "audio": "video");
+
+ logStatisticalData(is_audio);
+}
+
+void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
+ LOGV("trackProgressStatus: %lld us", timeUs);
+ if (mTrackEveryTimeDurationUs > 0 &&
+ timeUs - mPreviousTrackTimeUs >= mTrackEveryTimeDurationUs) {
+ LOGV("Fire time tracking progress status at %lld us", timeUs);
+ mOwner->trackProgressStatus(this, timeUs - mPreviousTrackTimeUs, err);
+ mPreviousTrackTimeUs = timeUs;
+ }
+}
+
+void MPEG4Writer::trackProgressStatus(
+ const MPEG4Writer::Track* track, int64_t timeUs, status_t err) {
+ Mutex::Autolock lock(mLock);
+ int32_t nTracks = mTracks.size();
+ CHECK(nTracks >= 1);
+ CHECK(nTracks < 64); // Arbitrary number
+
+ int32_t trackNum = 0;
+#if 0
+ // In the worst case, we can put the trackNum
+ // along with MEDIA_RECORDER_INFO_COMPLETION_STATUS
+ // to report the progress.
+ for (List<Track *>::iterator it = mTracks.begin();
+ it != mTracks.end(); ++it, ++trackNum) {
+ if (track == (*it)) {
+ break;
+ }
+ }
+#endif
+ CHECK(trackNum < nTracks);
+ trackNum <<= 16;
+
+ // Error notification
+ // Do not consider ERROR_END_OF_STREAM an error
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ notify(MEDIA_RECORDER_EVENT_ERROR,
+ trackNum | MEDIA_RECORDER_ERROR_UNKNOWN,
+ err);
+ return;
+ }
+
+ if (timeUs == -1) {
+ // Send completion notification
+ notify(MEDIA_RECORDER_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_INFO_COMPLETION_STATUS,
+ err);
+ return;
+ } else {
+ // Send progress status
+ notify(MEDIA_RECORDER_EVENT_INFO,
+ trackNum | MEDIA_RECORDER_INFO_PROGRESS_TIME_STATUS,
+ timeUs / 1000);
+ }
+}
+
+void MPEG4Writer::Track::findMinAvgMaxSampleDurationMs(
+ int32_t *min, int32_t *avg, int32_t *max) {
+ CHECK(!mSampleSizes.empty());
+ int32_t avgSampleDurationMs = mMaxTimeStampUs / 1000 / mNumSamples;
+ int32_t minSampleDurationMs = 0x7FFFFFFF;
+ int32_t maxSampleDurationMs = 0;
+ for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
+ it != mSttsTableEntries.end(); ++it) {
+ int32_t sampleDurationMs =
+ (static_cast<int32_t>(it->sampleDurationUs) + 500) / 1000;
+ if (sampleDurationMs > maxSampleDurationMs) {
+ maxSampleDurationMs = sampleDurationMs;
+ } else if (sampleDurationMs < minSampleDurationMs) {
+ minSampleDurationMs = sampleDurationMs;
+ }
+ LOGI("sample duration: %d ms", sampleDurationMs);
+ }
+ CHECK(minSampleDurationMs != 0);
+ CHECK(avgSampleDurationMs != 0);
+ CHECK(maxSampleDurationMs != 0);
+ *min = minSampleDurationMs;
+ *avg = avgSampleDurationMs;
+ *max = maxSampleDurationMs;
+}
+
+// Don't count the last duration
+void MPEG4Writer::Track::findMinMaxChunkDurations(int64_t *min, int64_t *max) {
+ int64_t duration = mOwner->interleaveDuration();
+ int64_t minChunkDuration = duration;
+ int64_t maxChunkDuration = duration;
+ if (mChunkDurations.size() > 1) {
+ for (List<int64_t>::iterator it = mChunkDurations.begin();
+ it != --mChunkDurations.end(); ++it) {
+ if (minChunkDuration > (*it)) {
+ minChunkDuration = (*it);
+ } else if (maxChunkDuration < (*it)) {
+ maxChunkDuration = (*it);
+ }
+ }
+ }
+ *min = minChunkDuration;
+ *max = maxChunkDuration;
+}
+
+void MPEG4Writer::Track::logStatisticalData(bool isAudio) {
+ if (mMaxTimeStampUs <= 0 || mSampleSizes.empty()) {
+ LOGI("nothing is recorded");
+ return;
+ }
+
+ bool collectStats = collectStatisticalData();
+
+ if (collectStats) {
+ LOGI("%s track - duration %lld us, total %d frames",
+ isAudio? "audio": "video", mMaxTimeStampUs,
+ mNumSamples);
+ int32_t min, avg, max;
+ findMinAvgMaxSampleDurationMs(&min, &avg, &max);
+ LOGI("min/avg/max sample duration (ms): %d/%d/%d", min, avg, max);
+ if (!isAudio) {
+ float avgFps = 1000.0 / avg;
+ float minFps = 1000.0 / max;
+ float maxFps = 1000.0 / min;
+ LOGI("min/avg/max frame rate (fps): %.2f/%.2f/%.2f",
+ minFps, avgFps, maxFps);
+ }
+
+ int64_t totalBytes = 0;
+ for (List<size_t>::iterator it = mSampleSizes.begin();
+ it != mSampleSizes.end(); ++it) {
+ totalBytes += (*it);
+ }
+ float bitRate = (totalBytes * 8000000.0) / mMaxTimeStampUs;
+ LOGI("avg bit rate (bps): %.2f", bitRate);
+
+ int64_t duration = mOwner->interleaveDuration();
+ if (duration != 0) { // If interleaving is enabled
+ int64_t minChunk, maxChunk;
+ findMinMaxChunkDurations(&minChunk, &maxChunk);
+ LOGI("min/avg/max chunk duration (ms): %lld/%lld/%lld",
+ minChunk, duration, maxChunk);
+ }
+ }
+}
+
+void MPEG4Writer::Track::writeOneChunk(bool isAvc) {
+ mOwner->lock();
+ for (List<MediaBuffer *>::iterator it = mChunkSamples.begin();
+ it != mChunkSamples.end(); ++it) {
+ off_t offset = isAvc? mOwner->addLengthPrefixedSample_l(*it)
+ : mOwner->addSample_l(*it);
+ if (it == mChunkSamples.begin()) {
+ mChunkOffsets.push_back(offset);
+ }
+ }
+ mOwner->unlock();
+ while (!mChunkSamples.empty()) {
+ List<MediaBuffer *>::iterator it = mChunkSamples.begin();
+ (*it)->release();
+ (*it) = NULL;
+ mChunkSamples.erase(it);
+ }
+ mChunkSamples.clear();
}
int64_t MPEG4Writer::Track::getDurationUs() const {
return mMaxTimeStampUs;
}
-void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
+int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const {
+ return mEstimatedTrackSizeBytes;
+}
+
+void MPEG4Writer::Track::writeTrackHeader(
+ int32_t trackID, bool use32BitOffset) {
const char *mime;
bool success = mMeta->findCString(kKeyMIMEType, &mime);
CHECK(success);
bool is_audio = !strncasecmp(mime, "audio/", 6);
+ LOGV("%s track time scale: %d",
+ is_audio? "Audio": "Video", mTimeScale);
+
time_t now = time(NULL);
+ int32_t mvhdTimeScale = mOwner->getTimeScale();
+ int64_t trakDurationUs = getDurationUs();
mOwner->beginBox("trak");
mOwner->beginBox("tkhd");
- mOwner->writeInt32(0); // version=0, flags=0
+ // Flags = 7 to indicate that the track is enabled, and
+ // part of the presentation
+ mOwner->writeInt32(0x07); // version=0, flags=7
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
mOwner->writeInt32(trackID);
mOwner->writeInt32(0); // reserved
- mOwner->writeInt32(getDurationUs() / 1000);
+ int32_t tkhdDuration =
+ (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(tkhdDuration); // in mvhd timescale
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // layer
@@ -550,45 +1462,64 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
success = success && mMeta->findInt32(kKeyHeight, &height);
CHECK(success);
- mOwner->writeInt32(width);
- mOwner->writeInt32(height);
+ mOwner->writeInt32(width << 16); // 32-bit fixed-point value
+ mOwner->writeInt32(height << 16); // 32-bit fixed-point value
}
mOwner->endBox(); // tkhd
+ int64_t moovStartTimeUs = mOwner->getStartTimestampUs();
+ if (mStartTimestampUs != moovStartTimeUs) {
+ mOwner->beginBox("edts");
+ mOwner->beginBox("elst");
+ mOwner->writeInt32(0); // version=0, flags=0: 32-bit time
+ mOwner->writeInt32(2); // never ends with an empty list
+
+ // First elst entry: specify the starting time offset
+ int64_t offsetUs = mStartTimestampUs - moovStartTimeUs;
+ int32_t seg = (offsetUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(seg); // in mvhd timecale
+ mOwner->writeInt32(-1); // starting time offset
+ mOwner->writeInt32(1 << 16); // rate = 1.0
+
+ // Second elst entry: specify the track duration
+ seg = (trakDurationUs * mvhdTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(seg); // in mvhd timescale
+ mOwner->writeInt32(0);
+ mOwner->writeInt32(1 << 16);
+ mOwner->endBox();
+ mOwner->endBox();
+ }
+
mOwner->beginBox("mdia");
mOwner->beginBox("mdhd");
mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt32(now); // creation time
mOwner->writeInt32(now); // modification time
- mOwner->writeInt32(1000); // timescale
- mOwner->writeInt32(getDurationUs() / 1000);
- mOwner->writeInt16(0); // language code XXX
+ mOwner->writeInt32(mTimeScale); // media timescale
+ int32_t mdhdDuration = (trakDurationUs * mTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(mdhdDuration); // use media timescale
+ // Language follows the three letter standard ISO-639-2/T
+ // 'e', 'n', 'g' for "English", for instance.
+ // Each character is packed as the difference between its ASCII value and 0x60.
+ // For "English", these are 00101, 01110, 00111.
+ // XXX: Where is the padding bit located: 0x15C7?
+ mOwner->writeInt16(0); // language code
mOwner->writeInt16(0); // predefined
mOwner->endBox();
mOwner->beginBox("hdlr");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(0); // predefined
- mOwner->writeFourcc(is_audio ? "soun" : "vide");
+ mOwner->writeInt32(0); // component type: should be mhlr
+ mOwner->writeFourcc(is_audio ? "soun" : "vide"); // component subtype
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
- mOwner->writeCString(""); // name
+ // Removing "r" for the name string just makes the string 4 byte aligned
+ mOwner->writeCString(is_audio ? "SoundHandle": "VideoHandle"); // name
mOwner->endBox();
mOwner->beginBox("minf");
-
- mOwner->beginBox("dinf");
- mOwner->beginBox("dref");
- mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(1);
- mOwner->beginBox("url ");
- mOwner->writeInt32(1); // version=0, flags=1
- mOwner->endBox(); // url
- mOwner->endBox(); // dref
- mOwner->endBox(); // dinf
-
if (is_audio) {
mOwner->beginBox("smhd");
mOwner->writeInt32(0); // version=0, flags=0
@@ -597,14 +1528,25 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->endBox();
} else {
mOwner->beginBox("vmhd");
- mOwner->writeInt32(0x00000001); // version=0, flags=1
+ mOwner->writeInt32(0x01); // version=0, flags=1
mOwner->writeInt16(0); // graphics mode
mOwner->writeInt16(0); // opcolor
mOwner->writeInt16(0);
mOwner->writeInt16(0);
mOwner->endBox();
}
- mOwner->endBox(); // minf
+
+ mOwner->beginBox("dinf");
+ mOwner->beginBox("dref");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(1); // entry count (either url or urn)
+ // The table index here refers to the sample description index
+ // in the sample table entries.
+ mOwner->beginBox("url ");
+ mOwner->writeInt32(1); // version=0, flags=1 (self-contained)
+ mOwner->endBox(); // url
+ mOwner->endBox(); // dref
+ mOwner->endBox(); // dinf
mOwner->beginBox("stbl");
@@ -617,6 +1559,8 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
fourcc = "samr";
} else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mime)) {
fourcc = "sawb";
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+ fourcc = "mp4a";
} else {
LOGE("Unknown mime type '%s'.", mime);
CHECK(!"should not be here, unknown mime type.");
@@ -625,10 +1569,12 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->beginBox(fourcc); // audio format
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // reserved
- mOwner->writeInt16(0); // data ref index
+ mOwner->writeInt16(0x1); // data ref index
mOwner->writeInt32(0); // reserved
mOwner->writeInt32(0); // reserved
- mOwner->writeInt16(2); // channel count
+ int32_t nChannels;
+ CHECK_EQ(true, mMeta->findInt32(kKeyChannelCount, &nChannels));
+ mOwner->writeInt16(nChannels); // channel count
mOwner->writeInt16(16); // sample size
mOwner->writeInt16(0); // predefined
mOwner->writeInt16(0); // reserved
@@ -638,6 +1584,38 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
CHECK(success);
mOwner->writeInt32(samplerate << 16);
+ if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
+ mOwner->beginBox("esds");
+
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt8(0x03); // ES_DescrTag
+ mOwner->writeInt8(23 + mCodecSpecificDataSize);
+ mOwner->writeInt16(0x0000);// ES_ID
+ mOwner->writeInt8(0x00);
+
+ mOwner->writeInt8(0x04); // DecoderConfigDescrTag
+ mOwner->writeInt8(15 + mCodecSpecificDataSize);
+ mOwner->writeInt8(0x40); // objectTypeIndication ISO/IEC 14492-2
+ mOwner->writeInt8(0x15); // streamType AudioStream
+
+ mOwner->writeInt16(0x03); // XXX
+ mOwner->writeInt8(0x00); // buffer size 24-bit
+ mOwner->writeInt32(96000); // max bit rate
+ mOwner->writeInt32(96000); // avg bit rate
+
+ mOwner->writeInt8(0x05); // DecoderSpecificInfoTag
+ mOwner->writeInt8(mCodecSpecificDataSize);
+ mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
+
+ static const uint8_t kData2[] = {
+ 0x06, // SLConfigDescriptorTag
+ 0x01,
+ 0x02
+ };
+ mOwner->write(kData2, sizeof(kData2));
+
+ mOwner->endBox(); // esds
+ }
mOwner->endBox();
} else {
if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
@@ -653,7 +1631,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->writeInt32(0); // reserved
mOwner->writeInt16(0); // reserved
- mOwner->writeInt16(0); // data ref index
+ mOwner->writeInt16(1); // data ref index
mOwner->writeInt16(0); // predefined
mOwner->writeInt16(0); // reserved
mOwner->writeInt32(0); // predefined
@@ -698,7 +1676,7 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
0x00, 0x03, 0xe8, 0x00
};
mOwner->write(kData, sizeof(kData));
-
+
mOwner->writeInt8(0x05); // DecoderSpecificInfoTag
mOwner->writeInt8(mCodecSpecificDataSize);
@@ -727,59 +1705,79 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {
mOwner->endBox(); // avcC
}
+ mOwner->beginBox("pasp");
+ // This is useful if the pixel is not square
+ mOwner->writeInt32(1 << 16); // hspacing
+ mOwner->writeInt32(1 << 16); // vspacing
+ mOwner->endBox(); // pasp
mOwner->endBox(); // mp4v, s263 or avc1
}
mOwner->endBox(); // stsd
mOwner->beginBox("stts");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mSampleInfos.size() - 1);
-
- List<SampleInfo>::iterator it = mSampleInfos.begin();
- int64_t last = (*it).timestamp;
- ++it;
- while (it != mSampleInfos.end()) {
- mOwner->writeInt32(1);
- mOwner->writeInt32((*it).timestamp - last);
-
- last = (*it).timestamp;
-
- ++it;
+ mOwner->writeInt32(mSttsTableEntries.size());
+ for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
+ it != mSttsTableEntries.end(); ++it) {
+ mOwner->writeInt32(it->sampleCount);
+ int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
+ mOwner->writeInt32(dur);
}
mOwner->endBox(); // stts
+ if (!is_audio) {
+ mOwner->beginBox("stss");
+ mOwner->writeInt32(0); // version=0, flags=0
+ mOwner->writeInt32(mStssTableEntries.size()); // number of sync frames
+ for (List<int32_t>::iterator it = mStssTableEntries.begin();
+ it != mStssTableEntries.end(); ++it) {
+ mOwner->writeInt32(*it);
+ }
+ mOwner->endBox(); // stss
+ }
+
mOwner->beginBox("stsz");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(0); // default sample size
- mOwner->writeInt32(mSampleInfos.size());
- for (List<SampleInfo>::iterator it = mSampleInfos.begin();
- it != mSampleInfos.end(); ++it) {
- mOwner->writeInt32((*it).size);
+ if (mSamplesHaveSameSize) {
+ List<size_t>::iterator it = mSampleSizes.begin();
+ mOwner->writeInt32(*it); // default sample size
+ } else {
+ mOwner->writeInt32(0);
+ }
+ mOwner->writeInt32(mNumSamples);
+ if (!mSamplesHaveSameSize) {
+ for (List<size_t>::iterator it = mSampleSizes.begin();
+ it != mSampleSizes.end(); ++it) {
+ mOwner->writeInt32(*it);
+ }
}
mOwner->endBox(); // stsz
mOwner->beginBox("stsc");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mSampleInfos.size());
- int32_t n = 1;
- for (List<SampleInfo>::iterator it = mSampleInfos.begin();
- it != mSampleInfos.end(); ++it, ++n) {
- mOwner->writeInt32(n);
- mOwner->writeInt32(1);
- mOwner->writeInt32(1);
+ mOwner->writeInt32(mStscTableEntries.size());
+ for (List<StscTableEntry>::iterator it = mStscTableEntries.begin();
+ it != mStscTableEntries.end(); ++it) {
+ mOwner->writeInt32(it->firstChunk);
+ mOwner->writeInt32(it->samplesPerChunk);
+ mOwner->writeInt32(it->sampleDescriptionId);
}
mOwner->endBox(); // stsc
-
- mOwner->beginBox("co64");
+ mOwner->beginBox(use32BitOffset? "stco": "co64");
mOwner->writeInt32(0); // version=0, flags=0
- mOwner->writeInt32(mSampleInfos.size());
- for (List<SampleInfo>::iterator it = mSampleInfos.begin();
- it != mSampleInfos.end(); ++it, ++n) {
- mOwner->writeInt64((*it).offset);
+ mOwner->writeInt32(mChunkOffsets.size());
+ for (List<off_t>::iterator it = mChunkOffsets.begin();
+ it != mChunkOffsets.end(); ++it) {
+ if (use32BitOffset) {
+ mOwner->writeInt32(static_cast<int32_t>(*it));
+ } else {
+ mOwner->writeInt64((*it));
+ }
}
- mOwner->endBox(); // co64
+ mOwner->endBox(); // stco or co64
mOwner->endBox(); // stbl
+ mOwner->endBox(); // minf
mOwner->endBox(); // mdia
mOwner->endBox(); // trak
}
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index 4b3813b..39d264c 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -20,6 +20,7 @@ namespace android {
const char *MEDIA_MIMETYPE_IMAGE_JPEG = "image/jpeg";
+const char *MEDIA_MIMETYPE_VIDEO_VPX = "video/x-vnd.on2.vp8";
const char *MEDIA_MIMETYPE_VIDEO_AVC = "video/avc";
const char *MEDIA_MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es";
const char *MEDIA_MIMETYPE_VIDEO_H263 = "video/3gpp";
@@ -36,5 +37,7 @@ const char *MEDIA_MIMETYPE_AUDIO_RAW = "audio/raw";
const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mpeg4";
const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/wav";
const char *MEDIA_MIMETYPE_CONTAINER_OGG = "application/ogg";
+const char *MEDIA_MIMETYPE_CONTAINER_MATROSKA = "video/x-matroska";
+const char *MEDIA_MIMETYPE_CONTAINER_MPEG2TS = "video/mp2ts";
} // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 513f49c..56e6136 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -23,6 +23,9 @@
#include "include/MPEG4Extractor.h"
#include "include/WAVExtractor.h"
#include "include/OggExtractor.h"
+#include "include/MPEG2TSExtractor.h"
+
+#include "matroska/MatroskaExtractor.h"
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaDefs.h>
@@ -69,6 +72,10 @@ sp<MediaExtractor> MediaExtractor::Create(
return new WAVExtractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) {
return new OggExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) {
+ return new MatroskaExtractor(source);
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) {
+ return new MPEG2TSExtractor(source);
}
return NULL;
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
index ec89b74..b4ef338 100644
--- a/media/libstagefright/MediaSource.cpp
+++ b/media/libstagefright/MediaSource.cpp
@@ -32,23 +32,43 @@ void MediaSource::ReadOptions::reset() {
mOptions = 0;
mSeekTimeUs = 0;
mLatenessUs = 0;
+ mSkipFrameUntilTimeUs = 0;
}
-void MediaSource::ReadOptions::setSeekTo(int64_t time_us) {
+void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
mOptions |= kSeekTo_Option;
mSeekTimeUs = time_us;
+ mSeekMode = mode;
}
void MediaSource::ReadOptions::clearSeekTo() {
mOptions &= ~kSeekTo_Option;
mSeekTimeUs = 0;
+ mSeekMode = SEEK_CLOSEST_SYNC;
}
-bool MediaSource::ReadOptions::getSeekTo(int64_t *time_us) const {
+bool MediaSource::ReadOptions::getSeekTo(
+ int64_t *time_us, SeekMode *mode) const {
*time_us = mSeekTimeUs;
+ *mode = mSeekMode;
return (mOptions & kSeekTo_Option) != 0;
}
+void MediaSource::ReadOptions::clearSkipFrame() {
+ mOptions &= ~kSkipFrame_Option;
+ mSkipFrameUntilTimeUs = 0;
+}
+
+void MediaSource::ReadOptions::setSkipFrame(int64_t timeUs) {
+ mOptions |= kSkipFrame_Option;
+ mSkipFrameUntilTimeUs = timeUs;
+}
+
+bool MediaSource::ReadOptions::getSkipFrame(int64_t *timeUs) const {
+ *timeUs = mSkipFrameUntilTimeUs;
+ return (mOptions & kSkipFrame_Option) != 0;
+}
+
void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
mLatenessUs = lateness_us;
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
new file mode 100644
index 0000000..c02b7f3
--- /dev/null
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "NuCachedSource2"
+#include <utils/Log.h>
+
+#include "include/NuCachedSource2.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct PageCache {
+ PageCache(size_t pageSize);
+ ~PageCache();
+
+ struct Page {
+ void *mData;
+ size_t mSize;
+ };
+
+ Page *acquirePage();
+ void releasePage(Page *page);
+
+ void appendPage(Page *page);
+ size_t releaseFromStart(size_t maxBytes);
+
+ size_t totalSize() const {
+ return mTotalSize;
+ }
+
+ void copy(size_t from, void *data, size_t size);
+
+private:
+ size_t mPageSize;
+ size_t mTotalSize;
+
+ List<Page *> mActivePages;
+ List<Page *> mFreePages;
+
+ void freePages(List<Page *> *list);
+
+ DISALLOW_EVIL_CONSTRUCTORS(PageCache);
+};
+
+PageCache::PageCache(size_t pageSize)
+ : mPageSize(pageSize),
+ mTotalSize(0) {
+}
+
+PageCache::~PageCache() {
+ freePages(&mActivePages);
+ freePages(&mFreePages);
+}
+
+void PageCache::freePages(List<Page *> *list) {
+ List<Page *>::iterator it = list->begin();
+ while (it != list->end()) {
+ Page *page = *it;
+
+ free(page->mData);
+ delete page;
+ page = NULL;
+
+ ++it;
+ }
+}
+
+PageCache::Page *PageCache::acquirePage() {
+ if (!mFreePages.empty()) {
+ List<Page *>::iterator it = mFreePages.begin();
+ Page *page = *it;
+ mFreePages.erase(it);
+
+ return page;
+ }
+
+ Page *page = new Page;
+ page->mData = malloc(mPageSize);
+ page->mSize = 0;
+
+ return page;
+}
+
+void PageCache::releasePage(Page *page) {
+ page->mSize = 0;
+ mFreePages.push_back(page);
+}
+
+void PageCache::appendPage(Page *page) {
+ mTotalSize += page->mSize;
+ mActivePages.push_back(page);
+}
+
+size_t PageCache::releaseFromStart(size_t maxBytes) {
+ size_t bytesReleased = 0;
+
+ while (maxBytes > 0 && !mActivePages.empty()) {
+ List<Page *>::iterator it = mActivePages.begin();
+
+ Page *page = *it;
+
+ if (maxBytes < page->mSize) {
+ break;
+ }
+
+ mActivePages.erase(it);
+
+ maxBytes -= page->mSize;
+ bytesReleased += page->mSize;
+
+ releasePage(page);
+ }
+
+ mTotalSize -= bytesReleased;
+ return bytesReleased;
+}
+
+void PageCache::copy(size_t from, void *data, size_t size) {
+ LOG(VERBOSE) << "copy from " << from << " size " << size;
+
+ CHECK_LE(from + size, mTotalSize);
+
+ size_t offset = 0;
+ List<Page *>::iterator it = mActivePages.begin();
+ while (from >= offset + (*it)->mSize) {
+ offset += (*it)->mSize;
+ ++it;
+ }
+
+ size_t delta = from - offset;
+ size_t avail = (*it)->mSize - delta;
+
+ if (avail >= size) {
+ memcpy(data, (const uint8_t *)(*it)->mData + delta, size);
+ return;
+ }
+
+ memcpy(data, (const uint8_t *)(*it)->mData + delta, avail);
+ ++it;
+ data = (uint8_t *)data + avail;
+ size -= avail;
+
+ while (size > 0) {
+ size_t copy = (*it)->mSize;
+ if (copy > size) {
+ copy = size;
+ }
+ memcpy(data, (*it)->mData, copy);
+ data = (uint8_t *)data + copy;
+ size -= copy;
+ ++it;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
+ : mSource(source),
+ mReflector(new AHandlerReflector<NuCachedSource2>(this)),
+ mLooper(new ALooper),
+ mCache(new PageCache(kPageSize)),
+ mCacheOffset(0),
+ mFinalStatus(OK),
+ mLastAccessPos(0),
+ mFetching(true),
+ mLastFetchTimeUs(-1) {
+ mLooper->registerHandler(mReflector);
+ mLooper->start();
+
+ Mutex::Autolock autoLock(mLock);
+ (new AMessage(kWhatFetchMore, mReflector->id()))->post();
+}
+
+NuCachedSource2::~NuCachedSource2() {
+ mLooper->stop();
+ mLooper->unregisterHandler(mReflector->id());
+
+ delete mCache;
+ mCache = NULL;
+}
+
+status_t NuCachedSource2::initCheck() const {
+ return mSource->initCheck();
+}
+
+status_t NuCachedSource2::getSize(off_t *size) {
+ return mSource->getSize(size);
+}
+
+uint32_t NuCachedSource2::flags() {
+ return mSource->flags();
+}
+
+void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatFetchMore:
+ {
+ onFetch();
+ break;
+ }
+
+ case kWhatRead:
+ {
+ onRead(msg);
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void NuCachedSource2::fetchInternal() {
+ LOG(VERBOSE) << "fetchInternal";
+
+ CHECK_EQ(mFinalStatus, (status_t)OK);
+
+ PageCache::Page *page = mCache->acquirePage();
+
+ ssize_t n = mSource->readAt(
+ mCacheOffset + mCache->totalSize(), page->mData, kPageSize);
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (n < 0) {
+ LOG(ERROR) << "source returned error " << n;
+ mFinalStatus = n;
+ mCache->releasePage(page);
+ } else if (n == 0) {
+ LOG(INFO) << "ERROR_END_OF_STREAM";
+ mFinalStatus = ERROR_END_OF_STREAM;
+ mCache->releasePage(page);
+ } else {
+ page->mSize = n;
+ mCache->appendPage(page);
+ }
+}
+
+void NuCachedSource2::onFetch() {
+ LOG(VERBOSE) << "onFetch";
+
+ if (mFinalStatus != OK) {
+ LOG(VERBOSE) << "EOS reached, done prefetching for now";
+ mFetching = false;
+ }
+
+ bool keepAlive =
+ !mFetching
+ && mFinalStatus == OK
+ && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs;
+
+ if (mFetching || keepAlive) {
+ if (keepAlive) {
+ LOG(INFO) << "Keep alive";
+ }
+
+ fetchInternal();
+
+ mLastFetchTimeUs = ALooper::GetNowUs();
+
+ if (mFetching && mCache->totalSize() >= kHighWaterThreshold) {
+ LOG(INFO) << "Cache full, done prefetching for now";
+ mFetching = false;
+ }
+ } else {
+ Mutex::Autolock autoLock(mLock);
+ restartPrefetcherIfNecessary_l();
+ }
+
+ (new AMessage(kWhatFetchMore, mReflector->id()))->post(
+ mFetching ? 0 : 100000ll);
+}
+
+void NuCachedSource2::onRead(const sp<AMessage> &msg) {
+ LOG(VERBOSE) << "onRead";
+
+ int64_t offset;
+ CHECK(msg->findInt64("offset", &offset));
+
+ void *data;
+ CHECK(msg->findPointer("data", &data));
+
+ size_t size;
+ CHECK(msg->findSize("size", &size));
+
+ ssize_t result = readInternal(offset, data, size);
+
+ if (result == -EAGAIN) {
+ msg->post(50000);
+ return;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK(mAsyncResult == NULL);
+
+ mAsyncResult = new AMessage;
+ mAsyncResult->setInt32("result", result);
+
+ mCondition.signal();
+}
+
+void NuCachedSource2::restartPrefetcherIfNecessary_l() {
+ static const size_t kGrayArea = 256 * 1024;
+
+ if (mFetching || mFinalStatus != OK) {
+ return;
+ }
+
+ if (mCacheOffset + mCache->totalSize() - mLastAccessPos
+ >= kLowWaterThreshold) {
+ return;
+ }
+
+ size_t maxBytes = mLastAccessPos - mCacheOffset;
+ if (maxBytes < kGrayArea) {
+ return;
+ }
+
+ maxBytes -= kGrayArea;
+
+ size_t actualBytes = mCache->releaseFromStart(maxBytes);
+ mCacheOffset += actualBytes;
+
+ LOG(INFO) << "restarting prefetcher, totalSize = " << mCache->totalSize();
+ mFetching = true;
+}
+
+ssize_t NuCachedSource2::readAt(off_t offset, void *data, size_t size) {
+ Mutex::Autolock autoSerializer(mSerializer);
+
+ LOG(VERBOSE) << "readAt offset " << offset << " size " << size;
+
+ Mutex::Autolock autoLock(mLock);
+
+ // If the request can be completely satisfied from the cache, do so.
+
+ if (offset >= mCacheOffset
+ && offset + size <= mCacheOffset + mCache->totalSize()) {
+ size_t delta = offset - mCacheOffset;
+ mCache->copy(delta, data, size);
+
+ mLastAccessPos = offset + size;
+
+ return size;
+ }
+
+ sp<AMessage> msg = new AMessage(kWhatRead, mReflector->id());
+ msg->setInt64("offset", offset);
+ msg->setPointer("data", data);
+ msg->setSize("size", size);
+
+ CHECK(mAsyncResult == NULL);
+ msg->post();
+
+ while (mAsyncResult == NULL) {
+ mCondition.wait(mLock);
+ }
+
+ int32_t result;
+ CHECK(mAsyncResult->findInt32("result", &result));
+
+ mAsyncResult.clear();
+
+ if (result > 0) {
+ mLastAccessPos = offset + result;
+ }
+
+ return (ssize_t)result;
+}
+
+size_t NuCachedSource2::cachedSize() {
+ Mutex::Autolock autoLock(mLock);
+ return mCacheOffset + mCache->totalSize();
+}
+
+size_t NuCachedSource2::approxDataRemaining(bool *eos) {
+ Mutex::Autolock autoLock(mLock);
+ return approxDataRemaining_l(eos);
+}
+
+size_t NuCachedSource2::approxDataRemaining_l(bool *eos) {
+ *eos = (mFinalStatus != OK);
+ off_t lastBytePosCached = mCacheOffset + mCache->totalSize();
+ if (mLastAccessPos < lastBytePosCached) {
+ return lastBytePosCached - mLastAccessPos;
+ }
+ return 0;
+}
+
+ssize_t NuCachedSource2::readInternal(off_t offset, void *data, size_t size) {
+ LOG(VERBOSE) << "readInternal offset " << offset << " size " << size;
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (offset < mCacheOffset
+ || offset >= (off_t)(mCacheOffset + mCache->totalSize())) {
+ static const off_t kPadding = 32768;
+
+ // In the presence of multiple decoded streams, once of them will
+ // trigger this seek request, the other one will request data "nearby"
+ // soon, adjust the seek position so that that subsequent request
+ // does not trigger another seek.
+ off_t seekOffset = (offset > kPadding) ? offset - kPadding : 0;
+
+ seekInternal_l(seekOffset);
+ }
+
+ size_t delta = offset - mCacheOffset;
+
+ if (mFinalStatus != OK) {
+ if (delta >= mCache->totalSize()) {
+ return mFinalStatus;
+ }
+
+ size_t avail = mCache->totalSize() - delta;
+ mCache->copy(delta, data, avail);
+
+ return avail;
+ }
+
+ if (offset + size <= mCacheOffset + mCache->totalSize()) {
+ mCache->copy(delta, data, size);
+
+ return size;
+ }
+
+ LOG(VERBOSE) << "deferring read";
+
+ return -EAGAIN;
+}
+
+status_t NuCachedSource2::seekInternal_l(off_t offset) {
+ mLastAccessPos = offset;
+
+ if (offset >= mCacheOffset
+ && offset <= (off_t)(mCacheOffset + mCache->totalSize())) {
+ return OK;
+ }
+
+ LOG(INFO) << "new range: offset= " << offset;
+
+ mCacheOffset = offset;
+
+ size_t totalSize = mCache->totalSize();
+ CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);
+
+ mFinalStatus = OK;
+ mFetching = true;
+
+ return OK;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
new file mode 100644
index 0000000..ab9285d
--- /dev/null
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -0,0 +1,338 @@
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NuHTTPDataSource"
+#include <utils/Log.h>
+
+#include "include/NuHTTPDataSource.h"
+
+#include <cutils/properties.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+static bool ParseSingleUnsignedLong(
+ const char *from, unsigned long *x) {
+ char *end;
+ *x = strtoul(from, &end, 10);
+
+ if (end == from || *end != '\0') {
+ return false;
+ }
+
+ return true;
+}
+
+static bool ParseURL(
+ const char *url, String8 *host, unsigned *port, String8 *path) {
+ host->setTo("");
+ *port = 0;
+ path->setTo("");
+
+ if (strncasecmp("http://", url, 7)) {
+ return false;
+ }
+
+ const char *slashPos = strchr(&url[7], '/');
+
+ if (slashPos == NULL) {
+ host->setTo(&url[7]);
+ path->setTo("/");
+ } else {
+ host->setTo(&url[7], slashPos - &url[7]);
+ path->setTo(slashPos);
+ }
+
+ char *colonPos = strchr(host->string(), ':');
+
+ if (colonPos != NULL) {
+ unsigned long x;
+ if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
+ return false;
+ }
+
+ *port = x;
+
+ size_t colonOffset = colonPos - host->string();
+ String8 tmp(host->string(), colonOffset);
+ *host = tmp;
+ } else {
+ *port = 80;
+ }
+
+ return true;
+}
+
+NuHTTPDataSource::NuHTTPDataSource()
+ : mState(DISCONNECTED),
+ mPort(0),
+ mOffset(0),
+ mContentLength(0),
+ mContentLengthValid(false) {
+}
+
+NuHTTPDataSource::~NuHTTPDataSource() {
+}
+
+status_t NuHTTPDataSource::connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *overrides,
+ off_t offset) {
+ String8 headers;
+ MakeFullHeaders(overrides, &headers);
+
+ return connect(uri, headers, offset);
+}
+
+status_t NuHTTPDataSource::connect(
+ const char *uri,
+ const String8 &headers,
+ off_t offset) {
+ String8 host, path;
+ unsigned port;
+ if (!ParseURL(uri, &host, &port, &path)) {
+ return ERROR_MALFORMED;
+ }
+
+ return connect(host, port, path, headers, offset);
+}
+
+status_t NuHTTPDataSource::connect(
+ const char *host, unsigned port, const char *path,
+ const String8 &headers,
+ off_t offset) {
+ LOGI("connect to %s:%u%s @%ld", host, port, path, offset);
+
+ bool needsToReconnect = true;
+
+ if (mState == CONNECTED && host == mHost && port == mPort
+ && offset == mOffset) {
+ if (mContentLengthValid && mOffset == mContentLength) {
+ LOGI("Didn't have to reconnect, old one's still good.");
+ needsToReconnect = false;
+ }
+ }
+
+ mHost = host;
+ mPort = port;
+ mPath = path;
+ mHeaders = headers;
+
+ status_t err = OK;
+
+ mState = CONNECTING;
+
+ if (needsToReconnect) {
+ mHTTP.disconnect();
+ err = mHTTP.connect(host, port);
+ }
+
+ if (err != OK) {
+ mState = DISCONNECTED;
+ } else if (mState != CONNECTING) {
+ err = UNKNOWN_ERROR;
+ } else {
+ mState = CONNECTED;
+
+ mOffset = offset;
+ mContentLength = 0;
+ mContentLengthValid = false;
+
+ String8 request("GET ");
+ request.append(mPath);
+ request.append(" HTTP/1.1\r\n");
+ request.append("Host: ");
+ request.append(mHost);
+ request.append("\r\n");
+
+ if (offset != 0) {
+ char rangeHeader[128];
+ sprintf(rangeHeader, "Range: bytes=%ld-\r\n", offset);
+ request.append(rangeHeader);
+ }
+
+ request.append(mHeaders);
+ request.append("\r\n");
+
+ int httpStatus;
+ if ((err = mHTTP.send(request.string(), request.size())) != OK
+ || (err = mHTTP.receive_header(&httpStatus)) != OK) {
+ mHTTP.disconnect();
+ mState = DISCONNECTED;
+ return err;
+ }
+
+ if (httpStatus == 302) {
+ string value;
+ CHECK(mHTTP.find_header_value("Location", &value));
+
+ mState = DISCONNECTED;
+
+ mHTTP.disconnect();
+
+ return connect(value.c_str(), headers, offset);
+ }
+
+ if (httpStatus < 200 || httpStatus >= 300) {
+ mState = DISCONNECTED;
+ mHTTP.disconnect();
+
+ return ERROR_IO;
+ }
+
+ applyTimeoutResponse();
+
+ if (offset == 0) {
+ string value;
+ unsigned long x;
+ if (mHTTP.find_header_value(string("Content-Length"), &value)
+ && ParseSingleUnsignedLong(value.c_str(), &x)) {
+ mContentLength = (off_t)x;
+ mContentLengthValid = true;
+ }
+ } else {
+ string value;
+ unsigned long x;
+ if (mHTTP.find_header_value(string("Content-Range"), &value)) {
+ const char *slashPos = strchr(value.c_str(), '/');
+ if (slashPos != NULL
+ && ParseSingleUnsignedLong(slashPos + 1, &x)) {
+ mContentLength = x;
+ mContentLengthValid = true;
+ }
+ }
+ }
+ }
+
+ return err;
+}
+
+void NuHTTPDataSource::disconnect() {
+ if (mState == CONNECTING || mState == CONNECTED) {
+ mHTTP.disconnect();
+ }
+ mState = DISCONNECTED;
+}
+
+status_t NuHTTPDataSource::initCheck() const {
+ return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t NuHTTPDataSource::readAt(off_t offset, void *data, size_t size) {
+ LOGV("readAt offset %ld, size %d", offset, size);
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (offset != mOffset) {
+ String8 host = mHost;
+ String8 path = mPath;
+ String8 headers = mHeaders;
+ status_t err = connect(host, mPort, path, headers, offset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (mContentLengthValid) {
+ size_t avail =
+ (offset >= mContentLength) ? 0 : mContentLength - offset;
+
+ if (size > avail) {
+ size = avail;
+ }
+ }
+
+ size_t numBytesRead = 0;
+ while (numBytesRead < size) {
+ ssize_t n =
+ mHTTP.receive((uint8_t *)data + numBytesRead, size - numBytesRead);
+
+ if (n < 0) {
+ return n;
+ }
+
+ numBytesRead += (size_t)n;
+
+ if (n == 0) {
+ if (mContentLengthValid) {
+ // We know the content length and made sure not to read beyond
+ // it and yet the server closed the connection on us.
+ return ERROR_IO;
+ }
+
+ break;
+ }
+ }
+
+ mOffset += numBytesRead;
+
+ return numBytesRead;
+}
+
+status_t NuHTTPDataSource::getSize(off_t *size) {
+ *size = 0;
+
+ if (mState != CONNECTED) {
+ return ERROR_IO;
+ }
+
+ if (mContentLengthValid) {
+ *size = mContentLength;
+ return OK;
+ }
+
+ return ERROR_UNSUPPORTED;
+}
+
+uint32_t NuHTTPDataSource::flags() {
+ return kWantsPrefetching;
+}
+
+// static
+void NuHTTPDataSource::MakeFullHeaders(
+ const KeyedVector<String8, String8> *overrides, String8 *headers) {
+ headers->setTo("");
+
+ headers->append("User-Agent: stagefright/1.1 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.version.release", value, "Unknown");
+ headers->append(value);
+ headers->append(")\r\n");
+
+ if (overrides == NULL) {
+ return;
+ }
+
+ for (size_t i = 0; i < overrides->size(); ++i) {
+ String8 line;
+ line.append(overrides->keyAt(i));
+ line.append(": ");
+ line.append(overrides->valueAt(i));
+ line.append("\r\n");
+
+ headers->append(line);
+ }
+}
+
+void NuHTTPDataSource::applyTimeoutResponse() {
+ string timeout;
+ if (mHTTP.find_header_value("X-SocketTimeout", &timeout)) {
+ const char *s = timeout.c_str();
+ char *end;
+ long tmp = strtol(s, &end, 10);
+ if (end == s || *end != '\0') {
+ LOGW("Illegal X-SocketTimeout value given.");
+ return;
+ }
+
+ LOGI("overriding default timeout, new timeout is %ld seconds", tmp);
+ mHTTP.setReceiveTimeout(tmp);
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 69da7ef..3fba2d9 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -19,13 +19,18 @@
#include <utils/Log.h>
#include "include/AACDecoder.h"
+#include "include/AACEncoder.h"
#include "include/AMRNBDecoder.h"
#include "include/AMRNBEncoder.h"
#include "include/AMRWBDecoder.h"
+#include "include/AMRWBEncoder.h"
#include "include/AVCDecoder.h"
+#include "include/AVCEncoder.h"
#include "include/M4vH263Decoder.h"
+#include "include/M4vH263Encoder.h"
#include "include/MP3Decoder.h"
#include "include/VorbisDecoder.h"
+#include "include/VPXDecoder.h"
#include "include/ESDS.h"
@@ -60,6 +65,11 @@ static sp<MediaSource> Make##name(const sp<MediaSource> &source) { \
return new name(source); \
}
+#define FACTORY_CREATE_ENCODER(name) \
+static sp<MediaSource> Make##name(const sp<MediaSource> &source, const sp<MetaData> &meta) { \
+ return new name(source, meta); \
+}
+
#define FACTORY_REF(name) { #name, Make##name },
FACTORY_CREATE(MP3Decoder)
@@ -69,7 +79,37 @@ FACTORY_CREATE(AACDecoder)
FACTORY_CREATE(AVCDecoder)
FACTORY_CREATE(M4vH263Decoder)
FACTORY_CREATE(VorbisDecoder)
-FACTORY_CREATE(AMRNBEncoder)
+FACTORY_CREATE(VPXDecoder)
+FACTORY_CREATE_ENCODER(AMRNBEncoder)
+FACTORY_CREATE_ENCODER(AMRWBEncoder)
+FACTORY_CREATE_ENCODER(AACEncoder)
+FACTORY_CREATE_ENCODER(AVCEncoder)
+FACTORY_CREATE_ENCODER(M4vH263Encoder)
+
+static sp<MediaSource> InstantiateSoftwareEncoder(
+ const char *name, const sp<MediaSource> &source,
+ const sp<MetaData> &meta) {
+ struct FactoryInfo {
+ const char *name;
+ sp<MediaSource> (*CreateFunc)(const sp<MediaSource> &, const sp<MetaData> &);
+ };
+
+ static const FactoryInfo kFactoryInfo[] = {
+ FACTORY_REF(AMRNBEncoder)
+ FACTORY_REF(AMRWBEncoder)
+ FACTORY_REF(AACEncoder)
+ FACTORY_REF(AVCEncoder)
+ FACTORY_REF(M4vH263Encoder)
+ };
+ for (size_t i = 0;
+ i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
+ if (!strcmp(name, kFactoryInfo[i].name)) {
+ return (*kFactoryInfo[i].CreateFunc)(source, meta);
+ }
+ }
+
+ return NULL;
+}
static sp<MediaSource> InstantiateSoftwareCodec(
const char *name, const sp<MediaSource> &source) {
@@ -86,7 +126,7 @@ static sp<MediaSource> InstantiateSoftwareCodec(
FACTORY_REF(AVCDecoder)
FACTORY_REF(M4vH263Decoder)
FACTORY_REF(VorbisDecoder)
- FACTORY_REF(AMRNBEncoder)
+ FACTORY_REF(VPXDecoder)
};
for (size_t i = 0;
i < sizeof(kFactoryInfo) / sizeof(kFactoryInfo[0]); ++i) {
@@ -115,34 +155,47 @@ static const CodecInfo kDecoderInfo[] = {
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.decode" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "AACDecoder" },
// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacdec" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.decoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.decoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4dec" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263dec" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.decoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "AVCDecoder" },
// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcdec" },
{ MEDIA_MIMETYPE_AUDIO_VORBIS, "VorbisDecoder" },
+ { MEDIA_MIMETYPE_VIDEO_VPX, "VPXDecoder" },
};
static const CodecInfo kEncoderInfo[] = {
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.encode" },
{ MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.encode" },
+ { MEDIA_MIMETYPE_AUDIO_AMR_WB, "AMRWBEncoder" },
{ MEDIA_MIMETYPE_AUDIO_AAC, "OMX.TI.AAC.encode" },
- { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
+ { MEDIA_MIMETYPE_AUDIO_AAC, "AACEncoder" },
+// { MEDIA_MIMETYPE_AUDIO_AAC, "OMX.PV.aacenc" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.7x30.video.encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.qcom.video.encoder.mpeg4" },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.encoder" },
- { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Encoder" },
+// { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.PV.mpeg4enc" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.7x30.video.encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
{ MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
- { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
+ { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Encoder" },
+// { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.7x30.video.encoder.avc" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
{ MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
- { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
+ { MEDIA_MIMETYPE_VIDEO_AVC, "AVCEncoder" },
+// { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
};
#undef OPTIONAL
@@ -296,10 +349,17 @@ uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
quirks |= kRequiresAllocateBufferOnInputPorts;
quirks |= kRequiresAllocateBufferOnOutputPorts;
}
+ if (!strncmp(componentName, "OMX.qcom.7x30.video.encoder.", 28)) {
+ }
if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
quirks |= kRequiresAllocateBufferOnOutputPorts;
quirks |= kDefersOutputBufferAllocation;
}
+ if (!strncmp(componentName, "OMX.qcom.7x30.video.decoder.", 28)) {
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ quirks |= kRequiresAllocateBufferOnOutputPorts;
+ quirks |= kDefersOutputBufferAllocation;
+ }
if (!strncmp(componentName, "OMX.TI.", 7)) {
// Apparently I must not use OMX_UseBuffer on either input or
@@ -309,6 +369,9 @@ uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
quirks |= kRequiresAllocateBufferOnInputPorts;
quirks |= kRequiresAllocateBufferOnOutputPorts;
+ if (!strncmp(componentName, "OMX.TI.Video.encoder", 20)) {
+ quirks |= kAvoidMemcopyInputRecordingFrames;
+ }
}
if (!strcmp(componentName, "OMX.TI.Video.Decoder")) {
@@ -384,8 +447,8 @@ sp<MediaSource> OMXCodec::Create(
for (size_t i = 0; i < matchingCodecs.size(); ++i) {
componentName = matchingCodecs[i].string();
-#if BUILD_WITH_FULL_STAGEFRIGHT
- sp<MediaSource> softwareCodec =
+ sp<MediaSource> softwareCodec = createEncoder?
+ InstantiateSoftwareEncoder(componentName, source, meta):
InstantiateSoftwareCodec(componentName, source);
if (softwareCodec != NULL) {
@@ -393,7 +456,6 @@ sp<MediaSource> OMXCodec::Create(
return softwareCodec;
}
-#endif
LOGV("Attempting to allocate OMX node '%s'", componentName);
@@ -496,11 +558,12 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
size -= length;
}
- LOGV("AVC profile = %d (%s), level = %d",
- (int)profile, AVCProfileToString(profile), (int)level / 10);
+ CODEC_LOGV(
+ "AVC profile = %d (%s), level = %d",
+ (int)profile, AVCProfileToString(profile), level);
if (!strcmp(mComponentName, "OMX.TI.Video.Decoder")
- && (profile != kAVCProfileBaseline || level > 39)) {
+ && (profile != kAVCProfileBaseline || level > 30)) {
// This stream exceeds the decoder's capabilities. The decoder
// does not handle this gracefully and would clobber the heap
// and wreak havoc instead...
@@ -510,28 +573,33 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
}
}
+ int32_t bitRate = 0;
+ if (mIsEncoder) {
+ CHECK(meta->findInt32(kKeyBitRate, &bitRate));
+ }
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, mMIME)) {
- setAMRFormat(false /* isWAMR */);
+ setAMRFormat(false /* isWAMR */, bitRate);
}
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, mMIME)) {
- setAMRFormat(true /* isWAMR */);
+ setAMRFormat(true /* isWAMR */, bitRate);
}
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mMIME)) {
int32_t numChannels, sampleRate;
CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
- setAACFormat(numChannels, sampleRate);
+ setAACFormat(numChannels, sampleRate, bitRate);
}
+
if (!strncasecmp(mMIME, "video/", 6)) {
- int32_t width, height;
- bool success = meta->findInt32(kKeyWidth, &width);
- success = success && meta->findInt32(kKeyHeight, &height);
- CHECK(success);
if (mIsEncoder) {
- setVideoInputFormat(mMIME, width, height);
+ setVideoInputFormat(mMIME, meta);
} else {
+ int32_t width, height;
+ bool success = meta->findInt32(kKeyWidth, &width);
+ success = success && meta->findInt32(kKeyHeight, &height);
+ CHECK(success);
status_t err = setVideoOutputFormat(
mMIME, width, height);
@@ -570,7 +638,8 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
}
if (!strcmp(mComponentName, "OMX.TI.AMR.encode")
- || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")) {
+ || !strcmp(mComponentName, "OMX.TI.WBAMR.encode")
+ || !strcmp(mComponentName, "OMX.TI.AAC.encode")) {
setMinBufferSize(kPortIndexOutput, 8192); // XXX
}
@@ -683,6 +752,7 @@ static size_t getFrameSize(
case OMX_COLOR_FormatCbYCrY:
return width * height * 2;
+ case OMX_COLOR_FormatYUV420Planar:
case OMX_COLOR_FormatYUV420SemiPlanar:
return (width * height * 3) / 2;
@@ -693,8 +763,17 @@ static size_t getFrameSize(
}
void OMXCodec::setVideoInputFormat(
- const char *mime, OMX_U32 width, OMX_U32 height) {
- CODEC_LOGV("setVideoInputFormat width=%ld, height=%ld", width, height);
+ const char *mime, const sp<MetaData>& meta) {
+
+ int32_t width, height, frameRate, bitRate, stride, sliceHeight;
+ bool success = meta->findInt32(kKeyWidth, &width);
+ success = success && meta->findInt32(kKeyHeight, &height);
+ success = success && meta->findInt32(kKeySampleRate, &frameRate);
+ success = success && meta->findInt32(kKeyBitRate, &bitRate);
+ success = success && meta->findInt32(kKeyStride, &stride);
+ success = success && meta->findInt32(kKeySliceHeight, &sliceHeight);
+ CHECK(success);
+ CHECK(stride != 0);
OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
@@ -713,74 +792,78 @@ void OMXCodec::setVideoInputFormat(
colorFormat = OMX_COLOR_FormatYCbYCr;
}
+ status_t err;
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ //////////////////////// Input port /////////////////////////
CHECK_EQ(setVideoPortFormatType(
kPortIndexInput, OMX_VIDEO_CodingUnused,
colorFormat), OK);
- CHECK_EQ(setVideoPortFormatType(
- kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
- OK);
-
- OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
- def.nPortIndex = kPortIndexOutput;
-
- OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+ def.nPortIndex = kPortIndexInput;
- status_t err = mOMX->getParameter(
+ err = mOMX->getParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-
CHECK_EQ(err, OK);
+
+ def.nBufferSize = getFrameSize(colorFormat,
+ stride > 0? stride: -stride, sliceHeight);
+
CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
video_def->nFrameWidth = width;
video_def->nFrameHeight = height;
-
- video_def->eCompressionFormat = compressionFormat;
- video_def->eColorFormat = OMX_COLOR_FormatUnused;
+ video_def->nStride = stride;
+ video_def->nSliceHeight = sliceHeight;
+ video_def->xFramerate = (frameRate << 16); // Q16 format
+ video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ video_def->eColorFormat = colorFormat;
err = mOMX->setParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, OK);
- ////////////////////////////////////////////////////////////////////////////
-
+ //////////////////////// Output port /////////////////////////
+ CHECK_EQ(setVideoPortFormatType(
+ kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused),
+ OK);
InitOMXParams(&def);
- def.nPortIndex = kPortIndexInput;
+ def.nPortIndex = kPortIndexOutput;
err = mOMX->getParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
- CHECK_EQ(err, OK);
-
- def.nBufferSize = getFrameSize(colorFormat, width, height);
- CODEC_LOGV("Setting nBufferSize = %ld", def.nBufferSize);
+ CHECK_EQ(err, OK);
CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
video_def->nFrameWidth = width;
video_def->nFrameHeight = height;
- video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
- video_def->eColorFormat = colorFormat;
-
- video_def->xFramerate = 24 << 16; // XXX crucial!
+ video_def->xFramerate = 0; // No need for output port
+ video_def->nBitrate = bitRate; // Q16 format
+ video_def->eCompressionFormat = compressionFormat;
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
err = mOMX->setParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
CHECK_EQ(err, OK);
+ /////////////////// Codec-specific ////////////////////////
switch (compressionFormat) {
case OMX_VIDEO_CodingMPEG4:
{
- CHECK_EQ(setupMPEG4EncoderParameters(), OK);
+ CHECK_EQ(setupMPEG4EncoderParameters(meta), OK);
break;
}
case OMX_VIDEO_CodingH263:
+ CHECK_EQ(setupH263EncoderParameters(meta), OK);
break;
case OMX_VIDEO_CodingAVC:
{
- CHECK_EQ(setupAVCEncoderParameters(), OK);
+ CHECK_EQ(setupAVCEncoderParameters(meta), OK);
break;
}
@@ -790,84 +873,212 @@ void OMXCodec::setVideoInputFormat(
}
}
-status_t OMXCodec::setupMPEG4EncoderParameters() {
- OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
- InitOMXParams(&mpeg4type);
- mpeg4type.nPortIndex = kPortIndexOutput;
+static OMX_U32 setPFramesSpacing(int32_t iFramesInterval, int32_t frameRate) {
+ if (iFramesInterval < 0) {
+ return 0xFFFFFFFF;
+ } else if (iFramesInterval == 0) {
+ return 0;
+ }
+ OMX_U32 ret = frameRate * iFramesInterval;
+ CHECK(ret > 1);
+ return ret;
+}
+
+status_t OMXCodec::setupErrorCorrectionParameters() {
+ OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
+ InitOMXParams(&errorCorrectionType);
+ errorCorrectionType.nPortIndex = kPortIndexOutput;
status_t err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+ mNode, OMX_IndexParamVideoErrorCorrection,
+ &errorCorrectionType, sizeof(errorCorrectionType));
CHECK_EQ(err, OK);
- mpeg4type.nSliceHeaderSpacing = 0;
- mpeg4type.bSVH = OMX_FALSE;
- mpeg4type.bGov = OMX_FALSE;
-
- mpeg4type.nAllowedPictureTypes =
- OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
-
- mpeg4type.nPFrames = 23;
- mpeg4type.nBFrames = 0;
-
- mpeg4type.nIDCVLCThreshold = 0;
- mpeg4type.bACPred = OMX_TRUE;
- mpeg4type.nMaxPacketSize = 256;
- mpeg4type.nTimeIncRes = 1000;
- mpeg4type.nHeaderExtension = 0;
- mpeg4type.bReversibleVLC = OMX_FALSE;
-
- mpeg4type.eProfile = OMX_VIDEO_MPEG4ProfileCore;
- mpeg4type.eLevel = OMX_VIDEO_MPEG4Level2;
+ errorCorrectionType.bEnableHEC = OMX_FALSE;
+ errorCorrectionType.bEnableResync = OMX_TRUE;
+ errorCorrectionType.nResynchMarkerSpacing = 256;
+ errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
+ errorCorrectionType.bEnableRVLC = OMX_FALSE;
err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+ mNode, OMX_IndexParamVideoErrorCorrection,
+ &errorCorrectionType, sizeof(errorCorrectionType));
CHECK_EQ(err, OK);
+ return OK;
+}
- // ----------------
-
+status_t OMXCodec::setupBitRate(int32_t bitRate) {
OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
InitOMXParams(&bitrateType);
bitrateType.nPortIndex = kPortIndexOutput;
- err = mOMX->getParameter(
+ status_t err = mOMX->getParameter(
mNode, OMX_IndexParamVideoBitrate,
&bitrateType, sizeof(bitrateType));
CHECK_EQ(err, OK);
bitrateType.eControlRate = OMX_Video_ControlRateVariable;
- bitrateType.nTargetBitrate = 1000000;
+ bitrateType.nTargetBitrate = bitRate;
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoBitrate,
&bitrateType, sizeof(bitrateType));
CHECK_EQ(err, OK);
+ return OK;
+}
- // ----------------
+status_t OMXCodec::getVideoProfileLevel(
+ const sp<MetaData>& meta,
+ const CodecProfileLevel& defaultProfileLevel,
+ CodecProfileLevel &profileLevel) {
+ CODEC_LOGV("Default profile: %ld, level %ld",
+ defaultProfileLevel.mProfile, defaultProfileLevel.mLevel);
- OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrectionType;
- InitOMXParams(&errorCorrectionType);
- errorCorrectionType.nPortIndex = kPortIndexOutput;
+ // Are the default profile and level overwriten?
+ int32_t profile, level;
+ if (!meta->findInt32(kKeyVideoProfile, &profile)) {
+ profile = defaultProfileLevel.mProfile;
+ }
+ if (!meta->findInt32(kKeyVideoLevel, &level)) {
+ level = defaultProfileLevel.mLevel;
+ }
+ CODEC_LOGV("Target profile: %d, level: %d", profile, level);
- err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoErrorCorrection,
- &errorCorrectionType, sizeof(errorCorrectionType));
+ // Are the target profile and level supported by the encoder?
+ OMX_VIDEO_PARAM_PROFILELEVELTYPE param;
+ InitOMXParams(&param);
+ param.nPortIndex = kPortIndexOutput;
+ for (param.nProfileIndex = 0;; ++param.nProfileIndex) {
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoProfileLevelQuerySupported,
+ &param, sizeof(param));
+
+ if (err != OK) return err;
+
+ int32_t supportedProfile = static_cast<int32_t>(param.eProfile);
+ int32_t supportedLevel = static_cast<int32_t>(param.eLevel);
+ CODEC_LOGV("Supported profile: %d, level %d",
+ supportedProfile, supportedLevel);
+
+ if (profile == supportedProfile &&
+ level == supportedLevel) {
+ profileLevel.mProfile = profile;
+ profileLevel.mLevel = level;
+ return OK;
+ }
+ }
+
+ CODEC_LOGE("Target profile (%d) and level (%d) is not supported",
+ profile, level);
+ return BAD_VALUE;
+}
+
+status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
+ int32_t iFramesInterval, frameRate, bitRate;
+ bool success = meta->findInt32(kKeyBitRate, &bitRate);
+ success = success && meta->findInt32(kKeySampleRate, &frameRate);
+ success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+ CHECK(success);
+ OMX_VIDEO_PARAM_H263TYPE h263type;
+ InitOMXParams(&h263type);
+ h263type.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
CHECK_EQ(err, OK);
- errorCorrectionType.bEnableHEC = OMX_FALSE;
- errorCorrectionType.bEnableResync = OMX_TRUE;
- errorCorrectionType.nResynchMarkerSpacing = 256;
- errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
- errorCorrectionType.bEnableRVLC = OMX_FALSE;
+ h263type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+ h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ if (h263type.nPFrames == 0) {
+ h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+ h263type.nBFrames = 0;
+
+ // Check profile and level parameters
+ CodecProfileLevel defaultProfileLevel, profileLevel;
+ defaultProfileLevel.mProfile = OMX_VIDEO_H263ProfileBaseline;
+ defaultProfileLevel.mLevel = OMX_VIDEO_H263Level45;
+ err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
+ if (err != OK) return err;
+ h263type.eProfile = static_cast<OMX_VIDEO_H263PROFILETYPE>(profileLevel.mProfile);
+ h263type.eLevel = static_cast<OMX_VIDEO_H263LEVELTYPE>(profileLevel.mLevel);
+
+ h263type.bPLUSPTYPEAllowed = OMX_FALSE;
+ h263type.bForceRoundingTypeToZero = OMX_FALSE;
+ h263type.nPictureHeaderRepetition = 0;
+ h263type.nGOBHeaderInterval = 0;
err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoErrorCorrection,
- &errorCorrectionType, sizeof(errorCorrectionType));
+ mNode, OMX_IndexParamVideoH263, &h263type, sizeof(h263type));
+ CHECK_EQ(err, OK);
+
+ CHECK_EQ(setupBitRate(bitRate), OK);
+ CHECK_EQ(setupErrorCorrectionParameters(), OK);
+
+ return OK;
+}
+
+status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
+ int32_t iFramesInterval, frameRate, bitRate;
+ bool success = meta->findInt32(kKeyBitRate, &bitRate);
+ success = success && meta->findInt32(kKeySampleRate, &frameRate);
+ success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+ CHECK(success);
+ OMX_VIDEO_PARAM_MPEG4TYPE mpeg4type;
+ InitOMXParams(&mpeg4type);
+ mpeg4type.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
+ CHECK_EQ(err, OK);
+
+ mpeg4type.nSliceHeaderSpacing = 0;
+ mpeg4type.bSVH = OMX_FALSE;
+ mpeg4type.bGov = OMX_FALSE;
+
+ mpeg4type.nAllowedPictureTypes =
+ OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
+
+ mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ if (mpeg4type.nPFrames == 0) {
+ mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+ mpeg4type.nBFrames = 0;
+ mpeg4type.nIDCVLCThreshold = 0;
+ mpeg4type.bACPred = OMX_TRUE;
+ mpeg4type.nMaxPacketSize = 256;
+ mpeg4type.nTimeIncRes = 1000;
+ mpeg4type.nHeaderExtension = 0;
+ mpeg4type.bReversibleVLC = OMX_FALSE;
+
+ // Check profile and level parameters
+ CodecProfileLevel defaultProfileLevel, profileLevel;
+ defaultProfileLevel.mProfile = OMX_VIDEO_MPEG4ProfileSimple;
+ defaultProfileLevel.mLevel = OMX_VIDEO_MPEG4Level2;
+ err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
+ if (err != OK) return err;
+ mpeg4type.eProfile = static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profileLevel.mProfile);
+ mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(profileLevel.mLevel);
+
+ err = mOMX->setParameter(
+ mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
CHECK_EQ(err, OK);
+ CHECK_EQ(setupBitRate(bitRate), OK);
+ CHECK_EQ(setupErrorCorrectionParameters(), OK);
+
return OK;
}
-status_t OMXCodec::setupAVCEncoderParameters() {
+status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
+ int32_t iFramesInterval, frameRate, bitRate;
+ bool success = meta->findInt32(kKeyBitRate, &bitRate);
+ success = success && meta->findInt32(kKeySampleRate, &frameRate);
+ success = success && meta->findInt32(kKeyIFramesInterval, &iFramesInterval);
+ CHECK(success);
+
OMX_VIDEO_PARAM_AVCTYPE h264type;
InitOMXParams(&h264type);
h264type.nPortIndex = kPortIndexOutput;
@@ -880,47 +1091,51 @@ status_t OMXCodec::setupAVCEncoderParameters() {
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
h264type.nSliceHeaderSpacing = 0;
- h264type.nBFrames = 0;
- h264type.bUseHadamard = OMX_TRUE;
- h264type.nRefFrames = 1;
- h264type.nRefIdx10ActiveMinus1 = 0;
- h264type.nRefIdx11ActiveMinus1 = 0;
+ h264type.nBFrames = 0; // No B frames support yet
+ h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ if (h264type.nPFrames == 0) {
+ h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+ }
+
+ // Check profile and level parameters
+ CodecProfileLevel defaultProfileLevel, profileLevel;
+ defaultProfileLevel.mProfile = h264type.eProfile;
+ defaultProfileLevel.mLevel = h264type.eLevel;
+ err = getVideoProfileLevel(meta, defaultProfileLevel, profileLevel);
+ if (err != OK) return err;
+ h264type.eProfile = static_cast<OMX_VIDEO_AVCPROFILETYPE>(profileLevel.mProfile);
+ h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
+
+ if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+ h264type.bUseHadamard = OMX_TRUE;
+ h264type.nRefFrames = 1;
+ h264type.nRefIdx10ActiveMinus1 = 0;
+ h264type.nRefIdx11ActiveMinus1 = 0;
+ h264type.bEntropyCodingCABAC = OMX_FALSE;
+ h264type.bWeightedPPrediction = OMX_FALSE;
+ h264type.bconstIpred = OMX_FALSE;
+ h264type.bDirect8x8Inference = OMX_FALSE;
+ h264type.bDirectSpatialTemporal = OMX_FALSE;
+ h264type.nCabacInitIdc = 0;
+ }
+
+ if (h264type.nBFrames != 0) {
+ h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
+ }
+
h264type.bEnableUEP = OMX_FALSE;
h264type.bEnableFMO = OMX_FALSE;
h264type.bEnableASO = OMX_FALSE;
h264type.bEnableRS = OMX_FALSE;
- h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
- h264type.eLevel = OMX_VIDEO_AVCLevel1b;
h264type.bFrameMBsOnly = OMX_TRUE;
h264type.bMBAFF = OMX_FALSE;
- h264type.bEntropyCodingCABAC = OMX_FALSE;
- h264type.bWeightedPPrediction = OMX_FALSE;
- h264type.bconstIpred = OMX_FALSE;
- h264type.bDirect8x8Inference = OMX_FALSE;
- h264type.bDirectSpatialTemporal = OMX_FALSE;
- h264type.nCabacInitIdc = 0;
h264type.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoAvc, &h264type, sizeof(h264type));
CHECK_EQ(err, OK);
- OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
- InitOMXParams(&bitrateType);
- bitrateType.nPortIndex = kPortIndexOutput;
-
- err = mOMX->getParameter(
- mNode, OMX_IndexParamVideoBitrate,
- &bitrateType, sizeof(bitrateType));
- CHECK_EQ(err, OK);
-
- bitrateType.eControlRate = OMX_Video_ControlRateVariable;
- bitrateType.nTargetBitrate = 1000000;
-
- err = mOMX->setParameter(
- mNode, OMX_IndexParamVideoBitrate,
- &bitrateType, sizeof(bitrateType));
- CHECK_EQ(err, OK);
+ CHECK_EQ(setupBitRate(bitRate), OK);
return OK;
}
@@ -1057,7 +1272,11 @@ OMXCodec::OMXCodec(
mNoMoreOutputData(false),
mOutputPortSettingsHaveChanged(false),
mSeekTimeUs(-1),
- mLeftOverBuffer(NULL) {
+ mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
+ mTargetTimeUs(-1),
+ mSkipTimeUs(-1),
+ mLeftOverBuffer(NULL),
+ mPaused(false) {
mPortStatus[kPortIndexInput] = ENABLED;
mPortStatus[kPortIndexOutput] = ENABLED;
@@ -1424,13 +1643,33 @@ void OMXCodec::on_message(const omx_message &msg) {
kKeyBufferID,
msg.u.extended_buffer_data.buffer);
- mFilledBuffers.push_back(i);
- mBufferFilled.signal();
-
if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_EOS) {
CODEC_LOGV("No more output data.");
mNoMoreOutputData = true;
}
+
+ if (mTargetTimeUs >= 0) {
+ CHECK(msg.u.extended_buffer_data.timestamp <= mTargetTimeUs);
+
+ if (msg.u.extended_buffer_data.timestamp < mTargetTimeUs) {
+ CODEC_LOGV(
+ "skipping output buffer at timestamp %lld us",
+ msg.u.extended_buffer_data.timestamp);
+
+ fillOutputBuffer(info);
+ break;
+ }
+
+ CODEC_LOGV(
+ "returning output buffer at target timestamp "
+ "%lld us",
+ msg.u.extended_buffer_data.timestamp);
+
+ mTargetTimeUs = -1;
+ }
+
+ mFilledBuffers.push_back(i);
+ mBufferFilled.signal();
}
break;
@@ -1647,6 +1886,9 @@ void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
CODEC_LOGV("Finished flushing both ports, now continuing from"
" seek-time.");
+ // We implicitly resume pulling on our upstream source.
+ mPaused = false;
+
drainInputBuffers();
fillOutputBuffers();
}
@@ -1946,6 +2188,10 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
return;
}
+ if (mPaused) {
+ return;
+ }
+
status_t err;
bool signalEOS = false;
@@ -1955,26 +2201,40 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
int32_t n = 0;
for (;;) {
MediaBuffer *srcBuffer;
+ MediaSource::ReadOptions options;
+ if (mSkipTimeUs >= 0) {
+ options.setSkipFrame(mSkipTimeUs);
+ }
if (mSeekTimeUs >= 0) {
if (mLeftOverBuffer) {
mLeftOverBuffer->release();
mLeftOverBuffer = NULL;
}
-
- MediaSource::ReadOptions options;
- options.setSeekTo(mSeekTimeUs);
+ options.setSeekTo(mSeekTimeUs, mSeekMode);
mSeekTimeUs = -1;
+ mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
mBufferFilled.signal();
err = mSource->read(&srcBuffer, &options);
+
+ if (err == OK) {
+ int64_t targetTimeUs;
+ if (srcBuffer->meta_data()->findInt64(
+ kKeyTargetTime, &targetTimeUs)
+ && targetTimeUs >= 0) {
+ mTargetTimeUs = targetTimeUs;
+ } else {
+ mTargetTimeUs = -1;
+ }
+ }
} else if (mLeftOverBuffer) {
srcBuffer = mLeftOverBuffer;
mLeftOverBuffer = NULL;
err = OK;
} else {
- err = mSource->read(&srcBuffer);
+ err = mSource->read(&srcBuffer, &options);
}
if (err != OK) {
@@ -2004,13 +2264,19 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
break;
}
- memcpy((uint8_t *)info->mData + offset,
- (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
- srcBuffer->range_length());
+ if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+ CHECK(mOMXLivesLocally && offset == 0);
+ OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
+ header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
+ } else {
+ memcpy((uint8_t *)info->mData + offset,
+ (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+ srcBuffer->range_length());
+ }
int64_t lastBufferTimeUs;
CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
- CHECK(timestampUs >= 0);
+ CHECK(lastBufferTimeUs >= 0);
if (offset == 0) {
timestampUs = lastBufferTimeUs;
@@ -2128,11 +2394,24 @@ void OMXCodec::setState(State newState) {
void OMXCodec::setRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+
+ // port definition
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = portIndex;
+ status_t err = mOMX->getParameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+ def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
+ &def, sizeof(def)), OK);
+
+ // pcm param
OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
InitOMXParams(&pcmParams);
pcmParams.nPortIndex = portIndex;
- status_t err = mOMX->getParameter(
+ err = mOMX->getParameter(
mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
CHECK_EQ(err, OK);
@@ -2159,7 +2438,51 @@ void OMXCodec::setRawAudioFormat(
CHECK_EQ(err, OK);
}
-void OMXCodec::setAMRFormat(bool isWAMR) {
+static OMX_AUDIO_AMRBANDMODETYPE pickModeFromBitRate(bool isAMRWB, int32_t bps) {
+ if (isAMRWB) {
+ if (bps <= 6600) {
+ return OMX_AUDIO_AMRBandModeWB0;
+ } else if (bps <= 8850) {
+ return OMX_AUDIO_AMRBandModeWB1;
+ } else if (bps <= 12650) {
+ return OMX_AUDIO_AMRBandModeWB2;
+ } else if (bps <= 14250) {
+ return OMX_AUDIO_AMRBandModeWB3;
+ } else if (bps <= 15850) {
+ return OMX_AUDIO_AMRBandModeWB4;
+ } else if (bps <= 18250) {
+ return OMX_AUDIO_AMRBandModeWB5;
+ } else if (bps <= 19850) {
+ return OMX_AUDIO_AMRBandModeWB6;
+ } else if (bps <= 23050) {
+ return OMX_AUDIO_AMRBandModeWB7;
+ }
+
+ // 23850 bps
+ return OMX_AUDIO_AMRBandModeWB8;
+ } else { // AMRNB
+ if (bps <= 4750) {
+ return OMX_AUDIO_AMRBandModeNB0;
+ } else if (bps <= 5150) {
+ return OMX_AUDIO_AMRBandModeNB1;
+ } else if (bps <= 5900) {
+ return OMX_AUDIO_AMRBandModeNB2;
+ } else if (bps <= 6700) {
+ return OMX_AUDIO_AMRBandModeNB3;
+ } else if (bps <= 7400) {
+ return OMX_AUDIO_AMRBandModeNB4;
+ } else if (bps <= 7950) {
+ return OMX_AUDIO_AMRBandModeNB5;
+ } else if (bps <= 10200) {
+ return OMX_AUDIO_AMRBandModeNB6;
+ }
+
+ // 12200 bps
+ return OMX_AUDIO_AMRBandModeNB7;
+ }
+}
+
+void OMXCodec::setAMRFormat(bool isWAMR, int32_t bitRate) {
OMX_U32 portIndex = mIsEncoder ? kPortIndexOutput : kPortIndexInput;
OMX_AUDIO_PARAM_AMRTYPE def;
@@ -2172,9 +2495,8 @@ void OMXCodec::setAMRFormat(bool isWAMR) {
CHECK_EQ(err, OK);
def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
- def.eAMRBandMode =
- isWAMR ? OMX_AUDIO_AMRBandModeWB0 : OMX_AUDIO_AMRBandModeNB0;
+ def.eAMRBandMode = pickModeFromBitRate(isWAMR, bitRate);
err = mOMX->setParameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
CHECK_EQ(err, OK);
@@ -2191,9 +2513,61 @@ void OMXCodec::setAMRFormat(bool isWAMR) {
}
}
-void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate) {
+void OMXCodec::setAACFormat(int32_t numChannels, int32_t sampleRate, int32_t bitRate) {
+ CHECK(numChannels == 1 || numChannels == 2);
if (mIsEncoder) {
+ //////////////// input port ////////////////////
setRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+
+ //////////////// output port ////////////////////
+ // format
+ OMX_AUDIO_PARAM_PORTFORMATTYPE format;
+ format.nPortIndex = kPortIndexOutput;
+ format.nIndex = 0;
+ status_t err = OMX_ErrorNone;
+ while (OMX_ErrorNone == err) {
+ CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioPortFormat,
+ &format, sizeof(format)), OK);
+ if (format.eEncoding == OMX_AUDIO_CodingAAC) {
+ break;
+ }
+ format.nIndex++;
+ }
+ CHECK_EQ(OK, err);
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioPortFormat,
+ &format, sizeof(format)), OK);
+
+ // port definition
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ InitOMXParams(&def);
+ def.nPortIndex = kPortIndexOutput;
+ CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamPortDefinition,
+ &def, sizeof(def)), OK);
+ def.format.audio.bFlagErrorConcealment = OMX_TRUE;
+ def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamPortDefinition,
+ &def, sizeof(def)), OK);
+
+ // profile
+ OMX_AUDIO_PARAM_AACPROFILETYPE profile;
+ InitOMXParams(&profile);
+ profile.nPortIndex = kPortIndexOutput;
+ CHECK_EQ(mOMX->getParameter(mNode, OMX_IndexParamAudioAac,
+ &profile, sizeof(profile)), OK);
+ profile.nChannels = numChannels;
+ profile.eChannelMode = (numChannels == 1?
+ OMX_AUDIO_ChannelModeMono: OMX_AUDIO_ChannelModeStereo);
+ profile.nSampleRate = sampleRate;
+ profile.nBitRate = bitRate;
+ profile.nAudioBandWidth = 0;
+ profile.nFrameLength = 0;
+ profile.nAACtools = OMX_AUDIO_AACToolAll;
+ profile.nAACERtools = OMX_AUDIO_AACERNone;
+ profile.eAACProfile = OMX_AUDIO_AACObjectLC;
+ profile.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
+ CHECK_EQ(mOMX->setParameter(mNode, OMX_IndexParamAudioAac,
+ &profile, sizeof(profile)), OK);
+
} else {
OMX_AUDIO_PARAM_AACPROFILETYPE profile;
InitOMXParams(&profile);
@@ -2328,7 +2702,7 @@ void OMXCodec::clearCodecSpecificData() {
mCodecSpecificDataIndex = 0;
}
-status_t OMXCodec::start(MetaData *) {
+status_t OMXCodec::start(MetaData *meta) {
Mutex::Autolock autoLock(mLock);
if (mState != LOADED) {
@@ -2339,6 +2713,14 @@ status_t OMXCodec::start(MetaData *) {
if (mQuirks & kWantsNALFragments) {
params->setInt32(kKeyWantsNALFragments, true);
}
+ if (meta) {
+ int64_t startTimeUs = 0;
+ int64_t timeUs;
+ if (meta->findInt64(kKeyTime, &timeUs)) {
+ startTimeUs = timeUs;
+ }
+ params->setInt64(kKeyTime, startTimeUs);
+ }
status_t err = mSource->start(params.get());
if (err != OK) {
@@ -2351,7 +2733,10 @@ status_t OMXCodec::start(MetaData *) {
mNoMoreOutputData = false;
mOutputPortSettingsHaveChanged = false;
mSeekTimeUs = -1;
+ mSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
+ mTargetTimeUs = -1;
mFilledBuffers.clear();
+ mPaused = false;
return init();
}
@@ -2444,9 +2829,16 @@ status_t OMXCodec::read(
bool seeking = false;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode seekMode;
+ if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
seeking = true;
}
+ int64_t skipTimeUs;
+ if (options && options->getSkipFrame(&skipTimeUs)) {
+ mSkipTimeUs = skipTimeUs;
+ } else {
+ mSkipTimeUs = -1;
+ }
if (mInitialBufferSubmit) {
mInitialBufferSubmit = false;
@@ -2454,10 +2846,12 @@ status_t OMXCodec::read(
if (seeking) {
CHECK(seekTimeUs >= 0);
mSeekTimeUs = seekTimeUs;
+ mSeekMode = seekMode;
// There's no reason to trigger the code below, there's
// nothing to flush yet.
seeking = false;
+ mPaused = false;
}
drainInputBuffers();
@@ -2476,6 +2870,7 @@ status_t OMXCodec::read(
CHECK(seekTimeUs >= 0);
mSeekTimeUs = seekTimeUs;
+ mSeekMode = seekMode;
mFilledBuffers.clear();
@@ -2870,6 +3265,12 @@ void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
mOutputFormat = new MetaData;
mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
+ if (mIsEncoder) {
+ int32_t timeScale;
+ if (inputFormat->findInt32(kKeyTimeScale, &timeScale)) {
+ mOutputFormat->setInt32(kKeyTimeScale, timeScale);
+ }
+ }
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
@@ -2962,6 +3363,13 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
} else if (audio_def->eEncoding == OMX_AUDIO_CodingAAC) {
mOutputFormat->setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ int32_t numChannels, sampleRate, bitRate;
+ inputFormat->findInt32(kKeyChannelCount, &numChannels);
+ inputFormat->findInt32(kKeySampleRate, &sampleRate);
+ inputFormat->findInt32(kKeyBitRate, &bitRate);
+ mOutputFormat->setInt32(kKeyChannelCount, numChannels);
+ mOutputFormat->setInt32(kKeySampleRate, sampleRate);
+ mOutputFormat->setInt32(kKeyBitRate, bitRate);
} else {
CHECK(!"Should not be here. Unknown audio encoding.");
}
@@ -3011,6 +3419,14 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
}
}
+status_t OMXCodec::pause() {
+ Mutex::Autolock autoLock(mLock);
+
+ mPaused = true;
+
+ return OK;
+}
+
////////////////////////////////////////////////////////////////////////////////
status_t QueryCodecs(
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index d0d1b14..c267a23 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -76,7 +76,9 @@ struct MyVorbisExtractor {
status_t seekToOffset(off_t offset);
status_t readNextPacket(MediaBuffer **buffer);
- void init();
+ status_t init();
+
+ sp<MetaData> getFileMetaData() { return mFileMeta; }
private:
struct Page {
@@ -100,13 +102,17 @@ private:
vorbis_comment mVc;
sp<MetaData> mMeta;
+ sp<MetaData> mFileMeta;
ssize_t readPage(off_t offset, Page *page);
status_t findNextPage(off_t startOffset, off_t *pageOffset);
- void verifyHeader(
+ status_t verifyHeader(
MediaBuffer *buffer, uint8_t type);
+ void parseFileMetaData();
+ void extractAlbumArt(const void *data, size_t size);
+
MyVorbisExtractor(const MyVorbisExtractor &);
MyVorbisExtractor &operator=(const MyVorbisExtractor &);
};
@@ -149,7 +155,8 @@ status_t OggSource::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll;
LOGI("seeking to offset %ld", pos);
@@ -188,9 +195,14 @@ MyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
mNextLaceIndex(0),
mFirstDataOffset(-1) {
mCurrentPage.mNumSegments = 0;
+
+ vorbis_info_init(&mVi);
+ vorbis_comment_init(&mVc);
}
MyVorbisExtractor::~MyVorbisExtractor() {
+ vorbis_comment_clear(&mVc);
+ vorbis_info_clear(&mVi);
}
sp<MetaData> MyVorbisExtractor::getFormat() const {
@@ -297,6 +309,7 @@ ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) {
totalSize += page->mLace[i];
}
+#if 0
String8 tmp;
for (size_t i = 0; i < page->mNumSegments; ++i) {
char x[32];
@@ -306,6 +319,7 @@ ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) {
}
LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string());
+#endif
return sizeof(header) + page->mNumSegments + totalSize;
}
@@ -421,47 +435,60 @@ status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) {
}
}
-void MyVorbisExtractor::init() {
- vorbis_info_init(&mVi);
-
- vorbis_comment mVc;
-
+status_t MyVorbisExtractor::init() {
mMeta = new MetaData;
mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
MediaBuffer *packet;
- CHECK_EQ(readNextPacket(&packet), OK);
+ status_t err;
+ if ((err = readNextPacket(&packet)) != OK) {
+ return err;
+ }
LOGV("read packet of size %d\n", packet->range_length());
- verifyHeader(packet, 1);
+ err = verifyHeader(packet, 1);
packet->release();
packet = NULL;
+ if (err != OK) {
+ return err;
+ }
- CHECK_EQ(readNextPacket(&packet), OK);
+ if ((err = readNextPacket(&packet)) != OK) {
+ return err;
+ }
LOGV("read packet of size %d\n", packet->range_length());
- verifyHeader(packet, 3);
+ err = verifyHeader(packet, 3);
packet->release();
packet = NULL;
+ if (err != OK) {
+ return err;
+ }
- CHECK_EQ(readNextPacket(&packet), OK);
+ if ((err = readNextPacket(&packet)) != OK) {
+ return err;
+ }
LOGV("read packet of size %d\n", packet->range_length());
- verifyHeader(packet, 5);
+ err = verifyHeader(packet, 5);
packet->release();
packet = NULL;
+ if (err != OK) {
+ return err;
+ }
mFirstDataOffset = mOffset + mCurrentPageSize;
+
+ return OK;
}
-void MyVorbisExtractor::verifyHeader(
+status_t MyVorbisExtractor::verifyHeader(
MediaBuffer *buffer, uint8_t type) {
const uint8_t *data =
(const uint8_t *)buffer->data() + buffer->range_offset();
size_t size = buffer->range_length();
- CHECK(size >= 7);
-
- CHECK_EQ(data[0], type);
- CHECK(!memcmp(&data[1], "vorbis", 6));
+ if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) {
+ return ERROR_MALFORMED;
+ }
ogg_buffer buf;
buf.data = (uint8_t *)data;
@@ -508,18 +535,26 @@ void MyVorbisExtractor::verifyHeader(
case 3:
{
- CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits));
+ if (0 != _vorbis_unpack_comment(&mVc, &bits)) {
+ return ERROR_MALFORMED;
+ }
+
+ parseFileMetaData();
break;
}
case 5:
{
- CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits));
+ if (0 != _vorbis_unpack_books(&mVi, &bits)) {
+ return ERROR_MALFORMED;
+ }
mMeta->setData(kKeyVorbisBooks, 0, data, size);
break;
}
}
+
+ return OK;
}
uint64_t MyVorbisExtractor::approxBitrate() {
@@ -530,6 +565,192 @@ uint64_t MyVorbisExtractor::approxBitrate() {
return (mVi.bitrate_lower + mVi.bitrate_upper) / 2;
}
+void MyVorbisExtractor::parseFileMetaData() {
+ mFileMeta = new MetaData;
+ mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
+
+ struct {
+ const char *const mTag;
+ uint32_t mKey;
+ } kMap[] = {
+ { "TITLE", kKeyTitle },
+ { "ARTIST", kKeyArtist },
+ { "ALBUM", kKeyAlbum },
+ { "COMPOSER", kKeyComposer },
+ { "GENRE", kKeyGenre },
+ { "AUTHOR", kKeyAuthor },
+ { "TRACKNUMBER", kKeyCDTrackNumber },
+ { "DISCNUMBER", kKeyDiscNumber },
+ { "DATE", kKeyDate },
+ { "LYRICIST", kKeyWriter },
+ { "METADATA_BLOCK_PICTURE", kKeyAlbumArt },
+ };
+
+ for (int i = 0; i < mVc.comments; ++i) {
+ const char *comment = mVc.user_comments[i];
+
+ for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) {
+ size_t tagLen = strlen(kMap[j].mTag);
+ if (!strncasecmp(kMap[j].mTag, comment, tagLen)
+ && comment[tagLen] == '=') {
+ if (kMap[j].mKey == kKeyAlbumArt) {
+ extractAlbumArt(
+ &comment[tagLen + 1],
+ mVc.comment_lengths[i] - tagLen - 1);
+ } else {
+ mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]);
+ }
+ }
+ }
+
+ }
+
+#if 0
+ for (int i = 0; i < mVc.comments; ++i) {
+ LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
+ }
+#endif
+}
+
+// The returned buffer should be free()d.
+static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) {
+ *outSize = 0;
+
+ if ((size % 4) != 0) {
+ return NULL;
+ }
+
+ size_t n = size;
+ size_t padding = 0;
+ if (n >= 1 && s[n - 1] == '=') {
+ padding = 1;
+
+ if (n >= 2 && s[n - 2] == '=') {
+ padding = 2;
+ }
+ }
+
+ size_t outLen = 3 * size / 4 - padding;
+
+ *outSize = outLen;
+
+ void *buffer = malloc(outLen);
+
+ uint8_t *out = (uint8_t *)buffer;
+ size_t j = 0;
+ uint32_t accum = 0;
+ for (size_t i = 0; i < n; ++i) {
+ char c = s[i];
+ unsigned value;
+ if (c >= 'A' && c <= 'Z') {
+ value = c - 'A';
+ } else if (c >= 'a' && c <= 'z') {
+ value = 26 + c - 'a';
+ } else if (c >= '0' && c <= '9') {
+ value = 52 + c - '0';
+ } else if (c == '+') {
+ value = 62;
+ } else if (c == '/') {
+ value = 63;
+ } else if (c != '=') {
+ return NULL;
+ } else {
+ if (i < n - padding) {
+ return NULL;
+ }
+
+ value = 0;
+ }
+
+ accum = (accum << 6) | value;
+
+ if (((i + 1) % 4) == 0) {
+ out[j++] = (accum >> 16);
+
+ if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
+ if (j < outLen) { out[j++] = accum & 0xff; }
+
+ accum = 0;
+ }
+ }
+
+ return (uint8_t *)buffer;
+}
+
+void MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) {
+ LOGV("extractAlbumArt from '%s'", (const char *)data);
+
+ size_t flacSize;
+ uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize);
+
+ if (flac == NULL) {
+ LOGE("malformed base64 encoded data.");
+ return;
+ }
+
+ LOGV("got flac of size %d", flacSize);
+
+ uint32_t picType;
+ uint32_t typeLen;
+ uint32_t descLen;
+ uint32_t dataLen;
+ char type[128];
+
+ if (flacSize < 8) {
+ goto exit;
+ }
+
+ picType = U32_AT(flac);
+
+ if (picType != 3) {
+ // This is not a front cover.
+ goto exit;
+ }
+
+ typeLen = U32_AT(&flac[4]);
+ if (typeLen + 1 > sizeof(type)) {
+ goto exit;
+ }
+
+ if (flacSize < 8 + typeLen) {
+ goto exit;
+ }
+
+ memcpy(type, &flac[8], typeLen);
+ type[typeLen] = '\0';
+
+ LOGV("picType = %d, type = '%s'", picType, type);
+
+ if (!strcmp(type, "-->")) {
+ // This is not inline cover art, but an external url instead.
+ goto exit;
+ }
+
+ descLen = U32_AT(&flac[8 + typeLen]);
+
+ if (flacSize < 32 + typeLen + descLen) {
+ goto exit;
+ }
+
+ dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]);
+
+ if (flacSize < 32 + typeLen + descLen + dataLen) {
+ goto exit;
+ }
+
+ LOGV("got image data, %d trailing bytes",
+ flacSize - 32 - typeLen - descLen - dataLen);
+
+ mFileMeta->setData(
+ kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen);
+
+ mFileMeta->setCString(kKeyAlbumArtMIME, type);
+
+exit:
+ free(flac);
+ flac = NULL;
+}
+
////////////////////////////////////////////////////////////////////////////////
OggExtractor::OggExtractor(const sp<DataSource> &source)
@@ -537,10 +758,11 @@ OggExtractor::OggExtractor(const sp<DataSource> &source)
mInitCheck(NO_INIT),
mImpl(NULL) {
mImpl = new MyVorbisExtractor(mDataSource);
- CHECK_EQ(mImpl->seekToOffset(0), OK);
- mImpl->init();
+ mInitCheck = mImpl->seekToOffset(0);
- mInitCheck = OK;
+ if (mInitCheck == OK) {
+ mInitCheck = mImpl->init();
+ }
}
OggExtractor::~OggExtractor() {
@@ -570,15 +792,7 @@ sp<MetaData> OggExtractor::getTrackMetaData(
}
sp<MetaData> OggExtractor::getMetaData() {
- sp<MetaData> meta = new MetaData;
-
- if (mInitCheck != OK) {
- return meta;
- }
-
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG);
-
- return meta;
+ return mImpl->getFileMetaData();
}
bool SniffOgg(
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
deleted file mode 100644
index 650a9f9..0000000
--- a/media/libstagefright/Prefetcher.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Prefetcher"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include "include/Prefetcher.h"
-
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MediaDebug.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-#include <utils/List.h>
-
-namespace android {
-
-struct PrefetchedSource : public MediaSource {
- PrefetchedSource(
- size_t index,
- const sp<MediaSource> &source);
-
- virtual status_t start(MetaData *params);
- virtual status_t stop();
-
- virtual status_t read(
- MediaBuffer **buffer, const ReadOptions *options);
-
- virtual sp<MetaData> getFormat();
-
-protected:
- virtual ~PrefetchedSource();
-
-private:
- friend struct Prefetcher;
-
- Mutex mLock;
- Condition mCondition;
-
- sp<MediaSource> mSource;
- size_t mIndex;
- bool mStarted;
- bool mReachedEOS;
- status_t mFinalStatus;
- int64_t mSeekTimeUs;
- int64_t mCacheDurationUs;
- size_t mCacheSizeBytes;
- bool mPrefetcherStopped;
- bool mCurrentlyPrefetching;
-
- List<MediaBuffer *> mCachedBuffers;
-
- // Returns true iff source is currently caching.
- bool getCacheDurationUs(int64_t *durationUs, size_t *totalSize = NULL);
-
- void updateCacheDuration_l();
- void clearCache_l();
-
- void cacheMore();
- void onPrefetcherStopped();
-
- PrefetchedSource(const PrefetchedSource &);
- PrefetchedSource &operator=(const PrefetchedSource &);
-};
-
-Prefetcher::Prefetcher()
- : mDone(false),
- mThreadExited(false) {
- startThread();
-}
-
-Prefetcher::~Prefetcher() {
- stopThread();
-}
-
-sp<MediaSource> Prefetcher::addSource(const sp<MediaSource> &source) {
- Mutex::Autolock autoLock(mLock);
-
- sp<PrefetchedSource> psource =
- new PrefetchedSource(mSources.size(), source);
-
- mSources.add(psource);
-
- return psource;
-}
-
-void Prefetcher::startThread() {
- mThreadExited = false;
- mDone = false;
-
- int res = androidCreateThreadEtc(
- ThreadWrapper, this, "Prefetcher",
- ANDROID_PRIORITY_DEFAULT, 0, &mThread);
-
- CHECK_EQ(res, 1);
-}
-
-void Prefetcher::stopThread() {
- Mutex::Autolock autoLock(mLock);
-
- while (!mThreadExited) {
- mDone = true;
- mCondition.signal();
- mCondition.wait(mLock);
- }
-}
-
-// static
-int Prefetcher::ThreadWrapper(void *me) {
- static_cast<Prefetcher *>(me)->threadFunc();
-
- return 0;
-}
-
-// Cache at most 1 min for each source.
-static int64_t kMaxCacheDurationUs = 60 * 1000000ll;
-
-// At the same time cache at most 5MB per source.
-static size_t kMaxCacheSizeBytes = 5 * 1024 * 1024;
-
-// If the amount of cached data drops below this,
-// fill the cache up to the max duration again.
-static int64_t kLowWaterDurationUs = 5000000ll;
-
-void Prefetcher::threadFunc() {
- bool fillingCache = false;
-
- for (;;) {
- sp<PrefetchedSource> minSource;
- int64_t minCacheDurationUs = -1;
-
- {
- Mutex::Autolock autoLock(mLock);
- if (mDone) {
- break;
- }
-
- mCondition.waitRelative(
- mLock, fillingCache ? 1ll : 1000000000ll);
-
-
- ssize_t minIndex = -1;
- for (size_t i = 0; i < mSources.size(); ++i) {
- sp<PrefetchedSource> source = mSources[i].promote();
-
- if (source == NULL) {
- continue;
- }
-
- int64_t cacheDurationUs;
- size_t cacheSizeBytes;
- if (!source->getCacheDurationUs(&cacheDurationUs, &cacheSizeBytes)) {
- continue;
- }
-
- if (cacheSizeBytes > kMaxCacheSizeBytes) {
- LOGI("max cache size reached");
- continue;
- }
-
- if (mSources.size() > 1 && cacheDurationUs >= kMaxCacheDurationUs) {
- LOGI("max duration reached, size = %d bytes", cacheSizeBytes);
- continue;
- }
-
- if (minIndex < 0 || cacheDurationUs < minCacheDurationUs) {
- minCacheDurationUs = cacheDurationUs;
- minIndex = i;
- minSource = source;
- }
- }
-
- if (minIndex < 0) {
- if (fillingCache) {
- LOGV("[%p] done filling the cache, above high water mark.",
- this);
- fillingCache = false;
- }
- continue;
- }
- }
-
- if (!fillingCache && minCacheDurationUs < kLowWaterDurationUs) {
- LOGI("[%p] cache below low water mark, filling cache.", this);
- fillingCache = true;
- }
-
- if (fillingCache) {
- // Make sure not to hold the lock while calling into the source.
- // The lock guards the list of sources, not the individual sources
- // themselves.
- minSource->cacheMore();
- }
- }
-
- Mutex::Autolock autoLock(mLock);
- for (size_t i = 0; i < mSources.size(); ++i) {
- sp<PrefetchedSource> source = mSources[i].promote();
-
- if (source == NULL) {
- continue;
- }
-
- source->onPrefetcherStopped();
- }
-
- mThreadExited = true;
- mCondition.signal();
-}
-
-int64_t Prefetcher::getCachedDurationUs(bool *noMoreData) {
- Mutex::Autolock autoLock(mLock);
-
- int64_t minCacheDurationUs = -1;
- ssize_t minIndex = -1;
- bool anySourceActive = false;
- for (size_t i = 0; i < mSources.size(); ++i) {
- int64_t cacheDurationUs;
- sp<PrefetchedSource> source = mSources[i].promote();
- if (source == NULL) {
- continue;
- }
-
- if (source->getCacheDurationUs(&cacheDurationUs)) {
- anySourceActive = true;
- }
-
- if (minIndex < 0 || cacheDurationUs < minCacheDurationUs) {
- minCacheDurationUs = cacheDurationUs;
- minIndex = i;
- }
- }
-
- if (noMoreData) {
- *noMoreData = !anySourceActive;
- }
-
- return minCacheDurationUs < 0 ? 0 : minCacheDurationUs;
-}
-
-status_t Prefetcher::prepare(
- bool (*continueFunc)(void *cookie), void *cookie) {
- // Fill the cache.
-
- int64_t duration;
- bool noMoreData;
- do {
- usleep(100000);
-
- if (continueFunc && !(*continueFunc)(cookie)) {
- return -EINTR;
- }
-
- duration = getCachedDurationUs(&noMoreData);
- } while (!noMoreData && duration < 2000000ll);
-
- return OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-PrefetchedSource::PrefetchedSource(
- size_t index,
- const sp<MediaSource> &source)
- : mSource(source),
- mIndex(index),
- mStarted(false),
- mReachedEOS(false),
- mSeekTimeUs(0),
- mCacheDurationUs(0),
- mCacheSizeBytes(0),
- mPrefetcherStopped(false),
- mCurrentlyPrefetching(false) {
-}
-
-PrefetchedSource::~PrefetchedSource() {
- if (mStarted) {
- stop();
- }
-}
-
-status_t PrefetchedSource::start(MetaData *params) {
- CHECK(!mStarted);
-
- Mutex::Autolock autoLock(mLock);
-
- status_t err = mSource->start(params);
-
- if (err != OK) {
- return err;
- }
-
- mStarted = true;
-
- return OK;
-}
-
-status_t PrefetchedSource::stop() {
- CHECK(mStarted);
-
- Mutex::Autolock autoLock(mLock);
-
- while (mCurrentlyPrefetching) {
- mCondition.wait(mLock);
- }
-
- clearCache_l();
-
- status_t err = mSource->stop();
-
- mStarted = false;
-
- return err;
-}
-
-status_t PrefetchedSource::read(
- MediaBuffer **out, const ReadOptions *options) {
- *out = NULL;
-
- Mutex::Autolock autoLock(mLock);
-
- CHECK(mStarted);
-
- int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
- CHECK(seekTimeUs >= 0);
-
- clearCache_l();
-
- mReachedEOS = false;
- mSeekTimeUs = seekTimeUs;
- }
-
- while (!mPrefetcherStopped && !mReachedEOS && mCachedBuffers.empty()) {
- mCondition.wait(mLock);
- }
-
- if (mCachedBuffers.empty()) {
- return mReachedEOS ? mFinalStatus : ERROR_END_OF_STREAM;
- }
-
- *out = *mCachedBuffers.begin();
- mCachedBuffers.erase(mCachedBuffers.begin());
- updateCacheDuration_l();
- mCacheSizeBytes -= (*out)->size();
-
- return OK;
-}
-
-sp<MetaData> PrefetchedSource::getFormat() {
- return mSource->getFormat();
-}
-
-bool PrefetchedSource::getCacheDurationUs(
- int64_t *durationUs, size_t *totalSize) {
- Mutex::Autolock autoLock(mLock);
-
- *durationUs = mCacheDurationUs;
- if (totalSize != NULL) {
- *totalSize = mCacheSizeBytes;
- }
-
- if (!mStarted || mReachedEOS) {
- return false;
- }
-
- return true;
-}
-
-void PrefetchedSource::cacheMore() {
- MediaSource::ReadOptions options;
-
- Mutex::Autolock autoLock(mLock);
-
- if (!mStarted) {
- return;
- }
-
- mCurrentlyPrefetching = true;
-
- if (mSeekTimeUs >= 0) {
- options.setSeekTo(mSeekTimeUs);
- mSeekTimeUs = -1;
- }
-
- // Ensure our object does not go away while we're not holding
- // the lock.
- sp<PrefetchedSource> me = this;
-
- mLock.unlock();
- MediaBuffer *buffer;
- status_t err = mSource->read(&buffer, &options);
- mLock.lock();
-
- if (err != OK) {
- mCurrentlyPrefetching = false;
- mReachedEOS = true;
- mFinalStatus = err;
- mCondition.signal();
-
- return;
- }
-
- CHECK(buffer != NULL);
-
- MediaBuffer *copy = new MediaBuffer(buffer->range_length());
- memcpy(copy->data(),
- (const uint8_t *)buffer->data() + buffer->range_offset(),
- buffer->range_length());
-
- sp<MetaData> from = buffer->meta_data();
- sp<MetaData> to = copy->meta_data();
-
- int64_t timeUs;
- if (from->findInt64(kKeyTime, &timeUs)) {
- to->setInt64(kKeyTime, timeUs);
- }
-
- buffer->release();
- buffer = NULL;
-
- mCachedBuffers.push_back(copy);
- updateCacheDuration_l();
- mCacheSizeBytes += copy->size();
-
- mCurrentlyPrefetching = false;
- mCondition.signal();
-}
-
-void PrefetchedSource::updateCacheDuration_l() {
- if (mCachedBuffers.size() < 2) {
- mCacheDurationUs = 0;
- } else {
- int64_t firstTimeUs, lastTimeUs;
- CHECK((*mCachedBuffers.begin())->meta_data()->findInt64(
- kKeyTime, &firstTimeUs));
- CHECK((*--mCachedBuffers.end())->meta_data()->findInt64(
- kKeyTime, &lastTimeUs));
-
- mCacheDurationUs = lastTimeUs - firstTimeUs;
- }
-}
-
-void PrefetchedSource::clearCache_l() {
- List<MediaBuffer *>::iterator it = mCachedBuffers.begin();
- while (it != mCachedBuffers.end()) {
- (*it)->release();
-
- it = mCachedBuffers.erase(it);
- }
-
- updateCacheDuration_l();
- mCacheSizeBytes = 0;
-}
-
-void PrefetchedSource::onPrefetcherStopped() {
- Mutex::Autolock autoLock(mLock);
- mPrefetcherStopped = true;
- mCondition.signal();
-}
-
-} // namespace android
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 89a522e..2e62f9f 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -314,8 +314,10 @@ uint32_t abs_difference(uint32_t time1, uint32_t time2) {
return time1 > time2 ? time1 - time2 : time2 - time1;
}
-status_t SampleTable::findClosestSample(
+status_t SampleTable::findSampleAtTime(
uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
+ *sample_index = 0;
+
Mutex::Autolock autoLock(mLock);
uint32_t cur_sample = 0;
@@ -330,16 +332,37 @@ status_t SampleTable::findClosestSample(
uint32_t time1 = time + j * delta;
uint32_t time2 = time1 + delta;
+ uint32_t sampleTime;
if (i+1 == mTimeToSampleCount
|| (abs_difference(req_time, time1)
< abs_difference(req_time, time2))) {
*sample_index = cur_sample + j;
+ sampleTime = time1;
} else {
*sample_index = cur_sample + j + 1;
+ sampleTime = time2;
}
- if (flags & kSyncSample_Flag) {
- return findClosestSyncSample_l(*sample_index, sample_index);
+ switch (flags) {
+ case kFlagBefore:
+ {
+ if (sampleTime > req_time && *sample_index > 0) {
+ --*sample_index;
+ }
+ break;
+ }
+
+ case kFlagAfter:
+ {
+ if (sampleTime < req_time
+ && *sample_index + 1 < mNumSampleSizes) {
+ ++*sample_index;
+ }
+ break;
+ }
+
+ default:
+ break;
}
return OK;
@@ -352,8 +375,10 @@ status_t SampleTable::findClosestSample(
return ERROR_OUT_OF_RANGE;
}
-status_t SampleTable::findClosestSyncSample_l(
- uint32_t start_sample_index, uint32_t *sample_index) {
+status_t SampleTable::findSyncSampleNear(
+ uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
+ Mutex::Autolock autoLock(mLock);
+
*sample_index = 0;
if (mSyncSampleOffset < 0) {
@@ -362,29 +387,124 @@ status_t SampleTable::findClosestSyncSample_l(
return OK;
}
- uint32_t x;
- uint32_t left = 0;
- uint32_t right = mNumSyncSamples;
- while (left < right) {
- uint32_t mid = (left + right) / 2;
+ if (mNumSyncSamples == 0) {
+ *sample_index = 0;
+ return OK;
+ }
+ uint32_t left = 0;
+ while (left < mNumSyncSamples) {
+ uint32_t x;
if (mDataSource->readAt(
- mSyncSampleOffset + 8 + mid * 4, &x, 4) != 4) {
+ mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
return ERROR_IO;
}
x = ntohl(x);
+ --x;
+
+ if (x >= start_sample_index) {
+ break;
+ }
+
+ ++left;
+ }
+
+ --left;
+ uint32_t x;
+ if (mDataSource->readAt(
+ mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
+ return ERROR_IO;
+ }
+
+ x = ntohl(x);
+ --x;
+
+ if (left + 1 < mNumSyncSamples) {
+ uint32_t y;
+ if (mDataSource->readAt(
+ mSyncSampleOffset + 8 + (left + 1) * 4, &y, 4) != 4) {
+ return ERROR_IO;
+ }
+
+ y = ntohl(y);
+ --y;
+
+ // our sample lies between sync samples x and y.
+
+ status_t err = mSampleIterator->seekTo(start_sample_index);
+ if (err != OK) {
+ return err;
+ }
+
+ uint32_t sample_time = mSampleIterator->getSampleTime();
+
+ err = mSampleIterator->seekTo(x);
+ if (err != OK) {
+ return err;
+ }
+ uint32_t x_time = mSampleIterator->getSampleTime();
+
+ err = mSampleIterator->seekTo(y);
+ if (err != OK) {
+ return err;
+ }
+
+ uint32_t y_time = mSampleIterator->getSampleTime();
+
+ if (abs_difference(x_time, sample_time)
+ > abs_difference(y_time, sample_time)) {
+ // Pick the sync sample closest (timewise) to the start-sample.
+ x = y;
+ ++left;
+ }
+ }
+
+ switch (flags) {
+ case kFlagBefore:
+ {
+ if (x > start_sample_index) {
+ CHECK(left > 0);
+
+ if (mDataSource->readAt(
+ mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
+ return ERROR_IO;
+ }
+
+ x = ntohl(x);
+ --x;
- if (x < (start_sample_index + 1)) {
- left = mid + 1;
- } else if (x > (start_sample_index + 1)) {
- right = mid;
- } else {
+ CHECK(x <= start_sample_index);
+ }
break;
}
+
+ case kFlagAfter:
+ {
+ if (x < start_sample_index) {
+ if (left + 1 >= mNumSyncSamples) {
+ return ERROR_OUT_OF_RANGE;
+ }
+
+ if (mDataSource->readAt(
+ mSyncSampleOffset + 8 + (left + 1) * 4, &x, 4) != 4) {
+ return ERROR_IO;
+ }
+
+ x = ntohl(x);
+ --x;
+
+ CHECK(x >= start_sample_index);
+ }
+
+ break;
+ }
+
+ default:
+ break;
}
- *sample_index = x - 1;
+ *sample_index = x;
return OK;
}
diff --git a/media/libstagefright/ShoutcastSource.cpp b/media/libstagefright/ShoutcastSource.cpp
index ec25430..23b7681 100644
--- a/media/libstagefright/ShoutcastSource.cpp
+++ b/media/libstagefright/ShoutcastSource.cpp
@@ -93,7 +93,8 @@ status_t ShoutcastSource::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
return ERROR_UNSUPPORTED;
}
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 03287dd..1629e9f 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -26,10 +26,6 @@
// Sonivox includes
#include <libsonivox/eas.h>
-// Ogg Vorbis includes
-#include <Tremolo/ivorbiscodec.h>
-#include <Tremolo/ivorbisfile.h>
-
namespace android {
StagefrightMediaScanner::StagefrightMediaScanner()
@@ -42,7 +38,8 @@ static bool FileHasAcceptableExtension(const char *extension) {
static const char *kValidExtensions[] = {
".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
- ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota"
+ ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
+ ".mkv", ".mka", ".webm", ".ts"
};
static const size_t kNumValidExtensions =
sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
@@ -102,48 +99,6 @@ static status_t HandleMIDI(
return OK;
}
-static status_t HandleOGG(
- const char *filename, MediaScannerClient *client) {
- int duration;
-
- FILE *file = fopen(filename,"r");
- if (!file)
- return UNKNOWN_ERROR;
-
- OggVorbis_File vf;
- if (ov_open(file, &vf, NULL, 0) < 0) {
- return UNKNOWN_ERROR;
- }
-
- char **ptr=ov_comment(&vf,-1)->user_comments;
- while(*ptr){
- char *val = strstr(*ptr, "=");
- if (val) {
- int keylen = val++ - *ptr;
- char key[keylen + 1];
- strncpy(key, *ptr, keylen);
- key[keylen] = 0;
- if (!client->addStringTag(key, val)) goto failure;
- }
- ++ptr;
- }
-
- // Duration
- duration = ov_time_total(&vf, -1);
- if (duration > 0) {
- char buffer[20];
- sprintf(buffer, "%d", duration);
- if (!client->addStringTag("duration", buffer)) goto failure;
- }
-
- ov_clear(&vf); // this also closes the FILE
- return OK;
-
-failure:
- ov_clear(&vf); // this also closes the FILE
- return UNKNOWN_ERROR;
-}
-
status_t StagefrightMediaScanner::processFile(
const char *path, const char *mimeType,
MediaScannerClient &client) {
@@ -175,10 +130,6 @@ status_t StagefrightMediaScanner::processFile(
return HandleMIDI(path, &client);
}
- if (!strcasecmp(extension, ".ogg")) {
- return HandleOGG(path, &client);
- }
-
if (mRetriever->setDataSource(path) == OK
&& mRetriever->setMode(
METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) {
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 258be74..9d89c20 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -378,6 +378,24 @@ void StagefrightMetadataRetriever::parseMetaData() {
// The duration value is a string representing the duration in ms.
sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
+
+ if (numTracks == 1) {
+ const char *fileMIME;
+ CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
+
+ if (!strcasecmp(fileMIME, "video/x-matroska")) {
+ sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
+ const char *trackMIME;
+ CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
+
+ if (!strncasecmp("audio/", trackMIME, 6)) {
+ // The matroska file only contains a single audio track,
+ // rewrite its mime type.
+ mMetaData.add(
+ METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
+ }
+ }
+ }
}
diff --git a/media/libstagefright/ThrottledSource.cpp b/media/libstagefright/ThrottledSource.cpp
new file mode 100644
index 0000000..4711f7c
--- /dev/null
+++ b/media/libstagefright/ThrottledSource.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/ThrottledSource.h"
+
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+static int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+ThrottledSource::ThrottledSource(
+ const sp<DataSource> &source,
+ int32_t bandwidthLimitBytesPerSecond)
+ : mSource(source),
+ mBandwidthLimitBytesPerSecond(bandwidthLimitBytesPerSecond),
+ mStartTimeUs(-1),
+ mTotalTransferred(0) {
+ CHECK(mBandwidthLimitBytesPerSecond > 0);
+}
+
+status_t ThrottledSource::initCheck() const {
+ return mSource->initCheck();
+}
+
+ssize_t ThrottledSource::readAt(off_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t n = mSource->readAt(offset, data, size);
+
+ if (n <= 0) {
+ return n;
+ }
+
+ mTotalTransferred += n;
+
+ int64_t nowUs = getNowUs();
+
+ if (mStartTimeUs < 0) {
+ mStartTimeUs = nowUs;
+ }
+
+ // How long would it have taken to transfer everything we ever
+ // transferred given the limited bandwidth.
+ int64_t durationUs =
+ mTotalTransferred * 1000000ll / mBandwidthLimitBytesPerSecond;
+
+ int64_t whenUs = mStartTimeUs + durationUs;
+
+ if (whenUs > nowUs) {
+ usleep(whenUs - nowUs);
+ }
+
+ return n;
+}
+
+status_t ThrottledSource::getSize(off_t *size) {
+ return mSource->getSize(size);
+}
+
+uint32_t ThrottledSource::flags() {
+ return mSource->flags();
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 7365dfa..7c2b07e 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -282,7 +282,8 @@ status_t WAVSource::read(
*out = NULL;
int64_t seekTimeUs;
- if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
int64_t pos = (seekTimeUs * mSampleRate) / 1000000 * mNumChannels * 2;
if (pos > mSize) {
pos = mSize;
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index 2bc4448..c5b51c0 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -15,6 +15,7 @@
*/
#include "AACDecoder.h"
+#define LOG_TAG "AACDecoder"
#include "../../include/ESDS.h"
@@ -36,26 +37,33 @@ AACDecoder::AACDecoder(const sp<MediaSource> &source)
mAnchorTimeUs(0),
mNumSamplesOutput(0),
mInputBuffer(NULL) {
-}
-AACDecoder::~AACDecoder() {
- if (mStarted) {
- stop();
- }
+ sp<MetaData> srcFormat = mSource->getFormat();
- delete mConfig;
- mConfig = NULL;
-}
+ int32_t sampleRate;
+ CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-status_t AACDecoder::start(MetaData *params) {
- CHECK(!mStarted);
+ mMeta = new MetaData;
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(new MediaBuffer(2048 * 2));
+ // We'll always output stereo, regardless of how many channels are
+ // present in the input due to decoder limitations.
+ mMeta->setInt32(kKeyChannelCount, 2);
+ mMeta->setInt32(kKeySampleRate, sampleRate);
+ int64_t durationUs;
+ if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+ mMeta->setInt64(kKeyDuration, durationUs);
+ }
+ mMeta->setCString(kKeyDecoderComponent, "AACDecoder");
+
+ mInitCheck = initCheck();
+}
+
+status_t AACDecoder::initCheck() {
+ memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
- mConfig->aacPlusUpsamplingFactor = 0;
- mConfig->aacPlusEnabled = false;
+ mConfig->aacPlusEnabled = 1;
// The software decoder doesn't properly support mono output on
// AACplus files. Always output stereo.
@@ -64,8 +72,11 @@ status_t AACDecoder::start(MetaData *params) {
UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
mDecoderBuf = malloc(memRequirements);
- CHECK_EQ(PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf),
- MP4AUDEC_SUCCESS);
+ status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
+ if (err != MP4AUDEC_SUCCESS) {
+ LOGE("Failed to initialize MP4 audio decoder");
+ return UNKNOWN_ERROR;
+ }
uint32_t type;
const void *data;
@@ -83,18 +94,29 @@ status_t AACDecoder::start(MetaData *params) {
mConfig->pInputBuffer = (UChar *)codec_specific_data;
mConfig->inputBufferCurrentLength = codec_specific_data_size;
mConfig->inputBufferMaxLength = 0;
- mConfig->inputBufferUsedLength = 0;
- mConfig->remainderBits = 0;
-
- mConfig->pOutputBuffer = NULL;
- mConfig->pOutputBuffer_plus = NULL;
- mConfig->repositionFlag = false;
if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf)
!= MP4AUDEC_SUCCESS) {
return ERROR_UNSUPPORTED;
}
}
+ return OK;
+}
+
+AACDecoder::~AACDecoder() {
+ if (mStarted) {
+ stop();
+ }
+
+ delete mConfig;
+ mConfig = NULL;
+}
+
+status_t AACDecoder::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ mBufferGroup = new MediaBufferGroup;
+ mBufferGroup->add_buffer(new MediaBuffer(4096 * 2));
mSource->start();
@@ -127,28 +149,7 @@ status_t AACDecoder::stop() {
}
sp<MetaData> AACDecoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t sampleRate;
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-
- // We'll always output stereo, regardless of how many channels are
- // present in the input due to decoder limitations.
- meta->setInt32(kKeyChannelCount, 2);
-
- meta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "AACDecoder");
-
- return meta;
+ return mMeta;
}
status_t AACDecoder::read(
@@ -158,7 +159,8 @@ status_t AACDecoder::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
CHECK(seekTimeUs >= 0);
mNumSamplesOutput = 0;
@@ -200,13 +202,32 @@ status_t AACDecoder::read(
mConfig->remainderBits = 0;
mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data());
- mConfig->pOutputBuffer_plus = NULL;
+ mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
mConfig->repositionFlag = false;
Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
+ // Check on the sampling rate to see whether it is changed.
+ int32_t sampleRate;
+ CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
+ if (mConfig->samplingRate != sampleRate) {
+ mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
+ LOGW("Sample rate was %d, but now is %d",
+ sampleRate, mConfig->samplingRate);
+ buffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return INFO_FORMAT_CHANGED;
+ }
+
size_t numOutBytes =
mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
+ if (mConfig->aacPlusUpsamplingFactor == 2) {
+ if (mConfig->desiredChannels == 1) {
+ memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
+ }
+ numOutBytes *= 2;
+ }
if (decoderErr != MP4AUDEC_SUCCESS) {
LOGW("AAC decoder returned error %d, substituting silence", decoderErr);
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
new file mode 100644
index 0000000..052c354
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AACEncoder"
+#include <utils/Log.h>
+
+#include "AACEncoder.h"
+#include "voAAC.h"
+#include "cmnMemory.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+AACEncoder::AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
+ : mSource(source),
+ mMeta(meta),
+ mStarted(false),
+ mBufferGroup(NULL),
+ mInputBuffer(NULL),
+ mEncoderHandle(NULL),
+ mApiHandle(NULL),
+ mMemOperator(NULL) {
+}
+
+status_t AACEncoder::initCheck() {
+ CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
+ CHECK(mMeta->findInt32(kKeySampleRate, &mSampleRate));
+ CHECK(mMeta->findInt32(kKeyChannelCount, &mChannels));
+ CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
+
+ mApiHandle = new VO_AUDIO_CODECAPI;
+ CHECK(mApiHandle);
+
+ if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) {
+ LOGE("Failed to get api handle");
+ return UNKNOWN_ERROR;
+ }
+
+ mMemOperator = new VO_MEM_OPERATOR;
+ CHECK(mMemOperator != NULL);
+ mMemOperator->Alloc = cmnMemAlloc;
+ mMemOperator->Copy = cmnMemCopy;
+ mMemOperator->Free = cmnMemFree;
+ mMemOperator->Set = cmnMemSet;
+ mMemOperator->Check = cmnMemCheck;
+
+ VO_CODEC_INIT_USERDATA userData;
+ memset(&userData, 0, sizeof(userData));
+ userData.memflag = VO_IMF_USERMEMOPERATOR;
+ userData.memData = (VO_PTR) mMemOperator;
+ if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) {
+ LOGE("Failed to init AAC encoder");
+ return UNKNOWN_ERROR;
+ }
+ if (OK != setAudioSpecificConfigData()) {
+ LOGE("Failed to configure AAC encoder");
+ return UNKNOWN_ERROR;
+ }
+
+ // Configure AAC encoder$
+ AACENC_PARAM params;
+ memset(&params, 0, sizeof(params));
+ params.sampleRate = mSampleRate;
+ params.bitRate = mBitRate;
+ params.nChannels = mChannels;
+ params.adtsUsed = 0; // For MP4 file, don't use adts format$
+ if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AAC_ENCPARAM, &params)) {
+ LOGE("Failed to set AAC encoder parameters");
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) {
+ static const int32_t kSampleRateTable[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000
+ };
+ const int32_t tableSize = sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
+ for (int32_t i = 0; i < tableSize; ++i) {
+ if (sampleRate == kSampleRateTable[i]) {
+ index = i;
+ return OK;
+ }
+ }
+
+ LOGE("Sampling rate %d bps is not supported", sampleRate);
+ return UNKNOWN_ERROR;
+}
+
+status_t AACEncoder::setAudioSpecificConfigData() {
+ LOGV("setAudioSpecificConfigData: %d hz, %d bps, and %d channels",
+ mSampleRate, mBitRate, mChannels);
+
+ int32_t index;
+ CHECK_EQ(OK, getSampleRateTableIndex(mSampleRate, index));
+ if (mChannels > 2 || mChannels <= 0) {
+ LOGE("Unsupported number of channels(%d)", mChannels);
+ return UNKNOWN_ERROR;
+ }
+
+ // OMX_AUDIO_AACObjectLC
+ mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1));
+ mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mChannels << 3);
+ return OK;
+}
+
+AACEncoder::~AACEncoder() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t AACEncoder::start(MetaData *params) {
+ if (mStarted) {
+ LOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ mBufferGroup = new MediaBufferGroup;
+ mBufferGroup->add_buffer(new MediaBuffer(2048));
+
+ CHECK_EQ(OK, initCheck());
+
+ mNumInputSamples = 0;
+ mAnchorTimeUs = 0;
+ mFrameCount = 0;
+ mSource->start(params);
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AACEncoder::stop() {
+ if (!mStarted) {
+ LOGW("Call stop() when encoder has not started");
+ return OK;
+ }
+
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ delete mBufferGroup;
+ mBufferGroup = NULL;
+
+ mSource->stop();
+
+ if (mEncoderHandle) {
+ CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+ mEncoderHandle = NULL;
+ }
+ delete mApiHandle;
+ mApiHandle = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> AACEncoder::getFormat() {
+ sp<MetaData> srcFormat = mSource->getFormat();
+
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+ int64_t durationUs;
+ if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+ mMeta->setInt64(kKeyDuration, durationUs);
+ }
+
+ mMeta->setCString(kKeyDecoderComponent, "AACEncoder");
+
+ return mMeta;
+}
+
+status_t AACEncoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ status_t err;
+
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
+
+ MediaBuffer *buffer;
+ CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
+ uint8_t *outPtr = (uint8_t *)buffer->data();
+
+ if (mFrameCount == 0) {
+ memcpy(outPtr, mAudioSpecificConfigData, 2);
+ buffer->set_range(0, 2);
+ buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
+ *out = buffer;
+ ++mFrameCount;
+ return OK;
+ } else if (mFrameCount == 1) {
+ buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
+ }
+
+ while (mNumInputSamples < kNumSamplesPerFrame) {
+ if (mInputBuffer == NULL) {
+ if (mSource->read(&mInputBuffer, options) != OK) {
+ if (mNumInputSamples == 0) {
+ buffer->release();
+ return ERROR_END_OF_STREAM;
+ }
+ memset(&mInputFrame[mNumInputSamples],
+ 0,
+ sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples));
+ mNumInputSamples = 0;
+ break;
+ }
+
+ size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+ CHECK_EQ(align, 0);
+
+ int64_t timeUs;
+ if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ mAnchorTimeUs = timeUs;
+ }
+ }
+ size_t copy =
+ (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+
+ if (copy > mInputBuffer->range_length()) {
+ copy = mInputBuffer->range_length();
+ }
+
+ memcpy(&mInputFrame[mNumInputSamples],
+ (const uint8_t *) mInputBuffer->data()
+ + mInputBuffer->range_offset(),
+ copy);
+
+ mInputBuffer->set_range(
+ mInputBuffer->range_offset() + copy,
+ mInputBuffer->range_length() - copy);
+
+ if (mInputBuffer->range_length() == 0) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+ mNumInputSamples += copy / sizeof(int16_t);
+ if (mNumInputSamples >= kNumSamplesPerFrame) {
+ mNumInputSamples %= kNumSamplesPerFrame;
+ break;
+ }
+ }
+
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char*) mInputFrame;
+ inputData.Length = kNumSamplesPerFrame * sizeof(int16_t);
+ CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
+
+ VO_CODECBUFFER outputData;
+ memset(&outputData, 0, sizeof(outputData));
+ VO_AUDIO_OUTPUTINFO outputInfo;
+ memset(&outputInfo, 0, sizeof(outputInfo));
+
+ VO_U32 ret = VO_ERR_NONE;
+ outputData.Buffer = outPtr;
+ outputData.Length = buffer->size();
+ ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
+ CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+ CHECK(outputData.Length != 0);
+ buffer->set_range(0, outputData.Length);
+
+ int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
+ ++mFrameCount;
+ buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+
+ *out = buffer;
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/aacenc/Android.mk b/media/libstagefright/codecs/aacenc/Android.mk
new file mode 100644
index 0000000..cda4f9d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Android.mk
@@ -0,0 +1,87 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := basic_op/basicop2.c basic_op/oper_32b.c
+
+LOCAL_SRC_FILES += \
+ AACEncoder.cpp \
+ src/aac_rom.c \
+ src/aacenc.c \
+ src/aacenc_core.c \
+ src/adj_thr.c \
+ src/band_nrg.c \
+ src/bit_cnt.c \
+ src/bitbuffer.c \
+ src/bitenc.c \
+ src/block_switch.c \
+ src/channel_map.c \
+ src/dyn_bits.c \
+ src/grp_data.c \
+ src/interface.c \
+ src/line_pe.c \
+ src/ms_stereo.c \
+ src/pre_echo_control.c \
+ src/psy_configuration.c \
+ src/psy_main.c \
+ src/qc_main.c \
+ src/quantize.c \
+ src/sf_estim.c \
+ src/spreading.c \
+ src/stat_bits.c \
+ src/tns.c \
+ src/transform.c \
+ src/memalign.c
+
+ifeq ($(VOTT), v5)
+LOCAL_SRC_FILES += \
+ src/asm/ARMV5E/AutoCorrelation_v5.s \
+ src/asm/ARMV5E/band_nrg_v5.s \
+ src/asm/ARMV5E/CalcWindowEnergy_v5.s \
+ src/asm/ARMV5E/PrePostMDCT_v5.s \
+ src/asm/ARMV5E/R4R8First_v5.s \
+ src/asm/ARMV5E/Radix4FFT_v5.s
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_SRC_FILES += \
+ src/asm/ARMV5E/AutoCorrelation_v5.s \
+ src/asm/ARMV5E/band_nrg_v5.s \
+ src/asm/ARMV5E/CalcWindowEnergy_v5.s \
+ src/asm/ARMV7/PrePostMDCT_v7.s \
+ src/asm/ARMV7/R4R8First_v7.s \
+ src/asm/ARMV7/Radix4FFT_v7.s
+endif
+
+LOCAL_MODULE := libstagefright_aacenc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_SHARED_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/base/media/libstagefright/codecs/common/include \
+ frameworks/base/include \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/inc \
+ $(LOCAL_PATH)/basic_op
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+ifeq ($(VOTT), v5)
+LOCAL_CFLAGS += -DARMV5E -DARM_INASM -DARMV5_INASM
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_CFLAGS += -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
new file mode 100644
index 0000000..64d012d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/AAC_E_SAMPLES.c
@@ -0,0 +1,283 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: AAC_E_SAMPLES.h
+
+ Content: sample code for AAC encoder
+
+*******************************************************************************/
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "voAAC.h"
+#include "cmnMemory.h"
+
+#define VO_AAC_E_OUTPUT 1
+#define READ_SIZE (1024*8)
+unsigned char outBuf[1024*8];
+unsigned char inBuf[READ_SIZE];
+
+const char* HelpString =
+"VisualOn AAC encoder Usage:\n"
+"voAACEncTest -if <inputfile.pcm> -of <outputfile.aac> -sr <samplerate> -ch <channel> -br <bitrate> -adts <adts> \n"
+"-if input file name \n"
+"-of output file name \n"
+"-sr input pcm samplerate, default 44100 \n"
+"-ch input pcm channel, default 2 channel \n"
+"-br encoded aac bitrate, default 64000 * (samplerate/100)*channel/441(480)\n"
+"-adts add or no adts header, default add adts header\n"
+"For example: \n"
+"./voAACEncTest -if raw.pcm -of raw.aac -sr 44100 -ch 2 -br 128000\n";
+
+static int parsecmdline(int argc, char **argv,char **input_filename, char **output_filename, AACENC_PARAM *param)
+{
+ // notice that:
+ // bitRate/nChannels > 8000
+ // bitRate/nChannels < 160000
+ // bitRate/nChannels < sampleRate*6
+ param->adtsUsed = 1;
+ param->bitRate = 0;
+ param->nChannels = 2;
+ param->sampleRate = 44100;
+
+ if(argc < 5 || argc > 13)
+ {
+ return -1;
+ }
+
+ argc--;
+ argv++;
+ while (argc > 0)
+ {
+ if (!strcmp(*argv, "-if"))
+ {
+ argv++;
+ argc--;
+ *input_filename = *argv;
+ }
+ else if (!strcmp(*argv, "-of"))
+ {
+ argv++;
+ argc--;
+ *output_filename = *argv;
+ }
+ else if (!strcmp(*argv, "-sr"))
+ {
+ argv++;
+ argc--;
+ param->sampleRate = atoi(*argv);
+ }
+ else if (!strcmp(*argv, "-ch"))
+ {
+ argv++;
+ argc--;
+ param->nChannels = atoi(*argv);
+ }
+ else if (!strcmp(*argv, "-br"))
+ {
+ argv++;
+ argc--;
+ param->bitRate = atoi(*argv);
+ }
+ else if(!strcmp(*argv, "-adts"))
+ {
+ argv++;
+ argc--;
+ param->adtsUsed = atoi(*argv);
+ }
+ else
+ {
+ return -1;
+ }
+
+ argv++;
+ argc--;
+ }
+
+ if(param->bitRate == 0)
+ {
+ int scale = 441;
+ if(param->sampleRate%8000 == 0)
+ scale = 480;
+ param->bitRate = 640*param->nChannels*param->sampleRate/scale;
+ }
+
+ return 0;
+}
+
+int ReadFile2Buf(FILE* infile,unsigned char* dest,int readSize)
+{
+ int readBytes = 0;
+ readBytes = fread(dest, 1, readSize, infile);
+ return readBytes;
+}
+
+typedef int (VO_API * VOGETAUDIODECAPI) (VO_AUDIO_CODECAPI * pDecHandle);
+
+int main(int argc, char **argv)
+{
+ FILE *infile, *outfile;
+ int t1, t2;
+ VO_AUDIO_CODECAPI AudioAPI;
+ VO_MEM_OPERATOR moper;
+ VO_CODEC_INIT_USERDATA useData;
+ VO_HANDLE hCodec;
+ VO_CODECBUFFER inData;
+ VO_CODECBUFFER outData;
+ VO_AUDIO_OUTPUTINFO outInfo;
+ int firstWrite = 1;
+ int eofFile = 0;
+ int *info=(int*)inBuf;
+ int bytesLeft, nRead;
+ int EncoderdFrame = 0;
+ int total = 0;
+ int isOutput = 1;
+ int returnCode;
+ AACENC_PARAM aacpara;
+ void *handle;
+ void *pfunc;
+ VOGETAUDIODECAPI pGetAPI;
+ const char *infileName = NULL;
+ const char *outfileName = NULL;
+
+ returnCode = parsecmdline(argc,argv, &infileName, &outfileName, &aacpara);
+ if(returnCode)
+ {
+ printf("%s", HelpString);
+ return 0;
+ }
+
+ /* open input file */
+ infile = fopen(infileName, "rb");
+ if (!infile) {
+ printf("Open input file fail...");
+ return -1;
+ }
+
+ /* open output file */
+ if(isOutput)
+ {
+ outfile = fopen(outfileName, "wb");
+ if (!outfile) {
+ printf("Open output file fail...");
+ return -1;
+ }
+ }
+ // set memory operators;
+ moper.Alloc = cmnMemAlloc;
+ moper.Copy = cmnMemCopy;
+ moper.Free = cmnMemFree;
+ moper.Set = cmnMemSet;
+ moper.Check = cmnMemCheck;
+ useData.memflag = VO_IMF_USERMEMOPERATOR;
+ useData.memData = (VO_PTR)(&moper);
+ // open encoder dll;
+ handle = dlopen("/data/local/tmp/libvoAACEncv7.so", RTLD_NOW);
+ if(handle == 0)
+ {
+ printf("open dll error......");
+ return -1;
+ }
+ // Get API;
+ pfunc = dlsym(handle, "voGetAACEncAPI");
+ if(pfunc == 0)
+ {
+ printf("open function error......");
+ return -1;
+ }
+ pGetAPI = (VOGETAUDIODECAPI)pfunc;
+ returnCode = pGetAPI(&AudioAPI);
+ if(returnCode)
+ return -1;
+
+
+//####################################### Init Encoding Section #########################################
+ returnCode = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAAC, &useData);
+ if(returnCode < 0)
+ {
+ printf("#### VOI_Error2:fail to initialize the Encoderr###\n");
+ return -1;
+ }
+
+ returnCode = AudioAPI.SetParam(hCodec, VO_PID_AAC_ENCPARAM, &aacpara);
+
+ inData.Buffer = inBuf;
+ bytesLeft = ReadFile2Buf(infile,inData.Buffer,READ_SIZE);
+
+//####################################### Encoding Section #########################################
+
+ do {
+
+ inData.Length = bytesLeft;
+ outData.Buffer = outBuf;
+ outData.Length = 1024*8;
+
+ t1 = clock();
+
+ returnCode = AudioAPI.SetInputData(hCodec,&inData);
+
+ do {
+ outData.Buffer = outBuf;
+ outData.Length = 1024*8;
+
+ returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outInfo);
+
+ if(returnCode == 0)
+ EncoderdFrame++;
+ if(returnCode == VO_ERR_LICENSE_ERROR)
+ break;
+
+#if VO_AAC_E_OUTPUT
+ if (isOutput && returnCode == 0)
+ {
+ fwrite(outData.Buffer, 1, outData.Length, outfile);
+ }
+#endif
+ } while(returnCode != (VO_ERR_INPUT_BUFFER_SMALL));
+
+ if(returnCode == VO_ERR_LICENSE_ERROR)
+ break;
+
+ t2 = clock();
+ total += t2 - t1;
+
+ if (!eofFile) {
+ nRead = ReadFile2Buf(infile, inBuf,READ_SIZE);
+ bytesLeft = nRead;
+ inData.Buffer = inBuf;
+ if (feof(infile))
+ eofFile = 1;
+ }
+
+ } while (!eofFile && returnCode);
+
+
+//################################################ End Encoding Section #######################################################
+ returnCode = AudioAPI.Uninit(hCodec);
+
+ fclose(infile);
+ if (outfile)
+ {
+ fclose(outfile);
+ }
+ dlclose(handle);
+ return 0;
+}
+
+
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/Android.mk b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
new file mode 100644
index 0000000..52c9c07
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := AAC_E_SAMPLES.c
+
+LOCAL_SRC_FILES += \
+ ../../../Common/cmnMemory.c
+
+LOCAL_MODULE := TestvoAACEnc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_SHARED_LIBRARIES := libvoAACEnc
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/../../../Common \
+ $(LOCAL_PATH)/../../../Include \
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+include $(BUILD_EXECUTABLE)
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
new file mode 100644
index 0000000..22c5dc1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/eclair/Makefile
@@ -0,0 +1,55 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** Licensed under the Apache License, Version 2.0 (the "License");
+#** you may not use this file except in compliance with the License.
+#** You may obtain a copy of the License at
+#**
+#** http://www.apache.org/licenses/LICENSE-2.0
+#**
+#** Unless required by applicable law or agreed to in writing, software
+#** distributed under the License is distributed on an "AS IS" BASIS,
+#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#** See the License for the specific language governing permissions and
+#** limitations under the License.
+#*/
+
+# target6
+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
+VOTT:= v7
+
+
+# module type
+# please specify the type of your module: lib or exe
+VOMT:= exe
+
+
+# module macros
+# please append the additional macro definitions here for your module if necessary.
+# e.g. -DVISUALON, macro VISUALON defined for your module
+VOMM:= #ARMV5E
+
+
+
+# please specify the name of your module
+VOTARGET:= voAACEncTestv7
+
+
+# please modify here to be sure to see the g1.mk
+include ../../../../Tools/eclair.mk
+
+# dependent libraries.
+VODEPLIBS:=-ldl
+
+# module source
+# please modify here to be sure to see the ms.mk which specifies all source info of your module
+include ../ms.mk
+
+
+# please specify where is the voRelease on your PC, relative path is suggested
+VORELDIR:=../../../../../Release/
+
+
+# please modify here to be sure to see the doit.mk
+include ../../../../Tools/doit.mk
+
diff --git a/media/libstagefright/codecs/aacenc/SampleCode/ms.mk b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
new file mode 100644
index 0000000..771a569
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/SampleCode/ms.mk
@@ -0,0 +1,23 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** Licensed under the Apache License, Version 2.0 (the "License");
+#** you may not use this file except in compliance with the License.
+#** You may obtain a copy of the License at
+#**
+#** http://www.apache.org/licenses/LICENSE-2.0
+#**
+#** Unless required by applicable law or agreed to in writing, software
+#** distributed under the License is distributed on an "AS IS" BASIS,
+#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#** See the License for the specific language governing permissions and
+#** limitations under the License.
+#*/
+
+# please list all objects needed by your target here
+OBJS:=AAC_E_SAMPLES.o cmnMemory.o
+
+# please list all directories that all source files relative with your module(.h .c .cpp) locate
+VOSRCDIR:=../ ../../../../include ../../../../Common
+
+
diff --git a/media/libstagefright/codecs/aacenc/Tools/doit.mk b/media/libstagefright/codecs/aacenc/Tools/doit.mk
new file mode 100644
index 0000000..dea0b0a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Tools/doit.mk
@@ -0,0 +1,133 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+
+VERBOSE:=@
+
+
+VOMT ?= lib
+
+ifeq ($(VOMT), lib)
+LIB_STATIC=$(VOTARGET).a
+LIB_DYNAMIC=$(VOTARGET).so
+endif
+
+ifeq ($(VOMT), exe)
+TARGET=$(VOTARGET)
+endif
+
+CFLAGS=$(VOCFLAGS) $(addprefix -I, $(VOSRCDIR))
+CPPFLAGS=$(VOCPPFLAGS) $(addprefix -I, $(VOSRCDIR))
+ifneq ($(VOTT), pc)
+ASFLAGS=$(VOASFLAGS) $(addprefix -I, $(VOSRCDIR))
+endif
+
+LDFLAGS:=$(VOLDFLAGS)
+VOTEDEPS+=$(VODEPLIBS)
+VOTLDEPS+=$(VODEPLIBS)
+VOSTCLIBS ?=
+
+vpath %.c $(VOSRCDIR)
+vpath %.cpp $(VOSRCDIR)
+ifneq ($(VOTT), pc)
+vpath %.s $(VOSRCDIR)
+endif
+
+ifeq ($(VOTT), pc)
+BLTDIRS=$(VORELDIR)/Linux/static
+BLTDIRD=$(VORELDIR)/Linux/shared
+else
+BLTDIRS=$(VORELDIR)/Google/$(VONJ)/lib/$(VOTT)
+BLTDIRD=$(VORELDIR)/Google/$(VONJ)/so/$(VOTT)
+endif
+
+
+.PRECIOUS: $(OBJDIR)/%.o
+
+ifeq ($(VOMT), lib)
+all: mkdirs $(LIB_STATIC) $(LIB_DYNAMIC)
+mkdirs: $(OBJDIR) $(BLTDIRS) $(BLTDIRD)
+else
+all: mkdirs $(TARGET)
+mkdirs: $(OBJDIR)
+endif
+
+$(OBJDIR):
+ @if test ! -d $@; then \
+ mkdir -p $@; \
+ fi;
+
+ifeq ($(VOMT), lib)
+$(BLTDIRS):
+ @if test ! -d $@; then \
+ mkdir -p $@; \
+ fi;
+$(BLTDIRD):
+ @if test ! -d $@; then \
+ mkdir -p $@; \
+ fi;
+endif
+
+
+ifeq ($(VOMT), lib)
+$(LIB_STATIC):$(OBJS)
+ $(AR) cr $@ $(OBJDIR)/*.o $(VOSTCLIBS)
+ $(RANLIB) $@
+ifneq ($(VODBG), yes)
+ #$(STRIP) $@
+endif
+
+$(LIB_DYNAMIC):$(OBJS)
+ $(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTLDEPS)
+ifneq ($(VODBG), yes)
+ $(STRIP) $@
+endif
+
+else
+
+$(TARGET):$(OBJS)
+ $(GG) $(LDFLAGS) -o $@ $(OBJDIR)/*.o -Wl,--whole-archive $(VOSTCLIBS) -Wl,--no-whole-archive $(VOTEDEPS)
+ifneq ($(VODBG), yes)
+ $(STRIP) $@
+endif
+
+endif
+
+
+.SUFFIXES: .c .cpp .s .o
+.c.o:
+ $(VERBOSE) $(CC) $(CFLAGS) -o $(OBJDIR)/$@ -c $<
+#%.c:$(OBJDIR)/%.o
+# $(VERBOSE) $(CC) $(CFLAGS) -o $@ -c $<
+.cpp.o:
+ $(VERBOSE) $(GG) $(CPPFLAGS) -o $(OBJDIR)/$@ -c $<
+ifneq ($(VOTT), pc)
+.s.o:
+ $(VERBOSE) $(AS) $(ASFLAGS) -o $(OBJDIR)/$@ $<
+endif
+
+
+.PHONY: clean devel
+clean:
+ifeq ($(VOMT), lib)
+ -rm -fr $(OBJDIR) .*.sw* $(VOTARGET).*
+else
+ -rm -fr $(OBJDIR) .*.sw* $(VOTARGET)
+endif
+
+devel:
+ cp -a $(LIB_STATIC) $(BLTDIRS)
+ cp -a $(LIB_DYNAMIC) $(BLTDIRD)
+
diff --git a/media/libstagefright/codecs/aacenc/Tools/eclair.mk b/media/libstagefright/codecs/aacenc/Tools/eclair.mk
new file mode 100644
index 0000000..1688361
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/Tools/eclair.mk
@@ -0,0 +1,172 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+
+# special macro definitions for building
+VOPREDEF=-DLINUX -D_LINUX
+
+VOPRJ ?=
+VONJ ?= eclair
+VOTT ?= v6
+# control the version to release out
+# available: eva(evaluation), rel(release)
+VOVER=
+ifeq ($(VOVER), eva)
+VOPREDEF+=-D__VOVER_EVA__
+endif
+
+# for debug or not: yes for debug, any other for release
+VODBG?=ye
+
+# for detecting memory leak
+VODML=
+ifeq ($(VODML), yes)
+VOPREDEF+=-DDMEMLEAK
+endif
+
+VOPREDEF+=-D__VOTT_ARM__ -D__VONJ_ECLAIR__
+TCROOTPATH:=/opt/eclair
+GCCVER:=4.4.0
+TCPATH:=$(TCROOTPATH)/prebuilt/linux-x86/toolchain/arm-eabi-$(GCCVER)
+CCTPRE:=$(TCPATH)/bin/arm-eabi-
+AS:=$(CCTPRE)as
+AR:=$(CCTPRE)ar
+NM:=$(CCTPRE)nm
+CC:=$(CCTPRE)gcc
+GG:=$(CCTPRE)g++
+LD:=$(CCTPRE)ld
+SIZE:=$(CCTPRE)size
+STRIP:=$(CCTPRE)strip
+RANLIB:=$(CCTPRE)ranlib
+OBJCOPY:=$(CCTPRE)objcopy
+OBJDUMP:=$(CCTPRE)objdump
+READELF:=$(CCTPRE)readelf
+STRINGS:=$(CCTPRE)strings
+
+# target product dependcy
+# available: dream, generic
+VOTP:=sapphire-open
+CCTLIB:=$(TCROOTPATH)/out/target/product/$(VOTP)/obj/lib
+CCTINC:=-I$(TCROOTPATH)/system/core/include \
+ -I$(TCROOTPATH)/hardware/libhardware/include \
+ -I$(TCROOTPATH)/hardware/ril/include \
+ -I$(TCROOTPATH)/hardware/libhardware_legacy/include \
+ -I$(TCROOTPATH)/dalvik/libnativehelper/include \
+ -I$(TCROOTPATH)/dalvik/libnativehelper/include/nativehelper \
+ -I$(TCROOTPATH)/frameworks/base/include \
+ -I$(TCROOTPATH)/frameworks/base/core/jni \
+ -I$(TCROOTPATH)/frameworks/base/libs/audioflinger \
+ -I$(TCROOTPATH)/external/skia/include \
+ -I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/include \
+ -I$(TCROOTPATH)/bionic/libc/arch-arm/include \
+ -I$(TCROOTPATH)/bionic/libc/include \
+ -I$(TCROOTPATH)/bionic/libstdc++/include \
+ -I$(TCROOTPATH)/bionic/libc/kernel/common \
+ -I$(TCROOTPATH)/bionic/libc/kernel/arch-arm \
+ -I$(TCROOTPATH)/bionic/libm/include \
+ -I$(TCROOTPATH)/bionic/libm/include/arm \
+ -I$(TCROOTPATH)/bionic/libthread_db/include \
+ -I$(TCROOTPATH)/bionic/libm/arm \
+ -I$(TCROOTPATH)/bionic/libm \
+ -I$(TCROOTPATH)/frameworks/base/include/android_runtime
+ #-I$(TCROOTPATH)/out/target/product/$(VOTP)/obj/SHARED_LIBRARIES/libm_intermediates
+
+CCTCFLAGS:=-msoft-float -mthumb-interwork -fno-exceptions -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fmessage-length=0 -finline-functions -finline-limit=600 -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers -fstrict-aliasing -funswitch-loops
+#-fwide-exec-charset=charset=UTF-32
+
+# for target exe
+TELDFLAGS:=-nostdlib -Bdynamic -Wl,-T,$(TCROOTPATH)/build/core/armelf.x -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-rpath-link=$(CCTLIB) -L$(CCTLIB)
+
+VOTEDEPS:=$(CCTLIB)/crtbegin_dynamic.o $(CCTLIB)/crtend_android.o $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a -lc -lm
+
+# for target lib
+TLLDFLAGS:=-nostdlib -Wl,-T,$(TCROOTPATH)/build/core/armelf.xsc -Wl,--gc-sections -Wl,-shared,-Bsymbolic -L$(CCTLIB) -Wl,--no-whole-archive -Wl,--no-undefined $(TCPATH)/lib/gcc/arm-eabi/$(GCCVER)/interwork/libgcc.a
+
+VOTLDEPS:=-lm -lc
+
+
+ifeq ($(VOTT), v4)
+VOCFLAGS:=-mtune=arm9tdmi -march=armv4t
+VOASFLAGS:=-march=armv4t -mfpu=softfpa
+endif
+
+ifeq ($(VOTT), v5)
+VOCFLAGS:=-march=armv5te
+VOASFLAGS:=-march=armv5te -mfpu=vfp
+endif
+
+ifeq ($(VOTT), v5x)
+VOCFLAGS:=-march=armv5te -mtune=xscale
+VOASFLAGS:=-march=armv5te -mfpu=vfp
+endif
+
+ifeq ($(VOTT), v6)
+#VOCFLAGS:=-march=armv6 -mtune=arm1136jf-s
+#VOASFLAGS:=-march=armv6
+VOCFLAGS:=-march=armv6j -mtune=arm1136jf-s -mfpu=vfp -mfloat-abi=softfp -mapcs -mtpcs-leaf-frame -mlong-calls
+VOASFLAGS:=-march=armv6j -mcpu=arm1136jf-s -mfpu=arm1136jf-s -mfloat-abi=softfp -mapcs-float -mapcs-reentrant
+endif
+
+#
+# global link options
+VOLDFLAGS:=-Wl,-x,-X,--as-needed
+
+
+ifeq ($(VOTT), v7)
+VOCFLAGS+=-march=armv7-a -mtune=cortex-a8 -mfpu=neon -mfloat-abi=softfp
+VOASFLAGS+=-march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp
+VOLDFLAGS+=-Wl,--fix-cortex-a8
+endif
+
+#global compiling options for ARM target
+ifneq ($(VOTT), pc)
+VOASFLAGS+=--strip-local-absolute -R
+endif
+
+
+ifeq ($(VODBG), yes)
+VOCFLAGS+=-D_DEBUG -g
+else
+VOCFLAGS+=-DNDEBUG -O3
+endif
+
+VOCFLAGS+=$(VOPREDEF) $(VOMM) -Wall -fsigned-char -fomit-frame-pointer -fno-leading-underscore -fpic -fPIC -pipe -ftracer -fforce-addr -fno-bounds-check #-fvisibility=hidden #-fvisibility-inlines-hidden ##-ftree-loop-linear -mthumb -nostdinc -dD -fprefetch-loop-arrays
+
+
+ifneq ($(VOTT), pc)
+VOCFLAGS+=$(CCTCFLAGS) $(CCTINC)
+VOCPPFLAGS:=-fno-rtti $(VOCFLAGS)
+
+ifeq ($(VOMT), exe)
+VOLDFLAGS+=$(TELDFLAGS)
+endif
+
+ifeq ($(VOMT), lib)
+VOLDFLAGS+=$(TLLDFLAGS)
+endif
+else
+VOCPPFLAGS:=$(VOCFLAGS)
+ifeq ($(VOMT), lib)
+VOLDFLAGS+=-shared
+endif
+endif
+
+ifeq ($(VODBG), yes)
+#VOLDFLAGS:=
+endif
+
+# where to place object files
+OBJDIR=obj
+
diff --git a/media/libstagefright/codecs/aacenc/basic_op/basic_op.h b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
new file mode 100644
index 0000000..5457f33
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/basic_op.h
@@ -0,0 +1,1166 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: basicop2.h
+
+ Content: Constants , Globals and Basic arithmetic operators.
+
+*******************************************************************************/
+
+#ifndef __BASIC_OP_H
+#define __BASIC_OP_H
+
+#include "typedef.h"
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)0x7fff
+#define MIN_16 (Word16)0x8000
+#define ABS(a) ((a) >= 0) ? (a) : (-(a))
+
+/* Short abs, 1 */
+#define abs_s(x) ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16))
+
+/* 16 bit var1 -> MSB, 2 */
+#define L_deposit_h(x) (((Word32)(x)) << 16)
+
+
+/* 16 bit var1 -> LSB, 2 */
+#define L_deposit_l(x) ((Word32)(x))
+
+
+/* Long abs, 3 */
+#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32)
+
+
+/* Short negate, 1 */
+#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1))))
+
+
+/* Long negate, 2 */
+#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1)))
+
+
+#define MULHIGH(A,B) (int)(((Word64)(A)*(Word64)(B)) >> 32)
+#define fixmul(a, b) (int)((((Word64)(a)*(Word64)(b)) >> 32) << 1)
+
+
+#if (SATRUATE_IS_INLINE)
+__inline Word16 saturate(Word32 L_var1);
+#else
+Word16 saturate(Word32 L_var1);
+#endif
+
+/* Short shift left, 1 */
+#if (SHL_IS_INLINE)
+__inline Word16 shl (Word16 var1, Word16 var2);
+#else
+Word16 shl (Word16 var1, Word16 var2);
+#endif
+
+/* Short shift right, 1 */
+#if (SHR_IS_INLINE)
+__inline Word16 shr (Word16 var1, Word16 var2);
+#else
+Word16 shr (Word16 var1, Word16 var2);
+#endif
+
+#if (L_MULT_IS_INLINE)
+__inline Word32 L_mult(Word16 var1, Word16 var2);
+#else
+Word32 L_mult(Word16 var1, Word16 var2);
+#endif
+
+/* Msu, 1 */
+#if (L_MSU_IS_INLINE)
+__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);
+#else
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2);
+#endif
+
+/* Long sub, 2 */
+#if (L_SUB_IS_INLINE)
+__inline Word32 L_sub(Word32 L_var1, Word32 L_var2);
+#else
+Word32 L_sub(Word32 L_var1, Word32 L_var2);
+#endif
+
+/* Long shift left, 2 */
+#if (L_SHL_IS_INLINE)
+__inline Word32 L_shl (Word32 L_var1, Word16 var2);
+#else
+Word32 L_shl (Word32 L_var1, Word16 var2);
+#endif
+
+/* Long shift right, 2*/
+#if (L_SHR_IS_INLINE)
+__inline Word32 L_shr (Word32 L_var1, Word16 var2);
+#else
+Word32 L_shr (Word32 L_var1, Word16 var2);
+#endif
+
+/* Short add, 1 */
+#if (ADD_IS_INLINE)
+__inline Word16 add (Word16 var1, Word16 var2);
+#else
+Word16 add (Word16 var1, Word16 var2);
+#endif
+
+/* Short sub, 1 */
+#if (SUB_IS_INLINE)
+__inline Word16 sub(Word16 var1, Word16 var2);
+#else
+Word16 sub(Word16 var1, Word16 var2);
+#endif
+
+/* Short division, 18 */
+#if (DIV_S_IS_INLINE)
+__inline Word16 div_s (Word16 var1, Word16 var2);
+#else
+Word16 div_s (Word16 var1, Word16 var2);
+#endif
+
+/* Short mult, 1 */
+#if (MULT_IS_INLINE)
+__inline Word16 mult (Word16 var1, Word16 var2);
+#else
+Word16 mult (Word16 var1, Word16 var2);
+#endif
+
+/* Short norm, 15 */
+#if (NORM_S_IS_INLINE)
+__inline Word16 norm_s (Word16 var1);
+#else
+Word16 norm_s (Word16 var1);
+#endif
+
+/* Long norm, 30 */
+#if (NORM_L_IS_INLINE)
+__inline Word16 norm_l (Word32 L_var1);
+#else
+Word16 norm_l (Word32 L_var1);
+#endif
+
+/* Round, 1 */
+#if (ROUND_IS_INLINE)
+__inline Word16 round16(Word32 L_var1);
+#else
+Word16 round16(Word32 L_var1);
+#endif
+
+/* Mac, 1 */
+#if (L_MAC_IS_INLINE)
+__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);
+#else
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2);
+#endif
+
+#if (L_ADD_IS_INLINE)
+__inline Word32 L_add (Word32 L_var1, Word32 L_var2);
+#else
+Word32 L_add (Word32 L_var1, Word32 L_var2);
+#endif
+
+/* Extract high, 1 */
+#if (EXTRACT_H_IS_INLINE)
+__inline Word16 extract_h (Word32 L_var1);
+#else
+Word16 extract_h (Word32 L_var1);
+#endif
+
+/* Extract low, 1 */
+#if (EXTRACT_L_IS_INLINE)
+__inline Word16 extract_l(Word32 L_var1);
+#else
+Word16 extract_l(Word32 L_var1);
+#endif
+
+/* Mult with round, 2 */
+#if (MULT_R_IS_INLINE)
+__inline Word16 mult_r(Word16 var1, Word16 var2);
+#else
+Word16 mult_r(Word16 var1, Word16 var2);
+#endif
+
+/* Shift right with round, 2 */
+#if (SHR_R_IS_INLINE)
+__inline Word16 shr_r (Word16 var1, Word16 var2);
+#else
+Word16 shr_r (Word16 var1, Word16 var2);
+#endif
+
+/* Mac with rounding,2 */
+#if (MAC_R_IS_INLINE)
+__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2);
+#else
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2);
+#endif
+
+/* Msu with rounding,2 */
+#if (MSU_R_IS_INLINE)
+__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2);
+#else
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2);
+#endif
+
+/* Long shift right with round, 3 */
+#if (L_SHR_R_IS_INLINE)
+__inline Word32 L_shr_r (Word32 L_var1, Word16 var2);
+#else
+Word32 L_shr_r (Word32 L_var1, Word16 var2);
+#endif
+
+#if ARMV4_INASM
+__inline Word32 ASM_L_shr(Word32 L_var1, Word16 var2)
+{
+ Word32 result;
+ asm volatile(
+ "MOV %[result], %[L_var1], ASR %[var2] \n"
+ :[result]"=r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2)
+ );
+ return result;
+}
+
+__inline Word32 ASM_L_shl(Word32 L_var1, Word16 var2)
+{
+ Word32 result;
+ asm volatile(
+ "MOV r2, %[L_var1] \n"
+ "MOV r3, #0x7fffffff\n"
+ "MOV %[result], %[L_var1], ASL %[var2] \n"
+ "TEQ r2, %[result], ASR %[var2]\n"
+ "EORNE %[result],r3,r2,ASR#31\n"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2)
+ :"r2", "r3"
+ );
+ return result;
+}
+
+__inline Word32 ASM_shr(Word32 L_var1, Word16 var2)
+{
+ Word32 result;
+ asm volatile(
+ "CMP %[var2], #15\n"
+ "MOVGE %[var2], #15\n"
+ "MOV %[result], %[L_var1], ASR %[var2]\n"
+ :[result]"=r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2)
+ );
+ return result;
+}
+
+__inline Word32 ASM_shl(Word32 L_var1, Word16 var2)
+{
+ Word32 result;
+ asm volatile(
+ "CMP %[var2], #16\n"
+ "MOVGE %[var2], #16\n"
+ "MOV %[result], %[L_var1], ASL %[var2]\n"
+ "MOV r3, #1\n"
+ "MOV r2, %[result], ASR #15\n"
+ "RSB r3,r3,r3,LSL #15 \n"
+ "TEQ r2, %[result], ASR #31 \n"
+ "EORNE %[result], r3, %[result],ASR #31"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1), [var2]"r"(var2)
+ :"r2", "r3"
+ );
+ return result;
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | definitions for inline basic arithmetic operators |
+ |___________________________________________________________________________|
+*/
+#if (SATRUATE_IS_INLINE)
+__inline Word16 saturate(Word32 L_var1)
+{
+#if ARMV5TE_SAT
+ Word16 result;
+ asm volatile (
+ "MOV %[result], %[L_var1]\n"
+ "MOV r3, #1\n"
+ "MOV r2,%[L_var1],ASR#15\n"
+ "RSB r3, r3, r3, LSL #15\n"
+ "TEQ r2,%[L_var1],ASR#31\n"
+ "EORNE %[result],r3,%[L_var1],ASR#31\n"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1)
+ :"r2", "r3"
+ );
+
+ return result;
+#else
+ Word16 var_out;
+
+ //var_out = (L_var1 > (Word32)0X00007fffL) ? (MAX_16) : ((L_var1 < (Word32)0xffff8000L) ? (MIN_16) : ((Word16)L_var1));
+
+ if (L_var1 > 0X00007fffL)
+ {
+ var_out = MAX_16;
+ }
+ else if (L_var1 < (Word32) 0xffff8000L)
+ {
+ var_out = MIN_16;
+ }
+ else
+ {
+ var_out = extract_l(L_var1);
+ }
+
+ return (var_out);
+#endif
+}
+#endif
+
+/* Short shift left, 1 */
+#if (SHL_IS_INLINE)
+__inline Word16 shl (Word16 var1, Word16 var2)
+{
+#if ARMV5TE_SHL
+ if(var2>=0)
+ {
+ return ASM_shl( var1, var2);
+ }
+ else
+ {
+ return ASM_shr( var1, -var2);
+ }
+#else
+ Word16 var_out;
+ Word32 result;
+
+ if (var2 < 0)
+ {
+ var_out = shr (var1, (Word16)-var2);
+ }
+ else
+ {
+ result = (Word32) var1 *((Word32) 1 << var2);
+
+ if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+ {
+ var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
+ }
+ else
+ {
+ var_out = extract_l(result);
+ }
+ }
+ return (var_out);
+#endif
+}
+#endif
+
+/* Short shift right, 1 */
+#if (SHR_IS_INLINE)
+__inline Word16 shr (Word16 var1, Word16 var2)
+{
+#if ARMV5TE_SHR
+ if(var2>=0)
+ {
+ return ASM_shr( var1, var2);
+ }
+ else
+ {
+ return ASM_shl( var1, -var2);
+ }
+#else
+ Word16 var_out;
+
+ if (var2 < 0)
+ {
+ var_out = shl (var1, (Word16)-var2);
+ }
+ else
+ {
+ if (var2 >= 15)
+ {
+ var_out = (Word16)((var1 < 0) ? -1 : 0);
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = (Word16)(~((~var1) >> var2));
+ }
+ else
+ {
+ var_out = (Word16)(var1 >> var2);
+ }
+ }
+ }
+
+ return (var_out);
+#endif
+}
+#endif
+
+
+#if (L_MULT_IS_INLINE)
+__inline Word32 L_mult(Word16 var1, Word16 var2)
+{
+#if ARMV5TE_L_MULT
+ Word32 result;
+ asm volatile(
+ "SMULBB %[result], %[var1], %[var2] \n"
+ "QADD %[result], %[result], %[result] \n"
+ :[result]"+r"(result)
+ :[var1]"r"(var1), [var2]"r"(var2)
+ );
+ return result;
+#else
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 *(Word32) var2;
+
+ if (L_var_out != (Word32) 0x40000000L)
+ {
+ L_var_out <<= 1;
+ }
+ else
+ {
+ L_var_out = MAX_32;
+ }
+ return (L_var_out);
+#endif
+}
+#endif
+
+#if (L_MSU_IS_INLINE)
+__inline Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+#if ARMV5TE_L_MSU
+ Word32 result;
+ asm volatile(
+ "SMULBB %[result], %[var1], %[var2] \n"
+ "QADD %[result], %[result], %[result] \n"
+ "QSUB %[result], %[L_var3], %[result]\n"
+ :[result]"+r"(result)
+ :[L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2)
+ );
+ return result;
+#else
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult(var1, var2);
+ L_var_out = L_sub(L_var3, L_product);
+ return (L_var_out);
+#endif
+}
+#endif
+
+#if (L_SUB_IS_INLINE)
+__inline Word32 L_sub(Word32 L_var1, Word32 L_var2)
+{
+#if ARMV5TE_L_SUB
+ Word32 result;
+ asm volatile(
+ "QSUB %[result], %[L_var1], %[L_var2]\n"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2)
+ );
+ return result;
+#else
+ Word32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) != 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ }
+ }
+
+ return (L_var_out);
+#endif
+}
+#endif
+
+#if (L_SHL_IS_INLINE)
+__inline Word32 L_shl(Word32 L_var1, Word16 var2)
+{
+#if ARMV5TE_L_SHL
+ if(var2>=0)
+ {
+ return ASM_L_shl( L_var1, var2);
+ }
+ else
+ {
+ return ASM_L_shr( L_var1, -var2);
+ }
+#else
+ Word32 L_var_out = 0L;
+
+ if (var2 <= 0)
+ {
+ L_var1 = L_shr(L_var1, (Word16)-var2);
+ }
+ else
+ {
+ for (; var2 > 0; var2--)
+ {
+ if (L_var1 > (Word32) 0X3fffffffL)
+ {
+ return MAX_32;
+ }
+ else
+ {
+ if (L_var1 < (Word32) 0xc0000000L)
+ {
+ return MIN_32;
+ }
+ }
+ L_var1 <<= 1;
+ L_var_out = L_var1;
+ }
+ }
+ return (L_var1);
+#endif
+}
+#endif
+
+#if (L_SHR_IS_INLINE)
+__inline Word32 L_shr (Word32 L_var1, Word16 var2)
+{
+#if ARMV5TE_L_SHR
+ if(var2>=0)
+ {
+ return ASM_L_shr( L_var1, var2);
+ }
+ else
+ {
+ return ASM_L_shl( L_var1, -var2);
+ }
+#else
+ Word32 L_var_out;
+
+ if (var2 < 0)
+ {
+ L_var_out = L_shl (L_var1, (Word16)-var2);
+ }
+ else
+ {
+ if (var2 >= 31)
+ {
+ L_var_out = (L_var1 < 0L) ? -1 : 0;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = ~((~L_var1) >> var2);
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+ return (L_var_out);
+#endif
+}
+#endif
+
+/* Short add, 1 */
+#if (ADD_IS_INLINE)
+__inline Word16 add (Word16 var1, Word16 var2)
+{
+#if ARMV5TE_ADD
+ Word32 result;
+ asm volatile(
+ "ADD %[result], %[var1], %[var2] \n"
+ "MOV r3, #0x1\n"
+ "MOV r2, %[result], ASR #15\n"
+ "RSB r3, r3, r3, LSL, #15\n"
+ "TEQ r2, %[result], ASR #31\n"
+ "EORNE %[result], r3, %[result], ASR #31"
+ :[result]"+r"(result)
+ :[var1]"r"(var1), [var2]"r"(var2)
+ :"r2", "r3"
+ );
+ return result;
+#else
+ Word16 var_out;
+ Word32 L_sum;
+
+ L_sum = (Word32) var1 + var2;
+ var_out = saturate(L_sum);
+
+ return (var_out);
+#endif
+}
+#endif
+
+/* Short sub, 1 */
+#if (SUB_IS_INLINE)
+__inline Word16 sub(Word16 var1, Word16 var2)
+{
+#if ARMV5TE_SUB
+ Word32 result;
+ asm volatile(
+ "MOV r3, #1\n"
+ "SUB %[result], %[var1], %[var2] \n"
+ "RSB r3,r3,r3,LSL#15\n"
+ "MOV r2, %[var1], ASR #15 \n"
+ "TEQ r2, %[var1], ASR #31 \n"
+ "EORNE %[result], r3, %[result], ASR #31 \n"
+ :[result]"+r"(result)
+ :[var1]"r"(var1), [var2]"r"(var2)
+ :"r2", "r3"
+ );
+ return result;
+#else
+ Word16 var_out;
+ Word32 L_diff;
+
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate(L_diff);
+
+ return (var_out);
+#endif
+}
+#endif
+
+/* Short division, 18 */
+#if (DIV_S_IS_INLINE)
+__inline Word16 div_s (Word16 var1, Word16 var2)
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+
+ var_out = MAX_16;
+ if (var1!= var2)//var1!= var2
+ {
+ var_out = 0;
+ L_num = (Word32) var1;
+
+ L_denom = (Word32) var2;
+
+ //return (L_num<<15)/var2;
+
+ for (iteration = 0; iteration < 15; iteration++)
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+
+ if (L_num >= L_denom)
+ {
+ L_num -= L_denom;
+ var_out++;
+ }
+ }
+ }
+ return (var_out);
+}
+#endif
+
+/* Short mult, 1 */
+#if (MULT_IS_INLINE)
+__inline Word16 mult (Word16 var1, Word16 var2)
+{
+#if ARMV5TE_MULT
+ Word32 result;
+ asm volatile(
+ "SMULBB r2, %[var1], %[var2] \n"
+ "MOV r3, #1\n"
+ "MOV %[result], r2, ASR #15\n"
+ "RSB r3, r3, r3, LSL #15\n"
+ "MOV r2, %[result], ASR #15\n"
+ "TEQ r2, %[result], ASR #31\n"
+ "EORNE %[result], r3, %[result], ASR #31 \n"
+ :[result]"+r"(result)
+ :[var1]"r"(var1), [var2]"r"(var2)
+ :"r2", "r3"
+ );
+ return result;
+#else
+ Word16 var_out;
+ Word32 L_product;
+
+ L_product = (Word32) var1 *(Word32) var2;
+ L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+ if (L_product & (Word32) 0x00010000L)
+ L_product = L_product | (Word32) 0xffff0000L;
+ var_out = saturate(L_product);
+
+ return (var_out);
+#endif
+}
+#endif
+
+
+/* Short norm, 15 */
+#if (NORM_S_IS_INLINE)
+__inline Word16 norm_s (Word16 var1)
+{
+#if ARMV5TE_NORM_S
+ Word16 result;
+ asm volatile(
+ "MOV r2,%[var1] \n"
+ "CMP r2, #0\n"
+ "RSBLT %[var1], %[var1], #0 \n"
+ "CLZNE %[result], %[var1]\n"
+ "SUBNE %[result], %[result], #17\n"
+ "MOVEQ %[result], #0\n"
+ "CMP r2, #-1\n"
+ "MOVEQ %[result], #15\n"
+ :[result]"+r"(result)
+ :[var1]"r"(var1)
+ :"r2"
+ );
+ return result;
+#else
+ Word16 var_out;
+
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == -1)
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var1 = (Word16)~var1;
+ }
+ for (var_out = 0; var1 < 0x4000; var_out++)
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+ return (var_out);
+#endif
+}
+#endif
+
+/* Long norm, 30 */
+#if (NORM_L_IS_INLINE)
+__inline Word16 norm_l (Word32 L_var1)
+{
+#if ARMV5TE_NORM_L
+ Word16 result;
+ asm volatile(
+ "CMP %[L_var1], #0\n"
+ "CLZNE %[result], %[L_var1]\n"
+ "SUBNE %[result], %[result], #1\n"
+ "MOVEQ %[result], #0\n"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1)
+ );
+ return result;
+#else
+ //Word16 var_out;
+
+ //if (L_var1 == 0)
+ //{
+ // var_out = 0;
+ //}
+ //else
+ //{
+ // if (L_var1 == (Word32) 0xffffffffL)
+ // {
+ // var_out = 31;
+ // }
+ // else
+ // {
+ // if (L_var1 < 0)
+ // {
+ // L_var1 = ~L_var1;
+ // }
+ // for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+ // {
+ // L_var1 <<= 1;
+ // }
+ // }
+ //}
+ //return (var_out);
+ Word16 a16;
+ Word16 r = 0 ;
+
+
+ if ( L_var1 < 0 ) {
+ L_var1 = ~L_var1;
+ }
+
+ if (0 == (L_var1 & 0x7fff8000)) {
+ a16 = extract_l(L_var1);
+ r += 16;
+
+ if (0 == (a16 & 0x7f80)) {
+ r += 8;
+
+ if (0 == (a16 & 0x0078)) {
+ r += 4;
+
+ if (0 == (a16 & 0x0006)) {
+ r += 2;
+
+ if (0 == (a16 & 0x0001)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0004)) {
+ r += 1;
+ }
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0060)) {
+ r += 2;
+
+ if (0 == (a16 & 0x0010)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0040)) {
+ r += 1;
+ }
+ }
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x7800)) {
+ r += 4;
+
+ if (0 == (a16 & 0x0600)) {
+ r += 2;
+
+ if (0 == (a16 & 0x0100)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0400)) {
+ r += 1;
+ }
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x6000)) {
+ r += 2;
+
+ if (0 == (a16 & 0x1000)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x4000)) {
+ r += 1;
+ }
+ }
+ }
+ }
+ }
+ else {
+ a16 = extract_h(L_var1);
+
+ if (0 == (a16 & 0x7f80)) {
+ r += 8;
+
+ if (0 == (a16 & 0x0078)) {
+ r += 4 ;
+
+ if (0 == (a16 & 0x0006)) {
+ r += 2;
+
+ if (0 == (a16 & 0x0001)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0004)) {
+ r += 1;
+ }
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0060)) {
+ r += 2;
+
+ if (0 == (a16 & 0x0010)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0040)) {
+ r += 1;
+ }
+ }
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x7800)) {
+ r += 4;
+
+ if (0 == (a16 & 0x0600)) {
+ r += 2;
+
+ if (0 == (a16 & 0x0100)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x0400)) {
+ r += 1;
+ }
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x6000)) {
+ r += 2;
+
+ if (0 == (a16 & 0x1000)) {
+ r += 1;
+ }
+ }
+ else {
+
+ if (0 == (a16 & 0x4000)) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ return r ;
+#endif
+}
+#endif
+
+/* Round, 1 */
+#if (ROUND_IS_INLINE)
+__inline Word16 round16(Word32 L_var1)
+{
+#if ARMV5TE_ROUND
+ Word16 result;
+ asm volatile(
+ "MOV r1,#0x00008000\n"
+ "QADD %[result], %[L_var1], r1\n"
+ "MOV %[result], %[result], ASR #16 \n"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1)
+ :"r1"
+ );
+ return result;
+#else
+ Word16 var_out;
+ Word32 L_rounded;
+
+ L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+ var_out = extract_h (L_rounded);
+ return (var_out);
+#endif
+}
+#endif
+
+/* Mac, 1 */
+#if (L_MAC_IS_INLINE)
+__inline Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+#if ARMV5TE_L_MAC
+ Word32 result;
+ asm volatile(
+ "SMULBB %[result], %[var1], %[var2]\n"
+ "QADD %[result], %[result], %[result]\n"
+ "QADD %[result], %[result], %[L_var3]\n"
+ :[result]"+r"(result)
+ : [L_var3]"r"(L_var3), [var1]"r"(var1), [var2]"r"(var2)
+ );
+ return result;
+#else
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult(var1, var2);
+ L_var_out = L_add (L_var3, L_product);
+ return (L_var_out);
+#endif
+}
+#endif
+
+#if (L_ADD_IS_INLINE)
+__inline Word32 L_add (Word32 L_var1, Word32 L_var2)
+{
+#if ARMV5TE_L_ADD
+ Word32 result;
+ asm volatile(
+ "QADD %[result], %[L_var1], %[L_var2]\n"
+ :[result]"+r"(result)
+ :[L_var1]"r"(L_var1), [L_var2]"r"(L_var2)
+ );
+ return result;
+#else
+ Word32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+ if (((L_var1 ^ L_var2) & MIN_32) == 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+ }
+ }
+ return (L_var_out);
+#endif
+}
+#endif
+
+
+
+#if (MULT_R_IS_INLINE)
+__inline Word16 mult_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32)var1 *(Word32)var2; /* product */
+ L_product_arr += (Word32)0x00004000L; /* round */
+ L_product_arr >>= 15; /* shift */
+
+ var_out = saturate(L_product_arr);
+
+ return (var_out);
+}
+#endif
+
+#if (SHR_R_IS_INLINE)
+__inline Word16 shr_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 > 15)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr(var1, var2);
+
+ if (var2 > 0)
+ {
+ if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ }
+
+ return (var_out);
+}
+#endif
+
+#if (MAC_R_IS_INLINE)
+__inline Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_mac (L_var3, var1, var2);
+ var_out = (Word16)((L_var3 + 0x8000L) >> 16);
+
+ return (var_out);
+}
+#endif
+
+#if (MSU_R_IS_INLINE)
+__inline Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_msu (L_var3, var1, var2);
+ var_out = (Word16)((L_var3 + 0x8000L) >> 16);
+
+ return (var_out);
+}
+#endif
+
+#if (L_SHR_R_IS_INLINE)
+__inline Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 > 31)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr(L_var1, var2);
+
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ L_var_out++;
+ }
+ }
+ }
+
+ return (L_var_out);
+}
+#endif
+
+#if (EXTRACT_H_IS_INLINE)
+__inline Word16 extract_h (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) (L_var1 >> 16);
+
+ return (var_out);
+}
+#endif
+
+#if (EXTRACT_L_IS_INLINE)
+__inline Word16 extract_l(Word32 L_var1)
+{
+ return (Word16) L_var1;
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/basic_op/basicop2.c b/media/libstagefright/codecs/aacenc/basic_op/basicop2.c
new file mode 100644
index 0000000..a0d5dba
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/basicop2.c
@@ -0,0 +1,1624 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: basicop2.c
+
+ Content: Basic arithmetic operators.
+
+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+
+/*___________________________________________________________________________
+ | |
+ | Functions |
+ |___________________________________________________________________________|
+*/
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : saturate |
+ | |
+ | Purpose : |
+ | |
+ | Limit the 32 bit input to the range of a 16 bit word. |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!SATRUATE_IS_INLINE)
+Word16 saturate(Word32 L_var1)
+{
+ Word16 var_out;
+
+ if (L_var1 > 0X00007fffL)
+ {
+ var_out = MAX_16;
+ }
+ else if (L_var1 < (Word32) 0xffff8000L)
+ {
+ var_out = MIN_16;
+ }
+ else
+ {
+ var_out = extract_l(L_var1);
+ }
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : add |
+ | |
+ | Purpose : |
+ | |
+ | Performs the addition (var1+var2) with overflow control and saturation;|
+ | the 16 bit result is set at +32767 when overflow occurs or at -32768 |
+ | when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!ADD_IS_INLINE)
+Word16 add (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_sum;
+
+ L_sum = (Word32)var1 + (Word32)var2;
+ var_out = saturate(L_sum);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : sub |
+ | |
+ | Purpose : |
+ | |
+ | Performs the subtraction (var1+var2) with overflow control and satu- |
+ | ration; the 16 bit result is set at +32767 when overflow occurs or at |
+ | -32768 when underflow occurs. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!SUB_IS_INLINE)
+Word16 sub(Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_diff;
+
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate(L_diff);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : abs_s |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of var1; abs_s(-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+//Word16 abs_s (Word16 var1)
+//{
+// Word16 var_out;
+//
+// if (var1 == MIN_16)
+// {
+// var_out = MAX_16;
+// }
+// else
+// {
+// if (var1 < 0)
+// {
+// var_out = (Word16)-var1;
+// }
+// else
+// {
+// var_out = var1;
+// }
+// }
+//
+// return (var_out);
+//}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+ | the var2 LSB of the result. If var2 is negative, arithmetically shift |
+ | var1 right by -var2 with sign extension. Saturate the result in case of |
+ | underflows or overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!SHL_IS_INLINE)
+Word16 shl (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 result;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = shr (var1, (Word16)-var2);
+ }
+ else
+ {
+ result = (Word32) var1 *((Word32) 1 << var2);
+
+ if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+ {
+ //Overflow = 1;
+ var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
+ }
+ else
+ {
+ var_out = extract_l(result);
+ }
+ }
+
+ return (var_out);
+}
+#endif
+// end
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 16 bit input var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift var1 left by |
+ | -var2 with sign extension. Saturate the result in case of underflows or |
+ | overflows. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!SHR_IS_INLINE)
+Word16 shr (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = shl (var1, (Word16)-var2);
+ }
+ else
+ {
+ if (var2 >= 15)
+ {
+ var_out = (Word16)((var1 < 0) ? -1 : 0);
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = (Word16)(~((~var1) >> var2));
+ }
+ else
+ {
+ var_out = (Word16)(var1 >> var2);
+ }
+ }
+ }
+
+ return (var_out);
+}
+#endif
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult |
+ | |
+ | Purpose : |
+ | |
+ | Performs the multiplication of var1 by var2 and gives a 16 bit result |
+ | which is scaled i.e.: |
+ | mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and |
+ | mult(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!MULT_IS_INLINE)
+Word16 mult (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product;
+
+ L_product = (Word32) var1 *(Word32) var2;
+
+ L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+
+ if (L_product & (Word32) 0x00010000L)
+ L_product = L_product | (Word32) 0xffff0000L;
+
+ var_out = saturate(L_product);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mult |
+ | |
+ | Purpose : |
+ | |
+ | L_mult is the 32 bit result of the multiplication of var1 times var2 |
+ | with one shift left i.e.: |
+ | L_mult(var1,var2) = L_shl((var1 times var2),1) and |
+ | L_mult(-32768,-32768) = 2147483647. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!L_MULT_IS_INLINE)
+Word32 L_mult(Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = (Word32) var1 *(Word32) var2;
+
+ if (L_var_out != (Word32) 0x40000000L)
+ {
+ L_var_out <<= 1;
+ }
+ else
+ {
+ L_var_out = MAX_32;
+ }
+
+ return (L_var_out);
+}
+#endif
+// end
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate var1 with saturation, saturate in the case where input is -32768:|
+ | negate(var1) = sub(0,var1). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+//Word16 negate (Word16 var1)
+//{
+// Word16 var_out;
+//
+// var_out = (Word16)((var1 == MIN_16) ? MAX_16 : -var1);
+//
+// return (var_out);
+//}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_h |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 MSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!EXTRACT_H_IS_INLINE)
+Word16 extract_h (Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) (L_var1 >> 16);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : extract_l |
+ | |
+ | Purpose : |
+ | |
+ | Return the 16 LSB of L_var1. |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!EXTRACT_L_IS_INLINE)
+Word16 extract_l(Word32 L_var1)
+{
+ Word16 var_out;
+
+ var_out = (Word16) L_var1;
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : round |
+ | |
+ | Purpose : |
+ | |
+ | Round the lower 16 bits of the 32 bit input number into the MS 16 bits |
+ | with saturation. Shift the resulting bits right by 16 and return the 16 |
+ | bit number: |
+ | round(L_var1) = extract_h(L_add(L_var1,32768)) |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32 ) whose value falls in the |
+ | range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!ROUND_IS_INLINE)
+Word16 round16(Word32 L_var1)
+{
+ Word16 var_out;
+ Word32 L_rounded;
+
+ L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+ var_out = extract_h (L_rounded);
+
+ return (var_out);
+}
+#endif
+// end
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_mac |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation, return a 32 bit result: |
+ | L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#if (!L_MSU_IS_INLINE)
+Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult(var1, var2);
+ L_var_out = L_add (L_var3, L_product);
+
+ return (L_var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_msu |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result to L_var3 with saturation, return a 32 bit result: |
+ | L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). |
+ | |
+ | Complexity weight : 1 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!L_MSU_IS_INLINE)
+Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+
+ L_product = L_mult(var1, var2);
+ L_var_out = L_sub (L_var3, L_product);
+
+ return (L_var_out);
+}
+#endif
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_add |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits addition of the two 32 bits variables (L_var1+L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#if (!L_ADD_IS_INLINE)
+Word32 L_add (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 + L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) == 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+ //Overflow = 1;
+ }
+ }
+
+ return (L_var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_sub |
+ | |
+ | Purpose : |
+ | |
+ | 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with |
+ | overflow control and saturation; the result is set at +2147483647 when |
+ | overflow occurs or at -2147483648 when underflow occurs. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | L_var2 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#if (!L_SUB_IS_INLINE)
+Word32 L_sub(Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+
+ L_var_out = L_var1 - L_var2;
+
+ if (((L_var1 ^ L_var2) & MIN_32) != 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ //Overflow = 1;
+ }
+ }
+
+ return (L_var_out);
+}
+#endif
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_negate |
+ | |
+ | Purpose : |
+ | |
+ | Negate the 32 bit variable L_var1 with saturation; saturate in the case |
+ | where input is -2147483648 (0x8000 0000). |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+//Word32 L_negate (Word32 L_var1)
+//{
+// Word32 L_var_out;
+//
+// L_var_out = (L_var1 == MIN_32) ? MAX_32 : -L_var1;
+//
+// return (L_var_out);
+//}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mult_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as mult with rounding, i.e.: |
+ | mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and |
+ | mult_r(-32768,-32768) = 32767. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!MULT_R_IS_INLINE)
+Word16 mult_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+
+ L_product_arr = (Word32) var1 *(Word32) var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15; /* shift */
+
+ if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+ var_out = saturate(L_product_arr);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shl |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero |
+ | fill the var2 LSB of the result. If var2 is negative, arithmetically |
+ | shift L_var1 right by -var2 with sign extension. Saturate the result in |
+ | case of underflows or overflows. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!L_SHL_IS_INLINE)
+Word32 L_shl (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out = 0L;
+
+ if (var2 <= 0)
+ {
+ L_var1 = L_shr(L_var1, (Word16)-var2);
+ }
+ else
+ {
+ for (; var2 > 0; var2--)
+ {
+ if (L_var1 > (Word32) 0X3fffffffL)
+ {
+ return MAX_32;
+ }
+ else
+ {
+ if (L_var1 < (Word32) 0xc0000000L)
+ {
+ return MIN_32;
+ }
+ }
+ L_var1 <<= 1;
+ }
+ }
+ return (L_var1);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr |
+ | |
+ | Purpose : |
+ | |
+ | Arithmetically shift the 32 bit input L_var1 right var2 positions with |
+ | sign extension. If var2 is negative, arithmetically shift L_var1 left |
+ | by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+ | in case of underflows or overflows. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+
+#if (!L_SHR_IS_INLINE)
+Word32 L_shr (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 < 0)
+ {
+ L_var_out = L_shl (L_var1, (Word16)-var2);
+ }
+ else
+ {
+ if (var2 >= 31)
+ {
+ L_var_out = (L_var1 < 0L) ? -1 : 0;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = ~((~L_var1) >> var2);
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+ return (L_var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as shr(var1,var2) but with rounding. Saturate the result in case of|
+ | underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (sub(shl(shr(var1,var2),1),shr(var1,sub(var2,1)))) |
+ | is equal to zero |
+ | then |
+ | shr_r(var1,var2) = shr(var1,var2) |
+ | else |
+ | shr_r(var1,var2) = add(shr(var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | shr_r(var1,var2) = shr(var1,var2). |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!SHR_R_IS_INLINE)
+Word16 shr_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ if (var2 > 15)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ var_out = shr (var1, var2);
+
+ if (var2 > 0)
+ {
+ if ((var1 & ((Word16) 1 << (var2 - 1))) != 0)
+ {
+ var_out++;
+ }
+ }
+ }
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : mac_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+ | result to L_var3 with saturation. Round the LS 16 bits of the result |
+ | into the MS 16 bits with saturation and shift the result right by 16. |
+ | Return a 16 bit result. |
+ | mac_r(L_var3,var1,var2) = round(L_mac(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!MAC_R_IS_INLINE)
+Word16 mac_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_mac (L_var3, var1, var2);
+ L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+ var_out = extract_h (L_var3);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : msu_r |
+ | |
+ | Purpose : |
+ | |
+ | Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+ | bit result to L_var3 with saturation. Round the LS 16 bits of the res- |
+ | ult into the MS 16 bits with saturation and shift the result right by |
+ | 16. Return a 16 bit result. |
+ | msu_r(L_var3,var1,var2) = round(L_msu(L_var3,var1,var2)) |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | L_var3 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 8000 <= L_var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+#if (!MSU_R_IS_INLINE)
+Word16 msu_r (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+
+ L_var3 = L_msu (L_var3, var1, var2);
+ L_var3 = L_add (L_var3, (Word32) 0x00008000L);
+ var_out = extract_h (L_var3);
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_h |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 MS bits of the 32 bit output. The |
+ | 16 LS bits of the output are zeroed. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff 0000. |
+ |___________________________________________________________________________|
+*/
+//Word32 L_deposit_h (Word16 var1)
+//{
+// Word32 L_var_out;
+//
+// L_var_out = (Word32) var1 << 16;
+//
+// return (L_var_out);
+//}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_deposit_l |
+ | |
+ | Purpose : |
+ | |
+ | Deposit the 16 bit var1 into the 16 LS bits of the 32 bit output. The |
+ | 16 MS bits of the output are sign extended. |
+ | |
+ | Complexity weight : 2 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0xFFFF 8000 <= var_out <= 0x0000 7fff. |
+ |___________________________________________________________________________|
+*/
+//Word32 L_deposit_l (Word16 var1)
+//{
+// Word32 L_var_out;
+//
+// L_var_out = (Word32) var1;
+//
+// return (L_var_out);
+//}
+
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_shr_r |
+ | |
+ | Purpose : |
+ | |
+ | Same as L_shr(L_var1,var2) but with rounding. Saturate the result in |
+ | case of underflows or overflows : |
+ | - If var2 is greater than zero : |
+ | if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+ | is equal to zero |
+ | then |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2) |
+ | else |
+ | L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) |
+ | - If var2 is less than or equal to zero : |
+ | L_shr_r(L_var1,var2) = L_shr(L_var1,var2). |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+#if (!L_SHR_R_IS_INLINE)
+Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+
+ if (var2 > 31)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr (L_var1, var2);
+
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ L_var_out++;
+ }
+ }
+ }
+
+ return (L_var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : L_abs |
+ | |
+ | Purpose : |
+ | |
+ | Absolute value of L_var1; Saturate in case where the input is |
+ | -214783648 |
+ | |
+ | Complexity weight : 3 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | L_var_out |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x7fff ffff. |
+ |___________________________________________________________________________|
+*/
+//Word32 L_abs (Word32 L_var1)
+//{
+// Word32 L_var_out;
+//
+// if (L_var1 == MIN_32)
+// {
+// L_var_out = MAX_32;
+// }
+// else
+// {
+// if (L_var1 < 0)
+// {
+// L_var_out = -L_var1;
+// }
+// else
+// {
+// L_var_out = L_var1;
+// }
+// }
+//
+// return (L_var_out);
+//}
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shift needed to normalize the 16 bit varia- |
+ | ble var1 for positive values on the interval with minimum of 16384 and |
+ | maximum of 32767, and for negative values on the interval with minimum |
+ | of -32768 and maximum of -16384; in order to normalize the result, the |
+ | following operation must be done : |
+ | norm_var1 = shl(var1,norm_s(var1)). |
+ | |
+ | Complexity weight : 15 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 000f. |
+ |___________________________________________________________________________|
+*/
+
+#if (!NORM_S_IS_INLINE)
+Word16 norm_s (Word16 var1)
+{
+ Word16 var_out;
+
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == -1)
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var1 = (Word16)~var1;
+ }
+ for (var_out = 0; var1 < 0x4000; var_out++)
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : div_s |
+ | |
+ | Purpose : |
+ | |
+ | Produces a result which is the fractional integer division of var1 by |
+ | var2; var1 and var2 must be positive and var2 must be greater or equal |
+ | to var1; the result is positive (leading bit equal to 0) and truncated |
+ | to 16 bits. |
+ | If var1 = var2 then div(var1,var2) = 32767. |
+ | |
+ | Complexity weight : 18 |
+ | |
+ | Inputs : |
+ | |
+ | var1 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var1 <= var2 and var2 != 0. |
+ | |
+ | var2 |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : var1 <= var2 <= 0x0000 7fff and var2 != 0. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+ | It's a Q15 value (point between b15 and b14). |
+ |___________________________________________________________________________|
+*/
+
+#if (!DIV_S_IS_INLINE)
+Word16 div_s (Word16 var1, Word16 var2)
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == var2)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ L_num = L_deposit_l (var1);
+ L_denom = L_deposit_l (var2);
+
+ for (iteration = 0; iteration < 15; iteration++)
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+
+ if (L_num >= L_denom)
+ {
+ L_num = L_sub(L_num, L_denom);
+ var_out = add (var_out, 1);
+ }
+ }
+ }
+ }
+
+ return (var_out);
+}
+#endif
+
+/*___________________________________________________________________________
+ | |
+ | Function Name : norm_l |
+ | |
+ | Purpose : |
+ | |
+ | Produces the number of left shifts needed to normalize the 32 bit varia-|
+ | ble L_var1 for positive values on the interval with minimum of |
+ | 1073741824 and maximum of 2147483647, and for negative values on the in-|
+ | terval with minimum of -2147483648 and maximum of -1073741824; in order |
+ | to normalize the result, the following operation must be done : |
+ | norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). |
+ | |
+ | Complexity weight : 30 |
+ | |
+ | Inputs : |
+ | |
+ | L_var1 |
+ | 32 bit long signed integer (Word32) whose value falls in the |
+ | range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+ | |
+ | Outputs : |
+ | |
+ | none |
+ | |
+ | Return Value : |
+ | |
+ | var_out |
+ | 16 bit short signed integer (Word16) whose value falls in the |
+ | range : 0x0000 0000 <= var_out <= 0x0000 001f. |
+ |___________________________________________________________________________|
+*/
+
+#if (!NORM_L_IS_INLINE)
+Word16 norm_l (Word32 L_var1)
+{
+ Word16 var_out;
+
+ if (L_var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (L_var1 == (Word32) 0xffffffffL)
+ {
+ var_out = 31;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var1 = ~L_var1;
+ }
+ for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+ {
+ L_var1 <<= 1;
+ }
+ }
+ }
+
+ return (var_out);
+}
+#endif
+
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
new file mode 100644
index 0000000..906a9df
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.c
@@ -0,0 +1,361 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: oper_32b.c
+
+ Content: This file contains operations in double precision.
+
+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+
+/*****************************************************************************
+ * *
+ * Function L_Extract() *
+ * *
+ * Extract from a 32 bit integer two 16 bit DPF. *
+ * *
+ * Arguments: *
+ * *
+ * L_32 : 32 bit integer. *
+ * 0x8000 0000 <= L_32 <= 0x7fff ffff. *
+ * hi : b16 to b31 of L_32 *
+ * lo : (L_32 - hi<<16)>>1 *
+ *****************************************************************************
+*/
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
+{
+ *hi = extract_h (L_32);
+ *lo = extract_l (L_msu (L_shr (L_32, 1), *hi, 16384));
+ return;
+}
+
+/*****************************************************************************
+ * *
+ * Function L_Comp() *
+ * *
+ * Compose from two 16 bit DPF a 32 bit integer. *
+ * *
+ * L_32 = hi<<16 + lo<<1 *
+ * *
+ * Arguments: *
+ * *
+ * hi msb *
+ * lo lsf (with sign) *
+ * *
+ * Return Value : *
+ * *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x8000 0000 <= L_32 <= 0x7fff fff0. *
+ * *
+ *****************************************************************************
+*/
+
+Word32 L_Comp (Word16 hi, Word16 lo)
+{
+ Word32 L_32;
+
+ L_32 = L_deposit_h (hi);
+ return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */
+}
+
+/*****************************************************************************
+ * Function Mpy_32() *
+ * *
+ * Multiply two 32 bit integers (DPF). The result is divided by 2**31 *
+ * *
+ * L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 *
+ * *
+ * This operation can also be viewed as the multiplication of two Q31 *
+ * number and the result is also in Q31. *
+ * *
+ * Arguments: *
+ * *
+ * hi1 hi part of first number *
+ * lo1 lo part of first number *
+ * hi2 hi part of second number *
+ * lo2 lo part of second number *
+ * *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
+{
+ Word32 L_32;
+
+ L_32 = L_mult (hi1, hi2);
+ L_32 = L_mac (L_32, mult (hi1, lo2), 1);
+ L_32 = L_mac (L_32, mult (lo1, hi2), 1);
+
+ return (L_32);
+}
+
+/*****************************************************************************
+ * Function Mpy_32_16() *
+ * *
+ * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
+ * by 2**15 *
+ * *
+ * *
+ * L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
+ * *
+ * Arguments: *
+ * *
+ * hi hi part of 32 bit number. *
+ * lo lo part of 32 bit number. *
+ * n 16 bit number. *
+ * *
+ *****************************************************************************
+*/
+
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
+{
+ Word32 L_32;
+
+ L_32 = L_mult (hi, n);
+ L_32 = L_mac (L_32, mult (lo, n), 1);
+
+ return (L_32);
+}
+
+/*****************************************************************************
+ * *
+ * Function Name : Div_32 *
+ * *
+ * Purpose : *
+ * Fractional integer division of two 32 bit numbers. *
+ * L_num / L_denom. *
+ * L_num and L_denom must be positive and L_num < L_denom. *
+ * L_denom = denom_hi<<16 + denom_lo<<1 *
+ * denom_hi is a normalize number. *
+ * *
+ * Inputs : *
+ * *
+ * L_num *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x0000 0000 < L_num < L_denom *
+ * *
+ * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) *
+ * *
+ * denom_hi *
+ * 16 bit positive normalized integer whose value falls in the *
+ * range : 0x4000 < hi < 0x7fff *
+ * denom_lo *
+ * 16 bit positive integer whose value falls in the *
+ * range : 0 < lo < 0x7fff *
+ * *
+ * Return Value : *
+ * *
+ * L_div *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x0000 0000 <= L_div <= 0x7fff ffff. *
+ * *
+ * Algorithm: *
+ * *
+ * - find = 1/L_denom. *
+ * First approximation: approx = 1 / denom_hi *
+ * 1/L_denom = approx * (2.0 - L_denom * approx ) *
+ * *
+ * - result = L_num * (1/L_denom) *
+ *****************************************************************************
+*/
+
+Word32 Div_32 (Word32 L_num, Word32 denom)
+{
+ Word16 approx;
+ Word32 L_32;
+ /* First approximation: 1 / L_denom = 1/denom_hi */
+
+ approx = div_s ((Word16) 0x3fff, denom >> 16);
+
+ /* 1/L_denom = approx * (2.0 - L_denom * approx) */
+
+ L_32 = L_mpy_ls (denom, approx);
+
+ L_32 = L_sub ((Word32) 0x7fffffffL, L_32);
+
+ L_32 = L_mpy_ls (L_32, approx);
+ /* L_num * (1/L_denom) */
+
+ L_32 = MULHIGH(L_32, L_num);
+ L_32 = L_shl (L_32, 3);
+
+ return (L_32);
+}
+
+/*!
+
+ \brief calculates the log dualis times 4 of argument
+ iLog4(x) = (Word32)(4 * log(value)/log(2.0))
+
+ \return ilog4 value
+
+*/
+Word16 iLog4(Word32 value)
+{
+ Word16 iLog4;
+
+ if(value != 0){
+ Word32 tmp;
+ Word16 tmp16;
+ iLog4 = norm_l(value);
+ tmp = (value << iLog4);
+ tmp16 = round16(tmp);
+ tmp = L_mult(tmp16, tmp16);
+ tmp16 = round16(tmp);
+ tmp = L_mult(tmp16, tmp16);
+ tmp16 = round16(tmp);
+
+ iLog4 = (-(iLog4 << 2) - norm_s(tmp16)) - 1;
+ }
+ else {
+ iLog4 = -128; /* -(INT_BITS*4); */
+ }
+
+ return iLog4;
+}
+
+#define step(shift) \
+ if ((0x40000000l >> shift) + root <= value) \
+ { \
+ value -= (0x40000000l >> shift) + root; \
+ root = (root >> 1) | (0x40000000l >> shift); \
+ } else { \
+ root = root >> 1; \
+ }
+
+Word32 rsqrt(Word32 value, /*!< Operand to square root (0.0 ... 1) */
+ Word32 accuracy) /*!< Number of valid bits that will be calculated */
+{
+ Word32 root = 0;
+ Word32 scale;
+
+ if(value < 0)
+ return 0;
+
+ scale = norm_l(value);
+ if(scale & 1) scale--;
+
+ value <<= scale;
+
+ step( 0); step( 2); step( 4); step( 6);
+ step( 8); step(10); step(12); step(14);
+ step(16); step(18); step(20); step(22);
+ step(24); step(26); step(28); step(30);
+
+ scale >>= 1;
+ if (root < value)
+ ++root;
+
+ root >>= scale;
+ return root* 46334;
+}
+
+static const Word32 pow2Table[POW2_TABLE_SIZE] = {
+0x7fffffff, 0x7fa765ad, 0x7f4f08ae, 0x7ef6e8da,
+0x7e9f0606, 0x7e476009, 0x7deff6b6, 0x7d98c9e6,
+0x7d41d96e, 0x7ceb2523, 0x7c94acde, 0x7c3e7073,
+0x7be86fb9, 0x7b92aa88, 0x7b3d20b6, 0x7ae7d21a,
+0x7a92be8b, 0x7a3de5df, 0x79e947ef, 0x7994e492,
+0x7940bb9e, 0x78ecccec, 0x78991854, 0x78459dac,
+0x77f25cce, 0x779f5591, 0x774c87cc, 0x76f9f359,
+0x76a7980f, 0x765575c8, 0x76038c5b, 0x75b1dba2,
+0x75606374, 0x750f23ab, 0x74be1c20, 0x746d4cac,
+0x741cb528, 0x73cc556d, 0x737c2d55, 0x732c3cba,
+0x72dc8374, 0x728d015d, 0x723db650, 0x71eea226,
+0x719fc4b9, 0x71511de4, 0x7102ad80, 0x70b47368,
+0x70666f76, 0x7018a185, 0x6fcb096f, 0x6f7da710,
+0x6f307a41, 0x6ee382de, 0x6e96c0c3, 0x6e4a33c9,
+0x6dfddbcc, 0x6db1b8a8, 0x6d65ca38, 0x6d1a1057,
+0x6cce8ae1, 0x6c8339b2, 0x6c381ca6, 0x6bed3398,
+0x6ba27e66, 0x6b57fce9, 0x6b0daeff, 0x6ac39485,
+0x6a79ad56, 0x6a2ff94f, 0x69e6784d, 0x699d2a2c,
+0x69540ec9, 0x690b2601, 0x68c26fb1, 0x6879ebb6,
+0x683199ed, 0x67e97a34, 0x67a18c68, 0x6759d065,
+0x6712460b, 0x66caed35, 0x6683c5c3, 0x663ccf92,
+0x65f60a80, 0x65af766a, 0x6569132f, 0x6522e0ad,
+0x64dcdec3, 0x64970d4f, 0x64516c2e, 0x640bfb41,
+0x63c6ba64, 0x6381a978, 0x633cc85b, 0x62f816eb,
+0x62b39509, 0x626f4292, 0x622b1f66, 0x61e72b65,
+0x61a3666d, 0x615fd05f, 0x611c6919, 0x60d9307b,
+0x60962665, 0x60534ab7, 0x60109d51, 0x5fce1e12,
+0x5f8bccdb, 0x5f49a98c, 0x5f07b405, 0x5ec5ec26,
+0x5e8451d0, 0x5e42e4e3, 0x5e01a540, 0x5dc092c7,
+0x5d7fad59, 0x5d3ef4d7, 0x5cfe6923, 0x5cbe0a1c,
+0x5c7dd7a4, 0x5c3dd19c, 0x5bfdf7e5, 0x5bbe4a61,
+0x5b7ec8f2, 0x5b3f7377, 0x5b0049d4, 0x5ac14bea,
+0x5a82799a, 0x5a43d2c6, 0x5a055751, 0x59c7071c,
+0x5988e209, 0x594ae7fb, 0x590d18d3, 0x58cf7474,
+0x5891fac1, 0x5854ab9b, 0x581786e6, 0x57da8c83,
+0x579dbc57, 0x57611642, 0x57249a29, 0x56e847ef,
+0x56ac1f75, 0x567020a0, 0x56344b52, 0x55f89f70,
+0x55bd1cdb, 0x5581c378, 0x55469329, 0x550b8bd4,
+0x54d0ad5b, 0x5495f7a1, 0x545b6a8b, 0x542105fd,
+0x53e6c9db, 0x53acb607, 0x5372ca68, 0x533906e0,
+0x52ff6b55, 0x52c5f7aa, 0x528cabc3, 0x52538786,
+0x521a8ad7, 0x51e1b59a, 0x51a907b4, 0x5170810b,
+0x51382182, 0x50ffe8fe, 0x50c7d765, 0x508fec9c,
+0x50582888, 0x50208b0e, 0x4fe91413, 0x4fb1c37c,
+0x4f7a9930, 0x4f439514, 0x4f0cb70c, 0x4ed5ff00,
+0x4e9f6cd4, 0x4e69006e, 0x4e32b9b4, 0x4dfc988c,
+0x4dc69cdd, 0x4d90c68b, 0x4d5b157e, 0x4d25899c,
+0x4cf022ca, 0x4cbae0ef, 0x4c85c3f1, 0x4c50cbb8,
+0x4c1bf829, 0x4be7492b, 0x4bb2bea5, 0x4b7e587d,
+0x4b4a169c, 0x4b15f8e6, 0x4ae1ff43, 0x4aae299b,
+0x4a7a77d5, 0x4a46e9d6, 0x4a137f88, 0x49e038d0,
+0x49ad1598, 0x497a15c4, 0x4947393f, 0x49147fee,
+0x48e1e9ba, 0x48af768a, 0x487d2646, 0x484af8d6,
+0x4818ee22, 0x47e70611, 0x47b5408c, 0x47839d7b,
+0x47521cc6, 0x4720be55, 0x46ef8210, 0x46be67e0,
+0x468d6fae, 0x465c9961, 0x462be4e2, 0x45fb521a,
+0x45cae0f2, 0x459a9152, 0x456a6323, 0x453a564d,
+0x450a6abb, 0x44daa054, 0x44aaf702, 0x447b6ead,
+0x444c0740, 0x441cc0a3, 0x43ed9ac0, 0x43be9580,
+0x438fb0cb, 0x4360ec8d, 0x433248ae, 0x4303c517,
+0x42d561b4, 0x42a71e6c, 0x4278fb2b, 0x424af7da,
+0x421d1462, 0x41ef50ae, 0x41c1aca8, 0x41942839,
+0x4166c34c, 0x41397dcc, 0x410c57a2, 0x40df50b8,
+0x40b268fa, 0x4085a051, 0x4058f6a8, 0x402c6be9
+};
+
+/*!
+
+ \brief calculates 2 ^ (x/y) for x<=0, y > 0, x <= 32768 * y
+
+ avoids integer division
+
+ \return
+*/
+Word32 pow2_xy(Word32 x, Word32 y)
+{
+ Word32 iPart;
+ Word32 fPart;
+ Word32 res;
+ Word32 tmp, tmp2;
+ Word32 shift, shift2;
+
+ tmp2 = -x;
+ iPart = tmp2 / y;
+ fPart = tmp2 - iPart*y;
+ iPart = min(iPart,INT_BITS-1);
+
+ res = pow2Table[(POW2_TABLE_SIZE*fPart)/y] >> iPart;
+
+ return(res);
+} \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h
new file mode 100644
index 0000000..4119bc3
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/oper_32b.h
@@ -0,0 +1,89 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: oper_32b.h
+
+ Content: Double precision operations
+
+*******************************************************************************/
+
+#ifndef __OPER_32b_H
+#define __OPER_32b_H
+
+#include "typedef.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define POW2_TABLE_BITS 8
+#define POW2_TABLE_SIZE (1<<POW2_TABLE_BITS)
+
+void L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
+Word32 L_Comp (Word16 hi, Word16 lo);
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
+Word32 Div_32 (Word32 L_num, Word32 denom);
+Word16 iLog4(Word32 value);
+Word32 rsqrt(Word32 value, Word32 accuracy);
+Word32 pow2_xy(Word32 x, Word32 y);
+
+__inline Word32 L_mpy_ls(Word32 L_var2, Word16 var1)
+{
+ unsigned short swLow1;
+ Word16 swHigh1;
+ Word32 l_var_out;
+
+ swLow1 = (unsigned short)(L_var2);
+ swHigh1 = (Word16)(L_var2 >> 16);
+
+ l_var_out = (long)swLow1 * (long)var1 >> 15;
+
+ l_var_out += swHigh1 * var1 << 1;
+
+ return(l_var_out);
+}
+
+__inline Word32 L_mpy_wx(Word32 L_var2, Word16 var1)
+{
+#if ARMV5TE_L_MPY_LS
+ Word32 result;
+ asm volatile(
+ "SMULWB %[result], %[L_var2], %[var1] \n"
+ :[result]"+r"(result)
+ :[L_var2]"r"(L_var2), [var1]"r"(var1)
+ );
+ return result;
+#else
+ unsigned short swLow1;
+ Word16 swHigh1;
+ Word32 l_var_out;
+
+ swLow1 = (unsigned short)(L_var2);
+ swHigh1 = (Word16)(L_var2 >> 16);
+
+ l_var_out = (long)swLow1 * (long)var1 >> 16;
+ l_var_out += swHigh1 * var1;
+
+ return(l_var_out);
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedef.h b/media/libstagefright/codecs/aacenc/basic_op/typedef.h
new file mode 100644
index 0000000..d3a626a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/typedef.h
@@ -0,0 +1,63 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: typedef.h
+
+ Content: type defined for defferent paltform
+
+*******************************************************************************/
+
+#ifndef typedef_h
+#define typedef_h "$Id $"
+
+#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version
+ of typedef.h */
+
+#ifdef ORIGINAL_TYPEDEF_H
+/*
+ * this is the original code from the ETSI file typedef.h
+ */
+
+#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__sun)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__unix__) || defined(__unix)
+typedef signed char Word8;
+typedef short Word16;
+typedef int Word32;
+typedef int Flag;
+
+#endif
+#else /* not original typedef.h */
+
+/*
+ * use (improved) type definition file typdefs.h and add a "Flag" type
+ */
+#include "typedefs.h"
+typedef int Flag;
+
+#endif
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/basic_op/typedefs.h b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h
new file mode 100644
index 0000000..7d16fca
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/basic_op/typedefs.h
@@ -0,0 +1,179 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: typedefs.h
+
+ Content: type defined or const defined
+
+*******************************************************************************/
+
+#ifndef typedefs_h
+#define typedefs_h "$Id $"
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8 /* number of bits in a char */
+#endif
+
+#ifndef VOAAC_SHRT_MAX
+#define VOAAC_SHRT_MAX (32767) /* maximum (signed) short value */
+#endif
+
+#ifndef VOAAC_SHRT_MIN
+#define VOAAC_SHRT_MIN (-32768) /* minimum (signed) short value */
+#endif
+
+/* Define NULL pointer value */
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+#ifndef assert
+#define assert(_Expression) ((void)0)
+#endif
+
+#ifdef LINUX
+#define __inline static __inline__
+#endif
+
+#define INT_BITS 32
+/*
+********************************************************************************
+* DEFINITION OF CONSTANTS
+********************************************************************************
+*/
+/*
+ ********* define char type
+ */
+typedef char Char;
+
+/*
+ ********* define 8 bit signed/unsigned types & constants
+ */
+typedef signed char Word8;
+typedef unsigned char UWord8;
+/*
+ ********* define 16 bit signed/unsigned types & constants
+ */
+typedef short Word16;
+typedef unsigned short UWord16;
+
+/*
+ ********* define 32 bit signed/unsigned types & constants
+ */
+typedef long Word32;
+typedef unsigned long UWord32;
+
+
+
+#ifdef LINUX
+typedef long long Word64;
+typedef unsigned long long UWord64;
+#else
+typedef __int64 Word64;
+typedef unsigned __int64 UWord64;
+#endif
+
+#ifndef min
+#define min(a,b) ( a < b ? a : b)
+#endif
+
+#ifndef max
+#define max(a,b) ( a > b ? a : b)
+#endif
+
+#ifdef ARM_INASM
+#ifdef ARMV5_INASM
+#define ARMV5E_INASM 1
+#endif
+#define ARMV4_INASM 1
+#endif
+
+#if ARMV4_INASM
+ #define ARMV5TE_SAT 1
+ #define ARMV5TE_ADD 1
+ #define ARMV5TE_SUB 1
+ #define ARMV5TE_SHL 1
+ #define ARMV5TE_SHR 1
+ #define ARMV5TE_L_SHL 1
+ #define ARMV5TE_L_SHR 1
+#endif//ARMV4
+#if ARMV5E_INASM
+ #define ARMV5TE_L_ADD 1
+ #define ARMV5TE_L_SUB 1
+ #define ARMV5TE_L_MULT 1
+ #define ARMV5TE_L_MAC 1
+ #define ARMV5TE_L_MSU 1
+
+
+ #define ARMV5TE_DIV_S 1
+ #define ARMV5TE_ROUND 1
+ #define ARMV5TE_MULT 1
+
+ #define ARMV5TE_NORM_S 1
+ #define ARMV5TE_NORM_L 1
+ #define ARMV5TE_L_MPY_LS 1
+#endif
+
+//basic operation functions optimization flags
+#define SATRUATE_IS_INLINE 1 //define saturate as inline function
+#define SHL_IS_INLINE 1 //define shl as inline function
+#define SHR_IS_INLINE 1 //define shr as inline function
+#define L_MULT_IS_INLINE 1 //define L_mult as inline function
+#define L_MSU_IS_INLINE 1 //define L_msu as inline function
+#define L_SUB_IS_INLINE 1 //define L_sub as inline function
+#define L_SHL_IS_INLINE 1 //define L_shl as inline function
+#define L_SHR_IS_INLINE 1 //define L_shr as inline function
+#define ADD_IS_INLINE 1 //define add as inline function //add, inline is the best
+#define SUB_IS_INLINE 1 //define sub as inline function //sub, inline is the best
+#define DIV_S_IS_INLINE 1 //define div_s as inline function
+#define MULT_IS_INLINE 1 //define mult as inline function
+#define NORM_S_IS_INLINE 1 //define norm_s as inline function
+#define NORM_L_IS_INLINE 1 //define norm_l as inline function
+#define ROUND_IS_INLINE 1 //define round as inline function
+#define L_MAC_IS_INLINE 1 //define L_mac as inline function
+#define L_ADD_IS_INLINE 1 //define L_add as inline function
+#define EXTRACT_H_IS_INLINE 1 //define extract_h as inline function
+#define EXTRACT_L_IS_INLINE 1 //define extract_l as inline function //???
+#define MULT_R_IS_INLINE 1 //define mult_r as inline function
+#define SHR_R_IS_INLINE 1 //define shr_r as inline function
+#define MAC_R_IS_INLINE 1 //define mac_r as inline function
+#define MSU_R_IS_INLINE 1 //define msu_r as inline function
+#define L_SHR_R_IS_INLINE 1 //define L_shr_r as inline function
+
+#define PREFIX voAACEnc
+#define LINK0(x, y, z) LINK1(x,y,z)
+#define LINK1(x,y,z) x##y##z
+#define ADD_PREFIX(func) LINK0(PREFIX, _, func)
+
+#define L_Extract ADD_PREFIX(L_Extract)
+#define L_Comp ADD_PREFIX(L_Comp)
+#define Mpy_32 ADD_PREFIX(Mpy_32)
+#define Mpy_32_16 ADD_PREFIX(Mpy_32_16)
+#define Div_32 ADD_PREFIX(Div_32)
+#define iLog4 ADD_PREFIX(iLog4)
+#define rsqrt ADD_PREFIX(rsqrt)
+#define pow2_xy ADD_PREFIX(pow2_xy)
+#define L_mpy_ls ADD_PREFIX(L_mpy_ls)
+#define L_mpy_wx ADD_PREFIX(L_mpy_wx)
+
+#define mem_malloc ADD_PREFIX(mem_malloc)
+#define mem_free ADD_PREFIX(mem_free)
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
new file mode 100644
index 0000000..b4f63af
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/eclair/ARMV5E/Makefile
@@ -0,0 +1,55 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** Licensed under the Apache License, Version 2.0 (the "License");
+#** you may not use this file except in compliance with the License.
+#** You may obtain a copy of the License at
+#**
+#** http://www.apache.org/licenses/LICENSE-2.0
+#**
+#** Unless required by applicable law or agreed to in writing, software
+#** distributed under the License is distributed on an "AS IS" BASIS,
+#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#** See the License for the specific language governing permissions and
+#** limitations under the License.
+#*/
+
+# target6
+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
+VOTT:= v5
+
+
+# module type
+# please specify the type of your module: lib or exe
+VOMT:= lib
+
+
+# module macros
+# please append the additional macro definitions here for your module if necessary.
+# e.g. -DVISUALON, macro VISUALON defined for your module
+VOMM:= -DARMV5E -DARM_INASM -DARMV5_INASM
+
+
+
+# please specify the name of your module
+VOTARGET:=libvoAACEncv5
+
+
+# please modify here to be sure to see the g1.mk
+include ../../../../../Tools/eclair.mk
+
+# dependent libraries.
+VODEPLIBS:=#-ldl -lstdc++
+
+# module source
+# please modify here to be sure to see the ms.mk which specifies all source info of your module
+include ../../ms.mk
+
+
+# please specify where is the voRelease on your PC, relative path is suggested
+VORELDIR:=../../../../../../Release
+
+
+# please modify here to be sure to see the doit.mk
+include ../../../../../Tools/doit.mk
+
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
new file mode 100644
index 0000000..cdce2c1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/eclair/ARMV7/Makefile
@@ -0,0 +1,55 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** Licensed under the Apache License, Version 2.0 (the "License");
+#** you may not use this file except in compliance with the License.
+#** You may obtain a copy of the License at
+#**
+#** http://www.apache.org/licenses/LICENSE-2.0
+#**
+#** Unless required by applicable law or agreed to in writing, software
+#** distributed under the License is distributed on an "AS IS" BASIS,
+#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#** See the License for the specific language governing permissions and
+#** limitations under the License.
+#*/
+
+# target6
+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
+VOTT:= v7
+
+
+# module type
+# please specify the type of your module: lib or exe
+VOMT:= lib
+
+
+# module macros
+# please append the additional macro definitions here for your module if necessary.
+# e.g. -DVISUALON, macro VISUALON defined for your module
+VOMM:= -DARMV5E -DARMV7Neon -DARM_INASM -DARMV5_INASM
+
+
+
+# please specify the name of your module
+VOTARGET:=libvoAACEncv7
+
+
+# please modify here to be sure to see the g1.mk
+include ../../../../../Tools/eclair.mk
+
+# dependent libraries.
+VODEPLIBS:=#-ldl -lstdc++
+
+# module source
+# please modify here to be sure to see the ms.mk which specifies all source info of your module
+include ../../ms.mk
+
+
+# please specify where is the voRelease on your PC, relative path is suggested
+VORELDIR:=../../../../../../Release
+
+
+# please modify here to be sure to see the doit.mk
+include ../../../../../Tools/doit.mk
+
diff --git a/media/libstagefright/codecs/aacenc/build/eclair/makefile b/media/libstagefright/codecs/aacenc/build/eclair/makefile
new file mode 100644
index 0000000..6bb3c13
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/eclair/makefile
@@ -0,0 +1,40 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** Licensed under the Apache License, Version 2.0 (the "License");
+#** you may not use this file except in compliance with the License.
+#** You may obtain a copy of the License at
+#**
+#** http://www.apache.org/licenses/LICENSE-2.0
+#**
+#** Unless required by applicable law or agreed to in writing, software
+#** distributed under the License is distributed on an "AS IS" BASIS,
+#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#** See the License for the specific language governing permissions and
+#** limitations under the License.
+#*/
+
+# Just acting as Father Makefile of Modules
+# please keep the name 'makefile' unchanged
+
+# Module Subdirs
+VOMSD:=$(dir $(shell find . -name 'Makefile'))
+
+all:
+ for dir in $(VOMSD); \
+ do \
+ $(MAKE) -C $$dir; \
+ done
+
+.PHONY:clean devel
+clean:
+ for dir in $(VOMSD); \
+ do \
+ $(MAKE) -C $$dir clean; \
+ done
+
+devel:
+ for dir in $(VOMSD); \
+ do \
+ $(MAKE) -C $$dir devel; \
+ done
diff --git a/media/libstagefright/codecs/aacenc/build/ms.mk b/media/libstagefright/codecs/aacenc/build/ms.mk
new file mode 100644
index 0000000..b67efbc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/build/ms.mk
@@ -0,0 +1,42 @@
+#/*
+#** Copyright 2003-2010, VisualOn, Inc.
+#**
+#** Licensed under the Apache License, Version 2.0 (the "License");
+#** you may not use this file except in compliance with the License.
+#** You may obtain a copy of the License at
+#**
+#** http://www.apache.org/licenses/LICENSE-2.0
+#**
+#** Unless required by applicable law or agreed to in writing, software
+#** distributed under the License is distributed on an "AS IS" BASIS,
+#** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#** See the License for the specific language governing permissions and
+#** limitations under the License.
+#*/
+
+
+# please list all objects needed by your target here
+OBJS:=basicop2.o oper_32b.o aac_rom.o aacenc.o aacenc_core.o adj_thr.o \
+ band_nrg.o bit_cnt.o bitbuffer.o bitenc.o block_switch.o channel_map.o \
+ dyn_bits.o grp_data.o interface.o line_pe.o memalign.o ms_stereo.o \
+ pre_echo_control.o psy_configuration.o psy_main.o qc_main.o quantize.o sf_estim.o \
+ spreading.o stat_bits.o tns.o transform.o
+
+# please list all directories that all source files relative with your module(.h .c .cpp) locate
+VOSRCDIR:=../../../src \
+ ../../../inc \
+ ../../../basic_op\
+ ../../../../../Include
+
+ifeq ($(VOTT), v5)
+OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \
+ PrePostMDCT_v5.o R4R8First_v5.o Radix4FFT_v5.o
+VOSRCDIR+= ../../../src/asm/ARMV5E/
+endif
+
+ifeq ($(VOTT), v7)
+OBJS+= AutoCorrelation_v5.o band_nrg_v5.o CalcWindowEnergy_v5.o \
+ PrePostMDCT_v7.o R4R8First_v7.o Radix4FFT_v7.o
+VOSRCDIR+= ../../../src/asm/ARMV5E/
+VOSRCDIR+= ../../../src/asm/ARMV7/
+endif \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf
new file mode 100644
index 0000000..874d0f7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/doc/voAACEncoderSDK.pdf
Binary files differ
diff --git a/media/libstagefright/codecs/aacenc/inc/aac_rom.h b/media/libstagefright/codecs/aacenc/inc/aac_rom.h
new file mode 100644
index 0000000..b0429fc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/aac_rom.h
@@ -0,0 +1,117 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: aac_rom.h
+
+ Content: constant tables
+
+*******************************************************************************/
+
+#ifndef ROM_H
+#define ROM_H
+
+#include "config.h"
+#include "psy_const.h"
+#include "tns_param.h"
+
+/*
+ mdct
+*/
+extern const int ShortWindowSine[FRAME_LEN_SHORT/2];
+extern const int LongWindowKBD[FRAME_LEN_LONG/2];
+
+extern const unsigned char bitrevTab[17 + 129];
+extern const int cossintab[128 + 1024];
+
+#if defined (ARMV5E) && !defined (ARMV7Neon)
+extern const int twidTab64[(4*6 + 16*6)/2];
+extern const int twidTab512[(8*6 + 32*6 + 128*6)/2];
+#else
+extern const int twidTab64[4*6 + 16*6];
+extern const int twidTab512[8*6 + 32*6 + 128*6];
+#endif
+
+/*
+ form factor
+*/
+extern const Word32 formfac_sqrttable[96];
+
+/*
+ quantizer
+*/
+extern const Word32 mTab_3_4[512];
+extern const Word32 mTab_4_3[512];
+/*! $2^{-\frac{n}{16}}$ table */
+extern const Word16 pow2tominusNover16[17] ;
+
+extern Word32 specExpMantTableComb_enc[4][14];
+extern const UWord8 specExpTableComb_enc[4][14];
+
+extern const Word16 quantBorders[4][4];
+//extern const Word16 quantRecon[3][4];
+extern const Word16 quantRecon[4][3];
+
+/*
+ huffman
+*/
+extern const UWord16 huff_ltab1_2[3][3][3][3];
+extern const UWord16 huff_ltab3_4[3][3][3][3];
+extern const UWord16 huff_ltab5_6[9][9];
+extern const UWord16 huff_ltab7_8[8][8];
+extern const UWord16 huff_ltab9_10[13][13];
+extern const UWord16 huff_ltab11[17][17];
+extern const UWord16 huff_ltabscf[121];
+extern const UWord16 huff_ctab1[3][3][3][3];
+extern const UWord16 huff_ctab2[3][3][3][3];
+extern const UWord16 huff_ctab3[3][3][3][3];
+extern const UWord16 huff_ctab4[3][3][3][3];
+extern const UWord16 huff_ctab5[9][9];
+extern const UWord16 huff_ctab6[9][9];
+extern const UWord16 huff_ctab7[8][8];
+extern const UWord16 huff_ctab8[8][8];
+extern const UWord16 huff_ctab9[13][13];
+extern const UWord16 huff_ctab10[13][13];
+extern const UWord16 huff_ctab11[17][17];
+extern const UWord32 huff_ctabscf[121];
+
+
+
+/*
+ misc
+*/
+extern const int sampRateTab[NUM_SAMPLE_RATES];
+extern const int BandwithCoefTab[8][NUM_SAMPLE_RATES];
+extern const int rates[8];
+extern const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES];
+extern const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES];
+extern const int sfBandTabShortOffset[NUM_SAMPLE_RATES];
+extern const short sfBandTabShort[76];
+extern const int sfBandTabLongOffset[NUM_SAMPLE_RATES];
+extern const short sfBandTabLong[325];
+
+extern const Word32 m_log2_table[INT_BITS];
+
+/*
+ TNS
+*/
+extern const Word32 tnsCoeff3[8];
+extern const Word32 tnsCoeff3Borders[8];
+extern const Word32 tnsCoeff4[16];
+extern const Word32 tnsCoeff4Borders[16];
+extern const Word32 invSBF[24];
+extern const Word16 sideInfoTabLong[MAX_SFB_LONG + 1];
+extern const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1];
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/aacenc_core.h b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h
new file mode 100644
index 0000000..faa1d20
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/aacenc_core.h
@@ -0,0 +1,117 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: aacenc_core.h
+
+ Content: aac encoder interface functions
+
+*******************************************************************************/
+
+#ifndef _aacenc_core_h_
+#define _aacenc_core_h_
+
+
+#include "typedef.h"
+#include "config.h"
+#include "bitenc.h"
+
+#include "psy_configuration.h"
+#include "psy_main.h"
+#include "qc_main.h"
+#include "psy_main.h"
+/*-------------------------- defines --------------------------------------*/
+
+
+/*-------------------- structure definitions ------------------------------*/
+typedef struct {
+ Word32 sampleRate; /* audio file sample rate */
+ Word32 bitRate; /* encoder bit rate in bits/sec */
+ Word16 nChannelsIn; /* number of channels on input (1,2) */
+ Word16 nChannelsOut; /* number of channels on output (1,2) */
+ Word16 bandWidth; /* targeted audio bandwidth in Hz */
+ Word16 adtsUsed; /* whether write adts header */
+} AACENC_CONFIG;
+
+
+typedef struct {
+
+ AACENC_CONFIG config; /* Word16 size: 8 */
+
+ ELEMENT_INFO elInfo; /* Word16 size: 4 */
+
+ QC_STATE qcKernel; /* Word16 size: 6 + 5(PADDING) + 7(ELEMENT_BITS) + 54(ADJ_THR_STATE) = 72 */
+ QC_OUT qcOut; /* Word16 size: MAX_CHANNELS*920(QC_OUT_CHANNEL) + 5(QC_OUT_ELEMENT) + 7 = 932 / 1852 */
+
+ PSY_OUT psyOut; /* Word16 size: MAX_CHANNELS*186 + 2 = 188 / 374 */
+ PSY_KERNEL psyKernel; /* Word16 size: 2587 / 4491 */
+
+ struct BITSTREAMENCODER_INIT bseInit; /* Word16 size: 6 */
+ struct BIT_BUF bitStream; /* Word16 size: 8 */
+ HANDLE_BIT_BUF hBitStream;
+ int initOK;
+
+ short *intbuf;
+ short *encbuf;
+ short *inbuf;
+ int enclen;
+ int inlen;
+ int intlen;
+ int uselength;
+
+ void *hCheck;
+ VO_MEM_OPERATOR *voMemop;
+ VO_MEM_OPERATOR voMemoprator;
+
+}AAC_ENCODER; /* Word16 size: 3809 / 6851 */
+
+/*-----------------------------------------------------------------------------
+
+functionname: AacInitDefaultConfig
+description: gives reasonable default configuration
+returns: ---
+
+------------------------------------------------------------------------------*/
+void AacInitDefaultConfig(AACENC_CONFIG *config);
+
+/*---------------------------------------------------------------------------
+
+functionname:AacEncOpen
+description: allocate and initialize a new encoder instance
+returns: AACENC_OK if success
+
+---------------------------------------------------------------------------*/
+
+Word16 AacEncOpen (AAC_ENCODER *hAacEnc, /* pointer to an encoder handle, initialized on return */
+ const AACENC_CONFIG config); /* pre-initialized config struct */
+
+Word16 AacEncEncode(AAC_ENCODER *hAacEnc,
+ Word16 *timeSignal,
+ const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */
+ Word16 *numAncBytes, /*!< number of ancillary Data Bytes, send as fill element */
+ UWord8 *outBytes, /*!< pointer to output buffer */
+ Word32 *numOutBytes /*!< number of bytes in output buffer */
+ );
+
+/*---------------------------------------------------------------------------
+
+functionname:AacEncClose
+description: deallocate an encoder instance
+
+---------------------------------------------------------------------------*/
+
+void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP); /* an encoder handle */
+
+#endif /* _aacenc_h_ */
diff --git a/media/libstagefright/codecs/aacenc/inc/adj_thr.h b/media/libstagefright/codecs/aacenc/inc/adj_thr.h
new file mode 100644
index 0000000..4057cbe
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/adj_thr.h
@@ -0,0 +1,57 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: adj_thr.h
+
+ Content: Threshold compensation function
+
+*******************************************************************************/
+
+#ifndef __ADJ_THR_H
+#define __ADJ_THR_H
+
+#include "adj_thr_data.h"
+#include "qc_data.h"
+#include "interface.h"
+
+Word16 bits2pe(const Word16 bits);
+
+Word32 AdjThrNew(ADJ_THR_STATE** phAdjThr,
+ Word32 nElements);
+
+void AdjThrDelete(ADJ_THR_STATE *hAdjThr);
+
+void AdjThrInit(ADJ_THR_STATE *hAdjThr,
+ const Word32 peMean,
+ Word32 chBitrate);
+
+void AdjustThresholds(ADJ_THR_STATE *adjThrState,
+ ATS_ELEMENT* AdjThrStateElement,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word16 *chBitDistribution,
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ QC_OUT_ELEMENT* qcOE,
+ ELEMENT_BITS* elBits,
+ const Word16 nChannels,
+ const Word16 maxBitFac);
+
+void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
+ const Word16 dynBitsUsed);
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h b/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h
new file mode 100644
index 0000000..25dd437
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/adj_thr_data.h
@@ -0,0 +1,69 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: adj_thr_data.h
+
+ Content: Threshold compensation parameter
+
+*******************************************************************************/
+
+#ifndef __ADJ_THR_DATA_H
+#define __ADJ_THR_DATA_H
+
+#include "typedef.h"
+#include "psy_const.h"
+#include "line_pe.h"
+
+typedef struct {
+ Word16 clipSaveLow, clipSaveHigh;
+ Word16 minBitSave, maxBitSave;
+ Word16 clipSpendLow, clipSpendHigh;
+ Word16 minBitSpend, maxBitSpend;
+} BRES_PARAM;
+
+typedef struct {
+ UWord8 modifyMinSnr;
+ Word16 startSfbL, startSfbS;
+} AH_PARAM;
+
+typedef struct {
+ Word32 maxRed;
+ Word32 startRatio, maxRatio;
+ Word32 redRatioFac;
+ Word32 redOffs;
+} MINSNR_ADAPT_PARAM;
+
+typedef struct {
+ /* parameters for bitreservoir control */
+ Word16 peMin, peMax;
+ /* constant offset to pe */
+ Word16 peOffset;
+ /* avoid hole parameters */
+ AH_PARAM ahParam;
+ /* paramters for adaptation of minSnr */
+ MINSNR_ADAPT_PARAM minSnrAdaptParam;
+ /* values for correction of pe */
+ Word16 peLast;
+ Word16 dynBitsLast;
+ Word16 peCorrectionFactor;
+} ATS_ELEMENT;
+
+typedef struct {
+ BRES_PARAM bresParamLong, bresParamShort; /* Word16 size: 2*8 */
+ ATS_ELEMENT adjThrStateElem; /* Word16 size: 19 */
+} ADJ_THR_STATE;
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/band_nrg.h b/media/libstagefright/codecs/aacenc/inc/band_nrg.h
new file mode 100644
index 0000000..68509da
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/band_nrg.h
@@ -0,0 +1,46 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: band_nrg.h
+
+ Content: Band/Line energy calculations functions
+
+*******************************************************************************/
+
+
+#ifndef _BAND_NRG_H
+#define _BAND_NRG_H
+
+#include "typedef.h"
+
+
+void CalcBandEnergy(const Word32 *mdctSpectrum,
+ const Word16 *bandOffset,
+ const Word16 numBands,
+ Word32 *bandEnergy,
+ Word32 *bandEnergySum);
+
+
+void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft,
+ const Word32 *mdctSpectrumRight,
+ const Word16 *bandOffset,
+ const Word16 numBands,
+ Word32 *bandEnergyMid,
+ Word32 *bandEnergyMidSum,
+ Word32 *bandEnergySide,
+ Word32 *bandEnergySideSum);
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/bit_cnt.h b/media/libstagefright/codecs/aacenc/inc/bit_cnt.h
new file mode 100644
index 0000000..808319e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/bit_cnt.h
@@ -0,0 +1,106 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bit_cnt.h
+
+ Content: Huffman Bitcounter & coder structure and functions
+
+*******************************************************************************/
+
+#ifndef __BITCOUNT_H
+#define __BITCOUNT_H
+
+#include "bitbuffer.h"
+#include "basic_op.h"
+#define INVALID_BITCOUNT (MAX_16/4)
+
+/*
+ code book number table
+*/
+
+enum codeBookNo{
+ CODE_BOOK_ZERO_NO= 0,
+ CODE_BOOK_1_NO= 1,
+ CODE_BOOK_2_NO= 2,
+ CODE_BOOK_3_NO= 3,
+ CODE_BOOK_4_NO= 4,
+ CODE_BOOK_5_NO= 5,
+ CODE_BOOK_6_NO= 6,
+ CODE_BOOK_7_NO= 7,
+ CODE_BOOK_8_NO= 8,
+ CODE_BOOK_9_NO= 9,
+ CODE_BOOK_10_NO= 10,
+ CODE_BOOK_ESC_NO= 11,
+ CODE_BOOK_RES_NO= 12,
+ CODE_BOOK_PNS_NO= 13
+};
+
+/*
+ code book index table
+*/
+
+enum codeBookNdx{
+ CODE_BOOK_ZERO_NDX=0,
+ CODE_BOOK_1_NDX,
+ CODE_BOOK_2_NDX,
+ CODE_BOOK_3_NDX,
+ CODE_BOOK_4_NDX,
+ CODE_BOOK_5_NDX,
+ CODE_BOOK_6_NDX,
+ CODE_BOOK_7_NDX,
+ CODE_BOOK_8_NDX,
+ CODE_BOOK_9_NDX,
+ CODE_BOOK_10_NDX,
+ CODE_BOOK_ESC_NDX,
+ CODE_BOOK_RES_NDX,
+ CODE_BOOK_PNS_NDX,
+ NUMBER_OF_CODE_BOOKS
+};
+
+/*
+ code book lav table
+*/
+
+enum codeBookLav{
+ CODE_BOOK_ZERO_LAV=0,
+ CODE_BOOK_1_LAV=1,
+ CODE_BOOK_2_LAV=1,
+ CODE_BOOK_3_LAV=2,
+ CODE_BOOK_4_LAV=2,
+ CODE_BOOK_5_LAV=4,
+ CODE_BOOK_6_LAV=4,
+ CODE_BOOK_7_LAV=7,
+ CODE_BOOK_8_LAV=7,
+ CODE_BOOK_9_LAV=12,
+ CODE_BOOK_10_LAV=12,
+ CODE_BOOK_ESC_LAV=16,
+ CODE_BOOK_SCF_LAV=60,
+ CODE_BOOK_PNS_LAV=60
+};
+
+Word16 bitCount(const Word16 *aQuantSpectrum,
+ const Word16 noOfSpecLines,
+ Word16 maxVal,
+ Word16 *bitCountLut);
+
+Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream);
+
+Word16 bitCountScalefactorDelta(Word16 delta);
+Word16 codeScalefactorDelta(Word16 scalefactor, HANDLE_BIT_BUF hBitstream);
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/bitbuffer.h b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h
new file mode 100644
index 0000000..cb850c9
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/bitbuffer.h
@@ -0,0 +1,89 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bitbuffer.h
+
+ Content: Bit Buffer Management structure and functions
+
+*******************************************************************************/
+
+#ifndef BITBUFFER_H
+#define BITBUFFER_H
+
+#include "typedef.h"
+
+
+enum direction
+{
+ forwardDirection,
+ backwardDirection
+};
+
+
+/*!
+ The pointer 'pReadNext' points to the next available word, where bits can be read from. The pointer
+ 'pWriteNext' points to the next available word, where bits can be written to. The pointer pBitBufBase
+ points to the start of the bitstream buffer and the pointer pBitBufEnd points to the end of the bitstream
+ buffer. The two pointers are used as lower-bound respectively upper-bound address for the modulo addressing
+ mode.
+
+ The element cntBits contains the currently available bits in the bit buffer. It will be incremented when
+ bits are written to the bitstream buffer and decremented when bits are read from the bitstream buffer.
+*/
+struct BIT_BUF
+{
+ UWord8 *pBitBufBase; /*!< pointer points to first position in bitstream buffer */
+ UWord8 *pBitBufEnd; /*!< pointer points to last position in bitstream buffer */
+
+ UWord8 *pWriteNext; /*!< pointer points to next available word in bitstream buffer to write */
+
+ UWord32 cache;
+
+ Word16 wBitPos; /*!< 31<=wBitPos<=0*/
+ Word16 cntBits; /*!< number of available bits in the bitstream buffer
+ write bits to bitstream buffer => increment cntBits
+ read bits from bitstream buffer => decrement cntBits */
+ Word16 size; /*!< size of bitbuffer in bits */
+ Word16 isValid; /*!< indicates whether the instance has been initialized */
+}; /* size Word16: 8 */
+
+/*! Define pointer to bit buffer structure */
+typedef struct BIT_BUF *HANDLE_BIT_BUF;
+
+
+HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
+ UWord8 *pBitBufBase,
+ Word16 bitBufSize);
+
+
+void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf);
+
+
+Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf);
+
+
+Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
+ Word32 writeValue,
+ Word16 noBitsToWrite);
+
+void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
+ UWord8 *pBitBufBase,
+ Word16 bitBufSize);
+
+#define GetNrBitsAvailable(hBitBuf) ( (hBitBuf)->cntBits)
+#define GetNrBitsRead(hBitBuf) ((hBitBuf)->size-(hBitBuf)->cntBits)
+
+#endif /* BITBUFFER_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/bitenc.h b/media/libstagefright/codecs/aacenc/inc/bitenc.h
new file mode 100644
index 0000000..1151057
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/bitenc.h
@@ -0,0 +1,50 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bitenc.h
+
+ Content: Bitstream encoder structure and functions
+
+*******************************************************************************/
+
+#ifndef _BITENC_H
+#define _BITENC_H
+
+#include "qc_data.h"
+#include "tns.h"
+#include "channel_map.h"
+#include "interface.h"
+
+struct BITSTREAMENCODER_INIT
+{
+ Word16 nChannels;
+ Word32 bitrate;
+ Word32 sampleRate;
+ Word16 profile;
+};
+
+
+
+Word16 WriteBitstream (HANDLE_BIT_BUF hBitstream,
+ ELEMENT_INFO elInfo,
+ QC_OUT *qcOut,
+ PSY_OUT *psyOut,
+ Word16 *globUsedBits,
+ const UWord8 *ancBytes,
+ Word16 samplerate
+ );
+
+#endif /* _BITENC_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/block_switch.h b/media/libstagefright/codecs/aacenc/inc/block_switch.h
new file mode 100644
index 0000000..3e35819
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/block_switch.h
@@ -0,0 +1,72 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: block_switch.h
+
+ Content: Block switching structure and functions
+
+*******************************************************************************/
+
+#ifndef _BLOCK_SWITCH_H
+#define _BLOCK_SWITCH_H
+
+#include "typedef.h"
+
+
+/****************** Defines ******************************/
+#define BLOCK_SWITCHING_IIR_LEN 2 /* Length of HighPass-FIR-Filter for Attack-Detection */
+#define BLOCK_SWITCH_WINDOWS TRANS_FAC /* number of windows for energy calculation */
+#define BLOCK_SWITCH_WINDOW_LEN FRAME_LEN_SHORT /* minimal granularity of energy calculation */
+
+
+
+/****************** Structures ***************************/
+typedef struct{
+ Word32 invAttackRatio;
+ Word16 windowSequence;
+ Word16 nextwindowSequence;
+ Flag attack;
+ Flag lastattack;
+ Word16 attackIndex;
+ Word16 lastAttackIndex;
+ Word16 noOfGroups;
+ Word16 groupLen[TRANS_FAC];
+ Word32 windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows (last and current) */
+ Word32 windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy in segments (last and current) */
+ Word32 iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */
+ Word32 maxWindowNrg; /* max energy in subwindows */
+ Word32 accWindowNrg; /* recursively accumulated windowNrgF */
+}BLOCK_SWITCHING_CONTROL;
+
+
+
+
+
+Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+ const Word32 bitRate, const Word16 nChannels);
+
+Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+ Word16 *timeSignal,
+ Word32 sampleRate,
+ Word16 chIncrement);
+
+Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
+ BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
+ const Word16 noOfChannels);
+
+
+
+#endif /* #ifndef _BLOCK_SWITCH_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/channel_map.h b/media/libstagefright/codecs/aacenc/inc/channel_map.h
new file mode 100644
index 0000000..e3aa8dc
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/channel_map.h
@@ -0,0 +1,37 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: channel_map.h
+
+ Content: channel mapping functions
+
+*******************************************************************************/
+
+#ifndef _CHANNEL_MAP_H
+#define _CHANNEL_MAP_H
+
+#include "psy_const.h"
+#include "qc_data.h"
+
+Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo);
+
+Word16 InitElementBits(ELEMENT_BITS *elementBits,
+ ELEMENT_INFO elInfo,
+ Word32 bitrateTot,
+ Word16 averageBitsTot,
+ Word16 staticBitsTot);
+
+#endif /* CHANNEL_MAP_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/config.h b/media/libstagefright/codecs/aacenc/inc/config.h
new file mode 100644
index 0000000..6211c8f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/config.h
@@ -0,0 +1,36 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: config.h
+
+ Content: aac encoder parameter
+
+*******************************************************************************/
+
+#ifndef _AACENC_CONFIG_H_
+#define _AACENC_CONFIG_H_
+
+#define MAX_CHANNELS 2
+
+#define AACENC_BLOCKSIZE 1024 /*! encoder only takes BLOCKSIZE samples at a time */
+#define AACENC_TRANS_FAC 8 /*! encoder short long ratio */
+
+
+#define MAXBITS_COEF 6144
+#define MINBITS_COEF 744
+
+
+#endif \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/inc/dyn_bits.h b/media/libstagefright/codecs/aacenc/inc/dyn_bits.h
new file mode 100644
index 0000000..0468fa2
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/dyn_bits.h
@@ -0,0 +1,82 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: dyn_bits.h
+
+ Content: Noiseless coder module structure and functions
+
+*******************************************************************************/
+
+#ifndef __DYN_BITS_H
+#define __DYN_BITS_H
+
+#include "psy_const.h"
+#include "tns.h"
+#include "bit_cnt.h"
+
+
+
+#define MAX_SECTIONS MAX_GROUPED_SFB
+#define SECT_ESC_VAL_LONG 31
+#define SECT_ESC_VAL_SHORT 7
+#define CODE_BOOK_BITS 4
+#define SECT_BITS_LONG 5
+#define SECT_BITS_SHORT 3
+
+typedef struct
+{
+ Word16 codeBook;
+ Word16 sfbStart;
+ Word16 sfbCnt;
+ Word16 sectionBits;
+}
+SECTION_INFO;
+
+
+
+
+typedef struct
+{
+ Word16 blockType;
+ Word16 noOfGroups;
+ Word16 sfbCnt;
+ Word16 maxSfbPerGroup;
+ Word16 sfbPerGroup;
+ Word16 noOfSections;
+ SECTION_INFO sectionInfo[MAX_SECTIONS];
+ Word16 sideInfoBits; /* sectioning bits */
+ Word16 huffmanBits; /* huffman coded bits */
+ Word16 scalefacBits; /* scalefac coded bits */
+ Word16 firstScf; /* first scf to be coded */
+ Word16 bitLookUp[MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1)];
+ Word16 mergeGainLookUp[MAX_SFB_LONG];
+}
+SECTION_DATA; /* Word16 size: 10 + 60(MAX_SECTIONS)*4(SECTION_INFO) + 51(MAX_SFB_LONG)*12(CODE_BOOK_ESC_NDX+1) + 51(MAX_SFB_LONG) = 913 */
+
+
+Word16 BCInit(void);
+
+Word16 dynBitCount(const Word16 *quantSpectrum,
+ const UWord16 *maxValueInSfb,
+ const Word16 *scalefac,
+ const Word16 blockType,
+ const Word16 sfbCnt,
+ const Word16 maxSfbPerGroup,
+ const Word16 sfbPerGroup,
+ const Word16 *sfbOffset,
+ SECTION_DATA *sectionData);
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/grp_data.h b/media/libstagefright/codecs/aacenc/inc/grp_data.h
new file mode 100644
index 0000000..9666577
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/grp_data.h
@@ -0,0 +1,44 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: grp_data.h
+
+ Content: Short block grouping function
+
+*******************************************************************************/
+
+#ifndef __GRP_DATA_H__
+#define __GRP_DATA_H__
+#include "psy_data.h"
+#include "typedefs.h"
+
+void
+groupShortData(Word32 *mdctSpectrum,
+ Word32 *tmpSpectrum,
+ SFB_THRESHOLD *sfbThreshold,
+ SFB_ENERGY *sfbEnergy,
+ SFB_ENERGY *sfbEnergyMS,
+ SFB_ENERGY *sfbSpreadedEnergy,
+ const Word16 sfbCnt,
+ const Word16 *sfbOffset,
+ const Word16 *sfbMinSnr,
+ Word16 *groupedSfbOffset,
+ Word16 *maxSfbPerGroup,
+ Word16 *groupedSfbMinSnr,
+ const Word16 noOfGroups,
+ const Word16 *groupLen);
+
+#endif /* _INTERFACE_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/interface.h b/media/libstagefright/codecs/aacenc/inc/interface.h
new file mode 100644
index 0000000..b84334a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/interface.h
@@ -0,0 +1,106 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: interface.h
+
+ Content: psychoaccoustic/quantizer structures and interface
+
+*******************************************************************************/
+
+#ifndef _INTERFACE_H
+#define _INTERFACE_H
+
+#include "config.h"
+#include "psy_const.h"
+#include "psy_data.h"
+#include "typedefs.h"
+
+
+enum
+{
+ MS_NONE = 0,
+ MS_SOME = 1,
+ MS_ALL = 2
+};
+
+enum
+{
+ MS_ON = 1
+};
+
+struct TOOLSINFO {
+ Word16 msDigest;
+ Word16 msMask[MAX_GROUPED_SFB];
+};
+
+
+typedef struct {
+ Word16 sfbCnt;
+ Word16 sfbPerGroup;
+ Word16 maxSfbPerGroup;
+ Word16 windowSequence;
+ Word16 windowShape;
+ Word16 groupingMask;
+ Word16 sfbOffsets[MAX_GROUPED_SFB+1];
+ Word16 mdctScale;
+ Word32 *sfbEnergy;
+ Word32 *sfbSpreadedEnergy;
+ Word32 *sfbThreshold;
+ Word32 *mdctSpectrum;
+ Word32 sfbEnSumLR;
+ Word32 sfbEnSumMS;
+ Word32 sfbDist[MAX_GROUPED_SFB];
+ Word32 sfbDistNew[MAX_GROUPED_SFB];
+ Word16 sfbMinSnr[MAX_GROUPED_SFB];
+ Word16 minSfMaxQuant[MAX_GROUPED_SFB];
+ Word16 minScfCalculated[MAX_GROUPED_SFB];
+ Word16 prevScfLast[MAX_GROUPED_SFB];
+ Word16 prevScfNext[MAX_GROUPED_SFB];
+ Word16 deltaPeLast[MAX_GROUPED_SFB];
+ TNS_INFO tnsInfo;
+} PSY_OUT_CHANNEL; /* Word16 size: 14 + 60(MAX_GROUPED_SFB) + 112(TNS_INFO) = 186 */
+
+typedef struct {
+ struct TOOLSINFO toolsInfo;
+ Word16 groupedSfbOffset[MAX_CHANNELS][MAX_GROUPED_SFB+1]; /* plus one for last dummy offset ! */
+ Word16 groupedSfbMinSnr[MAX_CHANNELS][MAX_GROUPED_SFB];
+} PSY_OUT_ELEMENT;
+
+typedef struct {
+ /* information shared by both channels */
+ PSY_OUT_ELEMENT psyOutElement;
+ /* information specific to each channel */
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS];
+}PSY_OUT;
+
+void BuildInterface(Word32 *mdctSpectrum,
+ const Word16 mdctScale,
+ SFB_THRESHOLD *sfbThreshold,
+ SFB_ENERGY *sfbEnergy,
+ SFB_ENERGY *sfbSpreadedEnergy,
+ const SFB_ENERGY_SUM sfbEnergySumLR,
+ const SFB_ENERGY_SUM sfbEnergySumMS,
+ const Word16 windowSequence,
+ const Word16 windowShape,
+ const Word16 sfbCnt,
+ const Word16 *sfbOffset,
+ const Word16 maxSfbPerGroup,
+ const Word16 *groupedSfbMinSnr,
+ const Word16 noOfGroups,
+ const Word16 *groupLen,
+ PSY_OUT_CHANNEL *psyOutCh);
+
+#endif /* _INTERFACE_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/line_pe.h b/media/libstagefright/codecs/aacenc/inc/line_pe.h
new file mode 100644
index 0000000..fed938b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/line_pe.h
@@ -0,0 +1,75 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: line_pe.h
+
+ Content: Perceptual entropie module structure and functions
+
+*******************************************************************************/
+
+#ifndef __LINE_PE_H
+#define __LINE_PE_H
+
+
+#include "psy_const.h"
+#include "interface.h"
+
+
+typedef struct {
+ Word16 sfbLdEnergy[MAX_GROUPED_SFB]; /* 4*log(sfbEnergy)/log(2) */
+ Word16 sfbNLines4[MAX_GROUPED_SFB]; /* 4*number of relevant lines in sfb */
+ Word16 sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */
+ Word16 sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */
+ Word16 sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */
+ Word16 pe; /* sum of sfbPe */
+ Word16 constPart; /* sum of sfbConstPart */
+ Word16 nActiveLines; /* sum of sfbNActiveLines */
+} PE_CHANNEL_DATA; /* size Word16: 303 */
+
+
+typedef struct {
+ PE_CHANNEL_DATA peChannelData[MAX_CHANNELS];
+ Word16 pe;
+ Word16 constPart;
+ Word16 nActiveLines;
+ Word16 offset;
+ Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB];
+ Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB];
+ Word32 sfbPeFactors[MAX_CHANNELS][MAX_GROUPED_SFB];
+} PE_DATA; /* size Word16: 303 + 4 + 120 + 240 = 667 */
+
+
+
+
+void prepareSfbPe(PE_DATA *peData,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word16 nChannels,
+ const Word16 peOffset);
+
+
+
+
+
+void calcSfbPe(PE_DATA *peData,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const Word16 nChannels);
+
+
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/memalign.h b/media/libstagefright/codecs/aacenc/inc/memalign.h
new file mode 100644
index 0000000..3b302a7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/memalign.h
@@ -0,0 +1,35 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: memalign.h
+
+ Content: Memory alloc alignments functions
+
+*******************************************************************************/
+
+#ifndef __VO_AACENC_MEM_ALIGN_H__
+#define __VO_AACENC_MEM_ALIGN_H__
+
+#include "voMem.h"
+#include "typedef.h"
+
+extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID);
+extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID);
+
+#endif /* __VO_MEM_ALIGN_H__ */
+
+
+
diff --git a/media/libstagefright/codecs/aacenc/inc/ms_stereo.h b/media/libstagefright/codecs/aacenc/inc/ms_stereo.h
new file mode 100644
index 0000000..6d43dec
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/ms_stereo.h
@@ -0,0 +1,45 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: ms_stereo.h
+
+ Content: Declaration MS stereo processing structure and functions
+
+*******************************************************************************/
+
+#ifndef __MS_STEREO_H__
+#define __MS_STEREO_H__
+#include "typedef.h"
+
+void MsStereoProcessing(Word32 *sfbEnergyLeft,
+ Word32 *sfbEnergyRight,
+ const Word32 *sfbEnergyMid,
+ const Word32 *sfbEnergySide,
+ Word32 *mdctSpectrumLeft,
+ Word32 *mdctSpectrumRight,
+ Word32 *sfbThresholdLeft,
+ Word32 *sfbThresholdRight,
+ Word32 *sfbSpreadedEnLeft,
+ Word32 *sfbSpreadedEnRight,
+ Word16 *msDigest,
+ Word16 *msMask,
+ const Word16 sfbCnt,
+ const Word16 sfbPerGroup,
+ const Word16 maxSfbPerGroup,
+ const Word16 *sfbOffset);
+
+
+#endif
diff --git a/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h b/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h
new file mode 100644
index 0000000..35f36e8
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/pre_echo_control.h
@@ -0,0 +1,42 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: pre_echo_control.h
+
+ Content: Pre echo control functions
+
+*******************************************************************************/
+
+#ifndef __PRE_ECHO_CONTROL_H
+#define __PRE_ECHO_CONTROL_H
+
+#include "typedefs.h"
+
+void InitPreEchoControl(Word32 *pbThresholdnm1,
+ Word16 numPb,
+ Word32 *pbThresholdQuiet);
+
+
+void PreEchoControl(Word32 *pbThresholdNm1,
+ Word16 numPb,
+ Word32 maxAllowedIncreaseFactor,
+ Word16 minRemainingThresholdFactor,
+ Word32 *pbThreshold,
+ Word16 mdctScale,
+ Word16 mdctScalenm1);
+
+#endif
+
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_configuration.h b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h
new file mode 100644
index 0000000..53cf25b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_configuration.h
@@ -0,0 +1,107 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: psy_configuration.h
+
+ Content: Psychoaccoustic configuration structure and functions
+
+*******************************************************************************/
+
+#ifndef _PSY_CONFIGURATION_H
+#define _PSY_CONFIGURATION_H
+
+#include "typedefs.h"
+#include "psy_const.h"
+#include "tns.h"
+
+typedef struct{
+
+ Word16 sfbCnt;
+ Word16 sfbActive; /* number of sf bands containing energy after lowpass */
+ Word16 *sfbOffset;
+
+ Word32 sfbThresholdQuiet[MAX_SFB_LONG];
+
+ Word16 maxAllowedIncreaseFactor; /* preecho control */
+ Word16 minRemainingThresholdFactor;
+
+ Word16 lowpassLine;
+ Word16 sampRateIdx;
+ Word32 clipEnergy; /* for level dependend tmn */
+
+ Word16 ratio;
+ Word16 sfbMaskLowFactor[MAX_SFB_LONG];
+ Word16 sfbMaskHighFactor[MAX_SFB_LONG];
+
+ Word16 sfbMaskLowFactorSprEn[MAX_SFB_LONG];
+ Word16 sfbMaskHighFactorSprEn[MAX_SFB_LONG];
+
+
+ Word16 sfbMinSnr[MAX_SFB_LONG]; /* minimum snr (formerly known as bmax) */
+
+ TNS_CONFIG tnsConf;
+
+}PSY_CONFIGURATION_LONG; /*Word16 size: 8 + 52 + 102 + 51 + 51 + 51 + 51 + 47 = 515 */
+
+
+typedef struct{
+
+ Word16 sfbCnt;
+ Word16 sfbActive; /* number of sf bands containing energy after lowpass */
+ Word16 *sfbOffset;
+
+ Word32 sfbThresholdQuiet[MAX_SFB_SHORT];
+
+ Word16 maxAllowedIncreaseFactor; /* preecho control */
+ Word16 minRemainingThresholdFactor;
+
+ Word16 lowpassLine;
+ Word16 sampRateIdx;
+ Word32 clipEnergy; /* for level dependend tmn */
+
+ Word16 ratio;
+ Word16 sfbMaskLowFactor[MAX_SFB_SHORT];
+ Word16 sfbMaskHighFactor[MAX_SFB_SHORT];
+
+ Word16 sfbMaskLowFactorSprEn[MAX_SFB_SHORT];
+ Word16 sfbMaskHighFactorSprEn[MAX_SFB_SHORT];
+
+
+ Word16 sfbMinSnr[MAX_SFB_SHORT]; /* minimum snr (formerly known as bmax) */
+
+ TNS_CONFIG tnsConf;
+
+}PSY_CONFIGURATION_SHORT; /*Word16 size: 8 + 16 + 16 + 16 + 16 + 16 + 16 + 16 + 47 = 167 */
+
+
+/* Returns the sample rate index */
+Word32 GetSRIndex(Word32 sampleRate);
+
+
+Word16 InitPsyConfigurationLong(Word32 bitrate,
+ Word32 samplerate,
+ Word16 bandwidth,
+ PSY_CONFIGURATION_LONG *psyConf);
+
+Word16 InitPsyConfigurationShort(Word32 bitrate,
+ Word32 samplerate,
+ Word16 bandwidth,
+ PSY_CONFIGURATION_SHORT *psyConf);
+
+#endif /* _PSY_CONFIGURATION_H */
+
+
+
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_const.h b/media/libstagefright/codecs/aacenc/inc/psy_const.h
new file mode 100644
index 0000000..5455ab1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_const.h
@@ -0,0 +1,80 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: psy_const.h
+
+ Content: Global psychoacoustic constants structures
+
+*******************************************************************************/
+
+#ifndef _PSYCONST_H
+#define _PSYCONST_H
+
+#include "config.h"
+
+#define TRUE 1
+#define FALSE 0
+
+#define FRAME_LEN_LONG AACENC_BLOCKSIZE
+#define TRANS_FAC 8
+#define FRAME_LEN_SHORT (FRAME_LEN_LONG/TRANS_FAC)
+
+
+
+/* Block types */
+enum
+{
+ LONG_WINDOW = 0,
+ START_WINDOW,
+ SHORT_WINDOW,
+ STOP_WINDOW
+};
+
+/* Window shapes */
+enum
+{
+ SINE_WINDOW = 0,
+ KBD_WINDOW = 1
+};
+
+/*
+ MS stuff
+*/
+enum
+{
+ SI_MS_MASK_NONE = 0,
+ SI_MS_MASK_SOME = 1,
+ SI_MS_MASK_ALL = 2
+};
+
+#define MAX_NO_OF_GROUPS 4
+#define MAX_SFB_SHORT 15 /* 15 for a memory optimized implementation, maybe 16 for convenient debugging */
+#define MAX_SFB_LONG 51 /* 51 for a memory optimized implementation, maybe 64 for convenient debugging */
+#define MAX_SFB (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG) /* = MAX_SFB_LONG */
+#define MAX_GROUPED_SFB (MAX_NO_OF_GROUPS*MAX_SFB_SHORT > MAX_SFB_LONG ? \
+ MAX_NO_OF_GROUPS*MAX_SFB_SHORT : MAX_SFB_LONG)
+
+#define BLOCK_SWITCHING_OFFSET (1*1024+3*128+64+128)
+#define BLOCK_SWITCHING_DATA_SIZE FRAME_LEN_LONG
+
+#define TRANSFORM_OFFSET_LONG 0
+#define TRANSFORM_OFFSET_SHORT 448
+
+#define LOG_NORM_PCM -15
+
+#define NUM_SAMPLE_RATES 12
+
+#endif /* _PSYCONST_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_data.h b/media/libstagefright/codecs/aacenc/inc/psy_data.h
new file mode 100644
index 0000000..1412d53
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_data.h
@@ -0,0 +1,66 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: psy_data.h
+
+ Content: Psychoacoustic data and structures
+
+*******************************************************************************/
+
+#ifndef _PSY_DATA_H
+#define _PSY_DATA_H
+
+#include "block_switch.h"
+#include "tns.h"
+
+/*
+ the structs can be implemented as unions
+*/
+
+typedef struct{
+ Word32 sfbLong[MAX_GROUPED_SFB];
+ Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT];
+}SFB_THRESHOLD; /* Word16 size: 260 */
+
+typedef struct{
+ Word32 sfbLong[MAX_GROUPED_SFB];
+ Word32 sfbShort[TRANS_FAC][MAX_SFB_SHORT];
+}SFB_ENERGY; /* Word16 size: 260 */
+
+typedef struct{
+ Word32 sfbLong;
+ Word32 sfbShort[TRANS_FAC];
+}SFB_ENERGY_SUM; /* Word16 size: 18 */
+
+
+typedef struct{
+ BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */
+ Word16 *mdctDelayBuffer; /* mdct delay buffer [BLOCK_SWITCHING_OFFSET]*/
+ Word32 sfbThresholdnm1[MAX_SFB]; /* PreEchoControl */
+ Word16 mdctScalenm1; /* scale of last block's mdct (PreEchoControl) */
+
+ SFB_THRESHOLD sfbThreshold; /* adapt */
+ SFB_ENERGY sfbEnergy; /* sfb Energy */
+ SFB_ENERGY sfbEnergyMS;
+ SFB_ENERGY_SUM sfbEnergySum;
+ SFB_ENERGY_SUM sfbEnergySumMS;
+ SFB_ENERGY sfbSpreadedEnergy;
+
+ Word32 *mdctSpectrum; /* mdct spectrum [FRAME_LEN_LONG] */
+ Word16 mdctScale; /* scale of mdct */
+}PSY_DATA; /* Word16 size: 4 + 87 + 102 + 360 + 360 + 360 + 18 + 18 + 360 = 1669 */
+
+#endif /* _PSY_DATA_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/psy_main.h b/media/libstagefright/codecs/aacenc/inc/psy_main.h
new file mode 100644
index 0000000..ab0b8b1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/psy_main.h
@@ -0,0 +1,69 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: psy_main.h
+
+ Content: Psychoacoustic major function block
+
+*******************************************************************************/
+
+#ifndef _PSYMAIN_H
+#define _PSYMAIN_H
+
+#include "psy_configuration.h"
+#include "qc_data.h"
+#include "memalign.h"
+
+/*
+ psy kernel
+*/
+typedef struct {
+ PSY_CONFIGURATION_LONG psyConfLong; /* Word16 size: 515 */
+ PSY_CONFIGURATION_SHORT psyConfShort; /* Word16 size: 167 */
+ PSY_DATA psyData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*1669*/
+ TNS_DATA tnsData[MAX_CHANNELS]; /* Word16 size: MAX_CHANNELS*235 */
+ Word32* pScratchTns;
+ Word16 sampleRateIdx;
+}PSY_KERNEL; /* Word16 size: 2587 / 4491 */
+
+
+Word16 PsyNew( PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP);
+Word16 PsyDelete( PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP);
+
+Word16 PsyOutNew( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP);
+Word16 PsyOutDelete( PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP);
+
+Word16 psyMainInit( PSY_KERNEL *hPsy,
+ Word32 sampleRate,
+ Word32 bitRate,
+ Word16 channels,
+ Word16 tnsMask,
+ Word16 bandwidth);
+
+
+Word16 psyMain(Word16 nChannels, /*!< total number of channels */
+ ELEMENT_INFO *elemInfo,
+ Word16 *timeSignal, /*!< interleaved time signal */
+ PSY_DATA psyData[MAX_CHANNELS],
+ TNS_DATA tnsData[MAX_CHANNELS],
+ PSY_CONFIGURATION_LONG* psyConfLong,
+ PSY_CONFIGURATION_SHORT* psyConfShort,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word32 *pScratchTns,
+ Word32 sampleRate);
+
+#endif /* _PSYMAIN_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/qc_data.h b/media/libstagefright/codecs/aacenc/inc/qc_data.h
new file mode 100644
index 0000000..81d4051
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/qc_data.h
@@ -0,0 +1,143 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: qc_data.h
+
+ Content: Quantizing & coding structures
+
+*******************************************************************************/
+
+#ifndef _QC_DATA_H
+#define _QC_DATA_H
+
+#include "psy_const.h"
+#include "dyn_bits.h"
+#include "adj_thr_data.h"
+
+
+#define MAX_MODES 10
+
+typedef enum {
+ MODE_INVALID = 0,
+ MODE_1, /* mono */
+ MODE_1_1, /* dual mono */
+ MODE_2 /* stereo */
+} ENCODER_MODE;
+
+typedef enum {
+ ID_SCE=0, /* Single Channel Element */
+ ID_CPE=1, /* Channel Pair Element */
+ ID_CCE=2, /* Coupling Channel Element */
+ ID_LFE=3, /* LFE Channel Element */
+ ID_DSE=4, /* current one DSE element for ancillary is supported */
+ ID_PCE=5,
+ ID_FIL=6,
+ ID_END=7
+}ELEMENT_TYPE;
+
+typedef struct {
+ ELEMENT_TYPE elType;
+ Word16 instanceTag;
+ Word16 nChannelsInEl;
+ Word16 ChannelIndex[MAX_CHANNELS];
+} ELEMENT_INFO;
+
+typedef struct {
+ Word32 paddingRest;
+} PADDING;
+
+
+/* Quantizing & coding stage */
+
+struct QC_INIT{
+ ELEMENT_INFO *elInfo;
+ Word16 maxBits; /* maximum number of bits in reservoir */
+ Word16 averageBits; /* average number of bits we should use */
+ Word16 bitRes;
+ Word16 meanPe;
+ Word32 chBitrate;
+ Word16 maxBitFac;
+ Word32 bitrate;
+
+ PADDING padding;
+};
+
+typedef struct
+{
+ Word16 *quantSpec; /* [FRAME_LEN_LONG]; */
+ UWord16 *maxValueInSfb; /* [MAX_GROUPED_SFB]; */
+ Word16 *scf; /* [MAX_GROUPED_SFB]; */
+ Word16 globalGain;
+ Word16 mdctScale;
+ Word16 groupingMask;
+ SECTION_DATA sectionData;
+ Word16 windowShape;
+} QC_OUT_CHANNEL;
+
+typedef struct
+{
+ Word16 adtsUsed;
+ Word16 staticBitsUsed; /* for verification purposes */
+ Word16 dynBitsUsed; /* for verification purposes */
+ Word16 pe;
+ Word16 ancBitsUsed;
+ Word16 fillBits;
+} QC_OUT_ELEMENT;
+
+typedef struct
+{
+ QC_OUT_CHANNEL qcChannel[MAX_CHANNELS];
+ QC_OUT_ELEMENT qcElement;
+ Word16 totStaticBitsUsed; /* for verification purposes */
+ Word16 totDynBitsUsed; /* for verification purposes */
+ Word16 totAncBitsUsed; /* for verification purposes */
+ Word16 totFillBits;
+ Word16 alignBits;
+ Word16 bitResTot;
+ Word16 averageBitsTot;
+} QC_OUT;
+
+typedef struct {
+ Word32 chBitrate;
+ Word16 averageBits; /* brutto -> look ancillary.h */
+ Word16 maxBits;
+ Word16 bitResLevel;
+ Word16 maxBitResBits;
+ Word16 relativeBits; /* Bits relative to total Bits scaled down by 2 */
+} ELEMENT_BITS;
+
+typedef struct
+{
+ /* this is basically struct QC_INIT */
+ Word16 averageBitsTot;
+ Word16 maxBitsTot;
+ Word16 globStatBits;
+ Word16 nChannels;
+ Word16 bitResTot;
+
+ Word16 maxBitFac;
+
+ PADDING padding;
+
+ ELEMENT_BITS elementBits;
+ ADJ_THR_STATE adjThr;
+
+ Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB];
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB];
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB];
+} QC_STATE;
+
+#endif /* _QC_DATA_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/qc_main.h b/media/libstagefright/codecs/aacenc/inc/qc_main.h
new file mode 100644
index 0000000..e1138b2
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/qc_main.h
@@ -0,0 +1,64 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: qc_main.h
+
+ Content: Quantizing & coding functions
+
+*******************************************************************************/
+
+#ifndef _QC_MAIN_H
+#define _QC_MAIN_H
+
+#include "qc_data.h"
+#include "interface.h"
+#include "memalign.h"
+
+/* Quantizing & coding stage */
+
+Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP);
+
+void QCOutDelete(QC_OUT *hQC, VO_MEM_OPERATOR *pMemOP);
+
+Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP);
+
+Word16 QCInit(QC_STATE *hQC,
+ struct QC_INIT *init);
+
+void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP);
+
+
+Word16 QCMain(QC_STATE *hQC,
+ ELEMENT_BITS* elBits,
+ ATS_ELEMENT* adjThrStateElement,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */
+ PSY_OUT_ELEMENT* psyOutElement,
+ QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], /* out */
+ QC_OUT_ELEMENT* qcOutElement,
+ Word16 nChannels,
+ Word16 ancillaryDataBytes); /* returns error code */
+
+void updateBitres(QC_STATE* qcKernel,
+ QC_OUT* qcOut);
+
+Word16 FinalizeBitConsumption(QC_STATE *hQC,
+ QC_OUT* qcOut);
+
+Word16 AdjustBitrate(QC_STATE *hQC,
+ Word32 bitRate,
+ Word32 sampleRate);
+
+#endif /* _QC_MAIN_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/quantize.h b/media/libstagefright/codecs/aacenc/inc/quantize.h
new file mode 100644
index 0000000..88a95e1
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/quantize.h
@@ -0,0 +1,42 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: quantize.h
+
+ Content: Quantization functions
+
+*******************************************************************************/
+
+#ifndef _QUANTIZE_H_
+#define _QUANTIZE_H_
+#include "typedefs.h"
+
+/* quantizing */
+
+#define MAX_QUANT 8191
+
+void QuantizeSpectrum(Word16 sfbCnt,
+ Word16 maxSfbPerGroup,
+ Word16 sfbPerGroup,
+ Word16 *sfbOffset, Word32 *mdctSpectrum,
+ Word16 globalGain, Word16 *scalefactors,
+ Word16 *quantizedSpectrum);
+
+Word32 calcSfbDist(const Word32 *spec,
+ Word16 sfbWidth,
+ Word16 gain);
+
+#endif /* _QUANTIZE_H_ */
diff --git a/media/libstagefright/codecs/aacenc/inc/sf_estim.h b/media/libstagefright/codecs/aacenc/inc/sf_estim.h
new file mode 100644
index 0000000..b25ec3c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/sf_estim.h
@@ -0,0 +1,46 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: sf_estim.h
+
+ Content: Scale factor estimation functions
+
+*******************************************************************************/
+
+#ifndef __SF_ESTIM_H__
+#define __SF_ESTIM_H__
+/*
+ Scale factor estimation
+ */
+#include "psy_const.h"
+#include "interface.h"
+#include "qc_data.h"
+
+void
+CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const Word16 nChannels);
+
+void
+EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word16 nChannels);
+#endif \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/inc/spreading.h b/media/libstagefright/codecs/aacenc/inc/spreading.h
new file mode 100644
index 0000000..29cf63d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/spreading.h
@@ -0,0 +1,33 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: spreading.h
+
+ Content: Spreading of energy functions
+
+*******************************************************************************/
+
+#ifndef _SPREADING_H
+#define _SPREADING_H
+#include "typedefs.h"
+
+
+void SpreadingMax(const Word16 pbCnt,
+ const Word16 *maskLowFactor,
+ const Word16 *maskHighFactor,
+ Word32 *pbSpreadedEnergy);
+
+#endif /* #ifndef _SPREADING_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/stat_bits.h b/media/libstagefright/codecs/aacenc/inc/stat_bits.h
new file mode 100644
index 0000000..6e90b9c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/stat_bits.h
@@ -0,0 +1,34 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: stat_bits.h
+
+ Content: Static bit counter functions
+
+*******************************************************************************/
+
+#ifndef __STAT_BITS_H
+#define __STAT_BITS_H
+
+#include "psy_const.h"
+#include "interface.h"
+
+Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word16 nChannels,
+ Word16 adtsUsed);
+
+#endif /* __STAT_BITS_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/tns.h b/media/libstagefright/codecs/aacenc/inc/tns.h
new file mode 100644
index 0000000..9ffcce9
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/tns.h
@@ -0,0 +1,108 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: tns.h
+
+ Content: TNS structures
+
+*******************************************************************************/
+
+#ifndef _TNS_H
+#define _TNS_H
+
+#include "typedef.h"
+#include "psy_const.h"
+
+
+
+#define TNS_MAX_ORDER 12
+#define TNS_MAX_ORDER_SHORT 5
+
+#define FILTER_DIRECTION 0
+
+typedef struct{ /*stuff that is tabulated dependent on bitrate etc. */
+ Word16 threshOn; /* min. prediction gain for using tns TABUL * 100*/
+ Word32 lpcStartFreq; /* lowest freq for lpc TABUL*/
+ Word32 lpcStopFreq; /* TABUL */
+ Word32 tnsTimeResolution;
+}TNS_CONFIG_TABULATED;
+
+
+typedef struct { /*assigned at InitTime*/
+ Word16 tnsActive;
+ Word16 tnsMaxSfb;
+
+ Word16 maxOrder; /* max. order of tns filter */
+ Word16 tnsStartFreq; /* lowest freq. for tns filtering */
+ Word16 coefRes;
+
+ TNS_CONFIG_TABULATED confTab;
+
+ Word32 acfWindow[TNS_MAX_ORDER+1];
+
+ Word16 tnsStartBand;
+ Word16 tnsStartLine;
+
+ Word16 tnsStopBand;
+ Word16 tnsStopLine;
+
+ Word16 lpcStartBand;
+ Word16 lpcStartLine;
+
+ Word16 lpcStopBand;
+ Word16 lpcStopLine;
+
+ Word16 tnsRatioPatchLowestCb;
+ Word16 tnsModifyBeginCb;
+
+ Word16 threshold; /* min. prediction gain for using tns TABUL * 100 */
+
+}TNS_CONFIG;
+
+
+typedef struct {
+ Word16 tnsActive;
+ Word32 parcor[TNS_MAX_ORDER];
+ Word16 predictionGain;
+} TNS_SUBBLOCK_INFO; /* Word16 size: 26 */
+
+typedef struct{
+ TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC];
+} TNS_DATA_SHORT;
+
+typedef struct{
+ TNS_SUBBLOCK_INFO subBlockInfo;
+} TNS_DATA_LONG;
+
+typedef struct{
+ TNS_DATA_LONG tnsLong;
+ TNS_DATA_SHORT tnsShort;
+}TNS_DATA_RAW;
+
+typedef struct{
+ Word16 numOfSubblocks;
+ TNS_DATA_RAW dataRaw;
+}TNS_DATA; /* Word16 size: 1 + 8*26 + 26 = 235 */
+
+typedef struct{
+ Word16 tnsActive[TRANS_FAC];
+ Word16 coefRes[TRANS_FAC];
+ Word16 length[TRANS_FAC];
+ Word16 order[TRANS_FAC];
+ Word16 coef[TRANS_FAC*TNS_MAX_ORDER_SHORT];
+}TNS_INFO; /* Word16 size: 72 */
+
+#endif /* _TNS_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/tns_func.h b/media/libstagefright/codecs/aacenc/inc/tns_func.h
new file mode 100644
index 0000000..58b75b6
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/tns_func.h
@@ -0,0 +1,75 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: tns_func.h
+
+ Content: TNS functions
+
+*******************************************************************************/
+
+/*
+ Temporal noise shaping
+ */
+#ifndef _TNS_FUNC_H
+#define _TNS_FUNC_H
+#include "typedef.h"
+#include "psy_configuration.h"
+
+Word16 InitTnsConfigurationLong(Word32 bitrate,
+ Word32 samplerate,
+ Word16 channels,
+ TNS_CONFIG *tnsConfig,
+ PSY_CONFIGURATION_LONG *psyConfig,
+ Word16 active);
+
+Word16 InitTnsConfigurationShort(Word32 bitrate,
+ Word32 samplerate,
+ Word16 channels,
+ TNS_CONFIG *tnsConfig,
+ PSY_CONFIGURATION_SHORT *psyConfig,
+ Word16 active);
+
+Word32 TnsDetect(TNS_DATA* tnsData,
+ TNS_CONFIG tC,
+ Word32* pScratchTns,
+ const Word16 sfbOffset[],
+ Word32* spectrum,
+ Word16 subBlockNumber,
+ Word16 blockType,
+ Word32 * sfbEnergy);
+
+void TnsSync(TNS_DATA *tnsDataDest,
+ const TNS_DATA *tnsDataSrc,
+ const TNS_CONFIG tC,
+ const Word16 subBlockNumber,
+ const Word16 blockType);
+
+Word16 TnsEncode(TNS_INFO* tnsInfo,
+ TNS_DATA* tnsData,
+ Word16 numOfSfb,
+ TNS_CONFIG tC,
+ Word16 lowPassLine,
+ Word32* spectrum,
+ Word16 subBlockNumber,
+ Word16 blockType);
+
+void ApplyTnsMultTableToRatios(Word16 startCb,
+ Word16 stopCb,
+ TNS_SUBBLOCK_INFO subInfo,
+ Word32 *thresholds);
+
+
+#endif /* _TNS_FUNC_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/tns_param.h b/media/libstagefright/codecs/aacenc/inc/tns_param.h
new file mode 100644
index 0000000..26266ac
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/tns_param.h
@@ -0,0 +1,52 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: tns_param.h
+
+ Content: TNS parameters
+
+*******************************************************************************/
+
+/*
+ TNS parameters
+ */
+#ifndef _TNS_PARAM_H
+#define _TNS_PARAM_H
+
+#include "tns.h"
+
+typedef struct{
+ Word32 samplingRate;
+ Word16 maxBandLong;
+ Word16 maxBandShort;
+}TNS_MAX_TAB_ENTRY;
+
+typedef struct{
+ Word32 bitRateFrom;
+ Word32 bitRateTo;
+ const TNS_CONFIG_TABULATED *paramMono_Long; /* contains TNS parameters */
+ const TNS_CONFIG_TABULATED *paramMono_Short;
+ const TNS_CONFIG_TABULATED *paramStereo_Long;
+ const TNS_CONFIG_TABULATED *paramStereo_Short;
+}TNS_INFO_TAB;
+
+
+void GetTnsParam(TNS_CONFIG_TABULATED *tnsConfigTab,
+ Word32 bitRate, Word16 channels, Word16 blockType);
+
+void GetTnsMaxBands(Word32 samplingRate, Word16 blockType, Word16* tnsMaxSfb);
+
+#endif /* _TNS_PARAM_H */
diff --git a/media/libstagefright/codecs/aacenc/inc/transform.h b/media/libstagefright/codecs/aacenc/inc/transform.h
new file mode 100644
index 0000000..2666914
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/inc/transform.h
@@ -0,0 +1,36 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: transform.h
+
+ Content: MDCT Transform functions
+
+*******************************************************************************/
+
+#ifndef __TRANSFORM_H__
+#define __TRANSFORM_H__
+
+#include "typedef.h"
+
+void Transform_Real(Word16 *mdctDelayBuffer,
+ Word16 *timeSignal,
+ Word16 chIncrement, /*! channel increment */
+ Word32 *realOut,
+ Word16 *mdctScale,
+ Word16 windowSequence
+ );
+
+#endif \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/patent_disclaimer.txt b/media/libstagefright/codecs/aacenc/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/patent_disclaimer.txt
@@ -0,0 +1,9 @@
+
+THIS IS NOT A GRANT OF PATENT RIGHTS.
+
+Google makes no representation or warranty that the codecs for which
+source code is made available hereunder are unencumbered by
+third-party patents. Those intending to use this source code in
+hardware or software products are advised that implementations of
+these codecs, including in open source software or shareware, may
+require patent licenses from the relevant patent holders.
diff --git a/media/libstagefright/codecs/aacenc/src/aac_rom.c b/media/libstagefright/codecs/aacenc/src/aac_rom.c
new file mode 100644
index 0000000..2ce0352
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/aac_rom.c
@@ -0,0 +1,2363 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: aac_rom.c
+
+ Content: constant tables
+
+*******************************************************************************/
+
+#include "aac_rom.h"
+
+#if defined (ARMV5E) && !defined (ARMV7Neon)
+
+/*
+ * Q30 for 128 and 1024
+ *
+ * for (i = 0; i < num/4; i++) {
+ * angle = (i + 0.125) * M_PI / num;
+ * x = cos(angle) * (1 << 30);
+ * x = sin(angle) * (1 << 30);
+ *
+ * angle = (num/2 - 1 - i + 0.125) * M_PI / num;
+ * x = cos(angle) * (1 << 30);
+ * x = sin(angle) * (1 << 30);
+ * }
+ */
+const int cossintab[128 + 1024] = {
+ /* 128 */
+ 0x3fffec43, 0x003243f1, 0x015fd4d2, 0x3ffc38d1, 0x3ff9c13a, 0x01c454f5, 0x02f1b755, 0x3feea776,
+ 0x3fe9b8a9, 0x03562038, 0x0483259d, 0x3fd73a4a, 0x3fcfd50b, 0x04e767c5, 0x0613e1c5, 0x3fb5f4ea,
+ 0x3fac1a5b, 0x0677edbb, 0x07a3adff, 0x3f8adc77, 0x3f7e8e1e, 0x08077457, 0x09324ca7, 0x3f55f796,
+ 0x3f473759, 0x0995bdfd, 0x0abf8043, 0x3f174e70, 0x3f061e95, 0x0b228d42, 0x0c4b0b94, 0x3eceeaad,
+ 0x3ebb4ddb, 0x0cada4f5, 0x0dd4b19a, 0x3e7cd778, 0x3e66d0b4, 0x0e36c82a, 0x0f5c35a3, 0x3e212179,
+ 0x3e08b42a, 0x0fbdba40, 0x10e15b4e, 0x3dbbd6d4, 0x3da106bd, 0x11423ef0, 0x1263e699, 0x3d4d0728,
+ 0x3d2fd86c, 0x12c41a4f, 0x13e39be9, 0x3cd4c38b, 0x3cb53aaa, 0x144310dd, 0x15604013, 0x3c531e88,
+ 0x3c314060, 0x15bee78c, 0x16d99864, 0x3bc82c1f, 0x3ba3fde7, 0x173763c9, 0x184f6aab, 0x3b3401bb,
+ 0x3b0d8909, 0x18ac4b87, 0x19c17d44, 0x3a96b636, 0x3a6df8f8, 0x1a1d6544, 0x1b2f971e, 0x39f061d2,
+ 0x39c5664f, 0x1b8a7815, 0x1c997fc4, 0x39411e33, 0x3913eb0e, 0x1cf34baf, 0x1dfeff67, 0x38890663,
+ 0x3859a292, 0x1e57a86d, 0x1f5fdee6, 0x37c836c2, 0x3796a996, 0x1fb7575c, 0x20bbe7d8, 0x36fecd0e,
+ 0x36cb1e2a, 0x21122240, 0x2212e492, 0x362ce855, 0x35f71fb1, 0x2267d3a0, 0x2364a02e, 0x3552a8f4,
+ 0x351acedd, 0x23b836ca, 0x24b0e699, 0x34703095, 0x34364da6, 0x250317df, 0x25f78497, 0x3385a222,
+ 0x3349bf48, 0x264843d9, 0x273847c8, 0x329321c7, 0x32554840, 0x27878893, 0x2872feb6, 0x3198d4ea,
+ 0x31590e3e, 0x28c0b4d2, 0x29a778db, 0x3096e223, 0x30553828, 0x29f3984c, 0x2ad586a3, 0x2f8d713a,
+ 0x2f49ee0f, 0x2b2003ac, 0x2bfcf97c, 0x2e7cab1c, 0x2e37592c, 0x2c45c8a0, 0x2d1da3d5, 0x2d64b9da,
+ /* 1024 */
+ 0x3fffffb1, 0x0006487f, 0x002bfb74, 0x3ffff0e3, 0x3fffe705, 0x00388c6e, 0x005e3f4c, 0x3fffba9b,
+ 0x3fffa6de, 0x006ad03b, 0x009082ea, 0x3fff5cd8, 0x3fff3f3c, 0x009d13c5, 0x00c2c62f, 0x3ffed79b,
+ 0x3ffeb021, 0x00cf56ef, 0x00f508fc, 0x3ffe2ae5, 0x3ffdf98c, 0x01019998, 0x01274b31, 0x3ffd56b5,
+ 0x3ffd1b7e, 0x0133dba3, 0x01598cb1, 0x3ffc5b0c, 0x3ffc15f7, 0x01661cf0, 0x018bcd5b, 0x3ffb37ec,
+ 0x3ffae8f9, 0x01985d60, 0x01be0d11, 0x3ff9ed53, 0x3ff99483, 0x01ca9cd4, 0x01f04bb4, 0x3ff87b44,
+ 0x3ff81896, 0x01fcdb2e, 0x02228924, 0x3ff6e1bf, 0x3ff67534, 0x022f184d, 0x0254c544, 0x3ff520c5,
+ 0x3ff4aa5d, 0x02615414, 0x0286fff3, 0x3ff33858, 0x3ff2b813, 0x02938e62, 0x02b93914, 0x3ff12878,
+ 0x3ff09e56, 0x02c5c71a, 0x02eb7086, 0x3feef126, 0x3fee5d28, 0x02f7fe1c, 0x031da62b, 0x3fec9265,
+ 0x3febf48b, 0x032a3349, 0x034fd9e5, 0x3fea0c35, 0x3fe96480, 0x035c6682, 0x03820b93, 0x3fe75e98,
+ 0x3fe6ad08, 0x038e97a9, 0x03b43b17, 0x3fe48990, 0x3fe3ce26, 0x03c0c69e, 0x03e66852, 0x3fe18d1f,
+ 0x3fe0c7da, 0x03f2f342, 0x04189326, 0x3fde6945, 0x3fdd9a27, 0x04251d77, 0x044abb73, 0x3fdb1e06,
+ 0x3fda450f, 0x0457451d, 0x047ce11a, 0x3fd7ab64, 0x3fd6c894, 0x04896a16, 0x04af03fc, 0x3fd4115f,
+ 0x3fd324b7, 0x04bb8c42, 0x04e123fa, 0x3fd04ffc, 0x3fcf597c, 0x04edab83, 0x051340f6, 0x3fcc673b,
+ 0x3fcb66e4, 0x051fc7b9, 0x05455ad1, 0x3fc8571f, 0x3fc74cf3, 0x0551e0c7, 0x0577716b, 0x3fc41fac,
+ 0x3fc30baa, 0x0583f68c, 0x05a984a6, 0x3fbfc0e3, 0x3fbea30c, 0x05b608eb, 0x05db9463, 0x3fbb3ac7,
+ 0x3fba131b, 0x05e817c3, 0x060da083, 0x3fb68d5b, 0x3fb55bdc, 0x061a22f7, 0x063fa8e7, 0x3fb1b8a2,
+ 0x3fb07d50, 0x064c2a67, 0x0671ad71, 0x3facbc9f, 0x3fab777b, 0x067e2df5, 0x06a3ae00, 0x3fa79954,
+ 0x3fa64a5f, 0x06b02d81, 0x06d5aa77, 0x3fa24ec6, 0x3fa0f600, 0x06e228ee, 0x0707a2b7, 0x3f9cdcf7,
+ 0x3f9b7a62, 0x0714201b, 0x073996a1, 0x3f9743eb, 0x3f95d787, 0x074612eb, 0x076b8616, 0x3f9183a5,
+ 0x3f900d72, 0x0778013d, 0x079d70f7, 0x3f8b9c28, 0x3f8a1c29, 0x07a9eaf5, 0x07cf5726, 0x3f858d79,
+ 0x3f8403ae, 0x07dbcff2, 0x08013883, 0x3f7f579b, 0x3f7dc405, 0x080db016, 0x083314f1, 0x3f78fa92,
+ 0x3f775d31, 0x083f8b43, 0x0864ec4f, 0x3f727661, 0x3f70cf38, 0x08716159, 0x0896be80, 0x3f6bcb0e,
+ 0x3f6a1a1c, 0x08a3323a, 0x08c88b65, 0x3f64f89b, 0x3f633de2, 0x08d4fdc6, 0x08fa52de, 0x3f5dff0e,
+ 0x3f5c3a8f, 0x0906c3e0, 0x092c14ce, 0x3f56de6a, 0x3f551026, 0x09388469, 0x095dd116, 0x3f4f96b4,
+ 0x3f4dbeac, 0x096a3f42, 0x098f8796, 0x3f4827f0, 0x3f464626, 0x099bf44c, 0x09c13831, 0x3f409223,
+ 0x3f3ea697, 0x09cda368, 0x09f2e2c7, 0x3f38d552, 0x3f36e006, 0x09ff4c78, 0x0a24873a, 0x3f30f181,
+ 0x3f2ef276, 0x0a30ef5e, 0x0a56256c, 0x3f28e6b6, 0x3f26ddec, 0x0a628bfa, 0x0a87bd3d, 0x3f20b4f5,
+ 0x3f1ea26e, 0x0a94222f, 0x0ab94e8f, 0x3f185c43, 0x3f164001, 0x0ac5b1dc, 0x0aead944, 0x3f0fdca5,
+ 0x3f0db6a9, 0x0af73ae5, 0x0b1c5d3d, 0x3f073621, 0x3f05066d, 0x0b28bd2a, 0x0b4dda5c, 0x3efe68bc,
+ 0x3efc2f50, 0x0b5a388d, 0x0b7f5081, 0x3ef5747b, 0x3ef3315a, 0x0b8bacf0, 0x0bb0bf8f, 0x3eec5965,
+ 0x3eea0c8e, 0x0bbd1a33, 0x0be22766, 0x3ee3177e, 0x3ee0c0f4, 0x0bee8038, 0x0c1387e9, 0x3ed9aecc,
+ 0x3ed74e91, 0x0c1fdee1, 0x0c44e0f9, 0x3ed01f55, 0x3ecdb56a, 0x0c513610, 0x0c763278, 0x3ec66920,
+ 0x3ec3f585, 0x0c8285a5, 0x0ca77c47, 0x3ebc8c31, 0x3eba0ee9, 0x0cb3cd84, 0x0cd8be47, 0x3eb2888f,
+ 0x3eb0019c, 0x0ce50d8c, 0x0d09f85b, 0x3ea85e41, 0x3ea5cda3, 0x0d1645a0, 0x0d3b2a64, 0x3e9e0d4c,
+ 0x3e9b7306, 0x0d4775a1, 0x0d6c5443, 0x3e9395b7, 0x3e90f1ca, 0x0d789d71, 0x0d9d75db, 0x3e88f788,
+ 0x3e8649f5, 0x0da9bcf2, 0x0dce8f0d, 0x3e7e32c6, 0x3e7b7b90, 0x0ddad406, 0x0dff9fba, 0x3e734778,
+ 0x3e70869f, 0x0e0be28e, 0x0e30a7c5, 0x3e6835a4, 0x3e656b2b, 0x0e3ce86b, 0x0e61a70f, 0x3e5cfd51,
+ 0x3e5a2939, 0x0e6de580, 0x0e929d7a, 0x3e519e86, 0x3e4ec0d1, 0x0e9ed9af, 0x0ec38ae8, 0x3e46194a,
+ 0x3e4331fa, 0x0ecfc4d9, 0x0ef46f3b, 0x3e3a6da4, 0x3e377cbb, 0x0f00a6df, 0x0f254a53, 0x3e2e9b9c,
+ 0x3e2ba11b, 0x0f317fa5, 0x0f561c15, 0x3e22a338, 0x3e1f9f21, 0x0f624f0c, 0x0f86e460, 0x3e168480,
+ 0x3e1376d5, 0x0f9314f5, 0x0fb7a317, 0x3e0a3f7b, 0x3e07283f, 0x0fc3d143, 0x0fe8581d, 0x3dfdd432,
+ 0x3dfab365, 0x0ff483d7, 0x10190352, 0x3df142ab, 0x3dee1851, 0x10252c94, 0x1049a49a, 0x3de48aef,
+ 0x3de15708, 0x1055cb5b, 0x107a3bd5, 0x3dd7ad05, 0x3dd46f94, 0x1086600e, 0x10aac8e6, 0x3dcaa8f5,
+ 0x3dc761fc, 0x10b6ea90, 0x10db4baf, 0x3dbd7ec7, 0x3dba2e48, 0x10e76ac3, 0x110bc413, 0x3db02e84,
+ 0x3dacd481, 0x1117e088, 0x113c31f3, 0x3da2b834, 0x3d9f54af, 0x11484bc2, 0x116c9531, 0x3d951bde,
+ 0x3d91aed9, 0x1178ac53, 0x119cedaf, 0x3d87598c, 0x3d83e309, 0x11a9021d, 0x11cd3b50, 0x3d797145,
+ 0x3d75f147, 0x11d94d02, 0x11fd7df6, 0x3d6b6313, 0x3d67d99b, 0x12098ce5, 0x122db583, 0x3d5d2efe,
+ 0x3d599c0e, 0x1239c1a7, 0x125de1da, 0x3d4ed50f, 0x3d4b38aa, 0x1269eb2b, 0x128e02dc, 0x3d40554e,
+ 0x3d3caf76, 0x129a0954, 0x12be186c, 0x3d31afc5, 0x3d2e007c, 0x12ca1c03, 0x12ee226c, 0x3d22e47c,
+ 0x3d1f2bc5, 0x12fa231b, 0x131e20c0, 0x3d13f37e, 0x3d10315a, 0x132a1e7e, 0x134e1348, 0x3d04dcd2,
+ 0x3d011145, 0x135a0e0e, 0x137df9e7, 0x3cf5a082, 0x3cf1cb8e, 0x1389f1af, 0x13add481, 0x3ce63e98,
+ 0x3ce2603f, 0x13b9c943, 0x13dda2f7, 0x3cd6b71e, 0x3cd2cf62, 0x13e994ab, 0x140d652c, 0x3cc70a1c,
+ 0x3cc318ff, 0x141953cb, 0x143d1b02, 0x3cb7379c, 0x3cb33d22, 0x14490685, 0x146cc45c, 0x3ca73fa9,
+ 0x3ca33bd3, 0x1478acbc, 0x149c611d, 0x3c97224c, 0x3c93151d, 0x14a84652, 0x14cbf127, 0x3c86df8e,
+ 0x3c82c909, 0x14d7d32a, 0x14fb745e, 0x3c76777b, 0x3c7257a2, 0x15075327, 0x152aeaa3, 0x3c65ea1c,
+ 0x3c61c0f1, 0x1536c62b, 0x155a53d9, 0x3c55377b, 0x3c510501, 0x15662c18, 0x1589afe3, 0x3c445fa2,
+ 0x3c4023dd, 0x159584d3, 0x15b8fea4, 0x3c33629d, 0x3c2f1d8e, 0x15c4d03e, 0x15e83fff, 0x3c224075,
+ 0x3c1df21f, 0x15f40e3a, 0x161773d6, 0x3c10f935, 0x3c0ca19b, 0x16233eac, 0x16469a0d, 0x3bff8ce8,
+ 0x3bfb2c0c, 0x16526176, 0x1675b286, 0x3bedfb99, 0x3be9917e, 0x1681767c, 0x16a4bd25, 0x3bdc4552,
+ 0x3bd7d1fa, 0x16b07d9f, 0x16d3b9cc, 0x3bca6a1d, 0x3bc5ed8d, 0x16df76c3, 0x1702a85e, 0x3bb86a08,
+ 0x3bb3e440, 0x170e61cc, 0x173188be, 0x3ba6451b, 0x3ba1b620, 0x173d3e9b, 0x17605ad0, 0x3b93fb63,
+ 0x3b8f6337, 0x176c0d15, 0x178f1e76, 0x3b818ceb, 0x3b7ceb90, 0x179acd1c, 0x17bdd394, 0x3b6ef9be,
+ 0x3b6a4f38, 0x17c97e93, 0x17ec7a0d, 0x3b5c41e8, 0x3b578e39, 0x17f8215e, 0x181b11c4, 0x3b496574,
+ 0x3b44a8a0, 0x1826b561, 0x18499a9d, 0x3b36646e, 0x3b319e77, 0x18553a7d, 0x1878147a, 0x3b233ee1,
+ 0x3b1e6fca, 0x1883b097, 0x18a67f3f, 0x3b0ff4d9, 0x3b0b1ca6, 0x18b21791, 0x18d4dad0, 0x3afc8663,
+ 0x3af7a516, 0x18e06f50, 0x1903270f, 0x3ae8f38b, 0x3ae40926, 0x190eb7b7, 0x193163e1, 0x3ad53c5b,
+ 0x3ad048e3, 0x193cf0a9, 0x195f9128, 0x3ac160e1, 0x3abc6458, 0x196b1a09, 0x198daec8, 0x3aad6129,
+ 0x3aa85b92, 0x199933bb, 0x19bbbca6, 0x3a993d3e, 0x3a942e9d, 0x19c73da3, 0x19e9baa3, 0x3a84f52f,
+ 0x3a7fdd86, 0x19f537a4, 0x1a17a8a5, 0x3a708906, 0x3a6b6859, 0x1a2321a2, 0x1a45868e, 0x3a5bf8d1,
+ 0x3a56cf23, 0x1a50fb81, 0x1a735442, 0x3a47449c, 0x3a4211f0, 0x1a7ec524, 0x1aa111a6, 0x3a326c74,
+ 0x3a2d30cd, 0x1aac7e6f, 0x1acebe9d, 0x3a1d7066, 0x3a182bc8, 0x1ada2746, 0x1afc5b0a, 0x3a08507f,
+ 0x3a0302ed, 0x1b07bf8c, 0x1b29e6d2, 0x39f30ccc, 0x39edb649, 0x1b354727, 0x1b5761d8, 0x39dda55a,
+ 0x39d845e9, 0x1b62bdf8, 0x1b84cc01, 0x39c81a36, 0x39c2b1da, 0x1b9023e5, 0x1bb22530, 0x39b26b6d,
+ 0x39acfa2b, 0x1bbd78d2, 0x1bdf6d4a, 0x399c990d, 0x39971ee7, 0x1beabca1, 0x1c0ca432, 0x3986a324,
+ 0x3981201e, 0x1c17ef39, 0x1c39c9cd, 0x397089bf, 0x396afddc, 0x1c45107c, 0x1c66ddfe, 0x395a4ceb,
+ 0x3954b82e, 0x1c72204f, 0x1c93e0ab, 0x3943ecb6, 0x393e4f23, 0x1c9f1e96, 0x1cc0d1b6, 0x392d692f,
+ 0x3927c2c9, 0x1ccc0b35, 0x1cedb106, 0x3916c262, 0x3911132d, 0x1cf8e611, 0x1d1a7e7d, 0x38fff85e,
+ 0x38fa405e, 0x1d25af0d, 0x1d473a00, 0x38e90b31, 0x38e34a69, 0x1d52660f, 0x1d73e374, 0x38d1fae9,
+ 0x38cc315d, 0x1d7f0afb, 0x1da07abc, 0x38bac795, 0x38b4f547, 0x1dab9db5, 0x1dccffbf, 0x38a37142,
+ 0x389d9637, 0x1dd81e21, 0x1df9725f, 0x388bf7ff, 0x3886143b, 0x1e048c24, 0x1e25d282, 0x38745bdb,
+ 0x386e6f60, 0x1e30e7a4, 0x1e52200c, 0x385c9ce3, 0x3856a7b6, 0x1e5d3084, 0x1e7e5ae2, 0x3844bb28,
+ 0x383ebd4c, 0x1e8966a8, 0x1eaa82e9, 0x382cb6b7, 0x3826b030, 0x1eb589f7, 0x1ed69805, 0x38148f9f,
+ 0x380e8071, 0x1ee19a54, 0x1f029a1c, 0x37fc45ef, 0x37f62e1d, 0x1f0d97a5, 0x1f2e8911, 0x37e3d9b7,
+ 0x37ddb945, 0x1f3981ce, 0x1f5a64cb, 0x37cb4b04, 0x37c521f6, 0x1f6558b5, 0x1f862d2d, 0x37b299e7,
+ 0x37ac6841, 0x1f911c3d, 0x1fb1e21d, 0x3799c66f, 0x37938c34, 0x1fbccc4d, 0x1fdd8381, 0x3780d0aa,
+ 0x377a8ddf, 0x1fe868c8, 0x2009113c, 0x3767b8a9, 0x37616d51, 0x2013f196, 0x20348b35, 0x374e7e7b,
+ 0x37482a9a, 0x203f6699, 0x205ff14f, 0x3735222f, 0x372ec5c9, 0x206ac7b8, 0x208b4372, 0x371ba3d4,
+ 0x37153eee, 0x209614d9, 0x20b68181, 0x3702037c, 0x36fb9618, 0x20c14ddf, 0x20e1ab63, 0x36e84135,
+ 0x36e1cb58, 0x20ec72b1, 0x210cc0fc, 0x36ce5d10, 0x36c7debd, 0x21178334, 0x2137c232, 0x36b4571b,
+ 0x36add058, 0x21427f4d, 0x2162aeea, 0x369a2f69, 0x3693a038, 0x216d66e2, 0x218d870b, 0x367fe608,
+ 0x36794e6e, 0x219839d8, 0x21b84a79, 0x36657b08, 0x365edb09, 0x21c2f815, 0x21e2f91a, 0x364aee7b,
+ 0x3644461b, 0x21eda17f, 0x220d92d4, 0x36304070, 0x36298fb4, 0x221835fb, 0x2238178d, 0x361570f8,
+ 0x360eb7e3, 0x2242b56f, 0x22628729, 0x35fa8023, 0x35f3beba, 0x226d1fc1, 0x228ce191, 0x35df6e03,
+ 0x35d8a449, 0x229774d7, 0x22b726a8, 0x35c43aa7, 0x35bd68a1, 0x22c1b496, 0x22e15655, 0x35a8e621,
+ 0x35a20bd3, 0x22ebdee5, 0x230b707e, 0x358d7081, 0x35868def, 0x2315f3a8, 0x23357509, 0x3571d9d9,
+ 0x356aef08, 0x233ff2c8, 0x235f63dc, 0x35562239, 0x354f2f2c, 0x2369dc29, 0x23893cdd, 0x353a49b2,
+ 0x35334e6f, 0x2393afb2, 0x23b2fff3, 0x351e5056, 0x35174ce0, 0x23bd6d48, 0x23dcad03, 0x35023636,
+ 0x34fb2a92, 0x23e714d3, 0x240643f4, 0x34e5fb63, 0x34dee795, 0x2410a639, 0x242fc4ad, 0x34c99fef,
+ 0x34c283fb, 0x243a215f, 0x24592f13, 0x34ad23eb, 0x34a5ffd5, 0x2463862c, 0x2482830d, 0x34908768,
+ 0x34895b36, 0x248cd487, 0x24abc082, 0x3473ca79, 0x346c962f, 0x24b60c57, 0x24d4e757, 0x3456ed2f,
+ 0x344fb0d1, 0x24df2d81, 0x24fdf775, 0x3439ef9c, 0x3432ab2e, 0x250837ed, 0x2526f0c1, 0x341cd1d2,
+ 0x34158559, 0x25312b81, 0x254fd323, 0x33ff93e2, 0x33f83f62, 0x255a0823, 0x25789e80, 0x33e235df,
+ 0x33dad95e, 0x2582cdbc, 0x25a152c0, 0x33c4b7db, 0x33bd535c, 0x25ab7c30, 0x25c9efca, 0x33a719e8,
+ 0x339fad70, 0x25d41369, 0x25f27584, 0x33895c18, 0x3381e7ac, 0x25fc934b, 0x261ae3d6, 0x336b7e7e,
+ 0x33640223, 0x2624fbbf, 0x26433aa7, 0x334d812d, 0x3345fce6, 0x264d4cac, 0x266b79dd, 0x332f6435,
+ 0x3327d808, 0x267585f8, 0x2693a161, 0x331127ab, 0x3309939c, 0x269da78b, 0x26bbb119, 0x32f2cba1,
+ 0x32eb2fb5, 0x26c5b14c, 0x26e3a8ec, 0x32d45029, 0x32ccac64, 0x26eda322, 0x270b88c2, 0x32b5b557,
+ 0x32ae09be, 0x27157cf5, 0x27335082, 0x3296fb3d, 0x328f47d5, 0x273d3eac, 0x275b0014, 0x327821ee,
+ 0x327066bc, 0x2764e82f, 0x27829760, 0x3259297d, 0x32516686, 0x278c7965, 0x27aa164c, 0x323a11fe,
+ 0x32324746, 0x27b3f235, 0x27d17cc1, 0x321adb83, 0x3213090f, 0x27db5288, 0x27f8caa5, 0x31fb8620,
+ 0x31f3abf5, 0x28029a45, 0x281fffe2, 0x31dc11e8, 0x31d4300b, 0x2829c954, 0x28471c5e, 0x31bc7eee,
+ 0x31b49564, 0x2850df9d, 0x286e2002, 0x319ccd46, 0x3194dc14, 0x2877dd07, 0x28950ab6, 0x317cfd04,
+ 0x3175042e, 0x289ec17a, 0x28bbdc61, 0x315d0e3b, 0x31550dc6, 0x28c58cdf, 0x28e294eb, 0x313d00ff,
+ 0x3134f8f1, 0x28ec3f1e, 0x2909343e, 0x311cd564, 0x3114c5c0, 0x2912d81f, 0x292fba40, 0x30fc8b7d,
+ 0x30f47449, 0x293957c9, 0x295626da, 0x30dc235e, 0x30d404a0, 0x295fbe06, 0x297c79f5, 0x30bb9d1c,
+ 0x30b376d8, 0x29860abd, 0x29a2b378, 0x309af8ca, 0x3092cb05, 0x29ac3dd7, 0x29c8d34d, 0x307a367c,
+ 0x3072013c, 0x29d2573c, 0x29eed95b, 0x30595648, 0x30511991, 0x29f856d5, 0x2a14c58b, 0x30385840,
+ 0x30301418, 0x2a1e3c8a, 0x2a3a97c7, 0x30173c7a, 0x300ef0e5, 0x2a440844, 0x2a604ff5, 0x2ff6030a,
+ 0x2fedb00d, 0x2a69b9ec, 0x2a85ee00, 0x2fd4ac04, 0x2fcc51a5, 0x2a8f516b, 0x2aab71d0, 0x2fb3377c,
+ 0x2faad5c1, 0x2ab4cea9, 0x2ad0db4e, 0x2f91a589, 0x2f893c75, 0x2ada318e, 0x2af62a63, 0x2f6ff63d,
+ 0x2f6785d7, 0x2aff7a05, 0x2b1b5ef8, 0x2f4e29af, 0x2f45b1fb, 0x2b24a7f6, 0x2b4078f5, 0x2f2c3ff2,
+ 0x2f23c0f6, 0x2b49bb4a, 0x2b657844, 0x2f0a391d, 0x2f01b2de, 0x2b6eb3ea, 0x2b8a5cce, 0x2ee81543,
+ 0x2edf87c6, 0x2b9391c0, 0x2baf267d, 0x2ec5d479, 0x2ebd3fc4, 0x2bb854b4, 0x2bd3d53a, 0x2ea376d6,
+ 0x2e9adaee, 0x2bdcfcb0, 0x2bf868ed, 0x2e80fc6e, 0x2e785958, 0x2c01899e, 0x2c1ce181, 0x2e5e6556,
+ 0x2e55bb17, 0x2c25fb66, 0x2c413edf, 0x2e3bb1a4, 0x2e330042, 0x2c4a51f3, 0x2c6580f1, 0x2e18e16d,
+ 0x2e1028ed, 0x2c6e8d2e, 0x2c89a79f, 0x2df5f4c7, 0x2ded352f, 0x2c92ad01, 0x2cadb2d5, 0x2dd2ebc7,
+ 0x2dca251c, 0x2cb6b155, 0x2cd1a27b, 0x2dafc683, 0x2da6f8ca, 0x2cda9a14, 0x2cf5767c, 0x2d8c8510,
+ 0x2d83b04f, 0x2cfe6728, 0x2d192ec1, 0x2d692784, 0x2d604bc0, 0x2d22187a, 0x2d3ccb34, 0x2d45adf6
+};
+
+
+const int twidTab512[(8*6 + 32*6 + 128*6)/2] = {
+ 0x40000000, 0x40000000, 0x40000000, 0x3b20187d,
+ 0x3ec50c7c, 0x3536238e, 0x2d412d41, 0x3b20187d,
+ 0x187d3b20, 0x187d3b20, 0x3536238e, 0xf3843ec5,
+ 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xe7833b20,
+ 0x238e3536, 0xc13b0c7c, 0xd2bf2d41, 0x187d3b20,
+ 0xc4e0e783, 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca,
+
+ 0x40000000, 0x40000000, 0x40000000, 0x3fb10645,
+ 0x3fec0323, 0x3f4e0964, 0x3ec50c7c, 0x3fb10645,
+ 0x3d3e1294, 0x3d3e1294, 0x3f4e0964, 0x39da1b5d,
+ 0x3b20187d, 0x3ec50c7c, 0x3536238e, 0x38711e2b,
+ 0x3e140f8c, 0x2f6b2afa, 0x3536238e, 0x3d3e1294,
+ 0x28993179, 0x31792899, 0x3c42158f, 0x20e736e5,
+ 0x2d412d41, 0x3b20187d, 0x187d3b20, 0x28993179,
+ 0x39da1b5d, 0x0f8c3e14, 0x238e3536, 0x38711e2b,
+ 0x06453fb1, 0x1e2b3871, 0x36e520e7, 0xfcdd3fec,
+ 0x187d3b20, 0x3536238e, 0xf3843ec5, 0x12943d3e,
+ 0x3367261f, 0xea713c42, 0x0c7c3ec5, 0x31792899,
+ 0xe1d53871, 0x06453fb1, 0x2f6b2afa, 0xd9e13367,
+ 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xf9bb3fb1,
+ 0x2afa2f6b, 0xcc99261f, 0xf3843ec5, 0x28993179,
+ 0xc78f1e2b, 0xed6c3d3e, 0x261f3367, 0xc3be158f,
+ 0xe7833b20, 0x238e3536, 0xc13b0c7c, 0xe1d53871,
+ 0x20e736e5, 0xc0140323, 0xdc723536, 0x1e2b3871,
+ 0xc04ff9bb, 0xd7673179, 0x1b5d39da, 0xc1ecf074,
+ 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xce872899,
+ 0x158f3c42, 0xc91bdf19, 0xcaca238e, 0x12943d3e,
+ 0xce87d767, 0xc78f1e2b, 0x0f8c3e14, 0xd506d095,
+ 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 0xc2c21294,
+ 0x09643f4e, 0xe4a3c626, 0xc13b0c7c, 0x06453fb1,
+ 0xed6cc2c2, 0xc04f0645, 0x03233fec, 0xf69cc0b2,
+
+ 0x40000000, 0x40000000, 0x40000000, 0x3ffb0192,
+ 0x3ffe00c9, 0x3ff4025b, 0x3fec0323, 0x3ffb0192,
+ 0x3fd304b5, 0x3fd304b5, 0x3ff4025b, 0x3f9c070d,
+ 0x3fb10645, 0x3fec0323, 0x3f4e0964, 0x3f8407d5,
+ 0x3fe103ec, 0x3eeb0bb6, 0x3f4e0964, 0x3fd304b5,
+ 0x3e710e05, 0x3f0e0af1, 0x3fc3057d, 0x3de2104f,
+ 0x3ec50c7c, 0x3fb10645, 0x3d3e1294, 0x3e710e05,
+ 0x3f9c070d, 0x3c8414d1, 0x3e140f8c, 0x3f8407d5,
+ 0x3bb61708, 0x3dae1111, 0x3f6a089c, 0x3ad21937,
+ 0x3d3e1294, 0x3f4e0964, 0x39da1b5d, 0x3cc51413,
+ 0x3f2f0a2a, 0x38cf1d79, 0x3c42158f, 0x3f0e0af1,
+ 0x37af1f8b, 0x3bb61708, 0x3eeb0bb6, 0x367c2192,
+ 0x3b20187d, 0x3ec50c7c, 0x3536238e, 0x3a8219ef,
+ 0x3e9c0d41, 0x33de257d, 0x39da1b5d, 0x3e710e05,
+ 0x3274275f, 0x392a1cc6, 0x3e440ec9, 0x30f82934,
+ 0x38711e2b, 0x3e140f8c, 0x2f6b2afa, 0x37af1f8b,
+ 0x3de2104f, 0x2dce2cb2, 0x36e520e7, 0x3dae1111,
+ 0x2c212e5a, 0x3612223d, 0x3d7711d3, 0x2a652ff1,
+ 0x3536238e, 0x3d3e1294, 0x28993179, 0x345324da,
+ 0x3d021354, 0x26c032ee, 0x3367261f, 0x3cc51413,
+ 0x24da3453, 0x3274275f, 0x3c8414d1, 0x22e635a5,
+ 0x31792899, 0x3c42158f, 0x20e736e5, 0x307629cd,
+ 0x3bfd164c, 0x1edc3811, 0x2f6b2afa, 0x3bb61708,
+ 0x1cc6392a, 0x2e5a2c21, 0x3b6c17c3, 0x1aa63a2f,
+ 0x2d412d41, 0x3b20187d, 0x187d3b20, 0x2c212e5a,
+ 0x3ad21937, 0x164c3bfd, 0x2afa2f6b, 0x3a8219ef,
+ 0x14133cc5, 0x29cd3076, 0x3a2f1aa6, 0x11d33d77,
+ 0x28993179, 0x39da1b5d, 0x0f8c3e14, 0x275f3274,
+ 0x39831c12, 0x0d413e9c, 0x261f3367, 0x392a1cc6,
+ 0x0af13f0e, 0x24da3453, 0x38cf1d79, 0x089c3f6a,
+ 0x238e3536, 0x38711e2b, 0x06453fb1, 0x223d3612,
+ 0x38111edc, 0x03ec3fe1, 0x20e736e5, 0x37af1f8b,
+ 0x01923ffb, 0x1f8b37af, 0x374b2039, 0xff373ffe,
+ 0x1e2b3871, 0x36e520e7, 0xfcdd3fec, 0x1cc6392a,
+ 0x367c2192, 0xfa833fc3, 0x1b5d39da, 0x3612223d,
+ 0xf82b3f84, 0x19ef3a82, 0x35a522e6, 0xf5d63f2f,
+ 0x187d3b20, 0x3536238e, 0xf3843ec5, 0x17083bb6,
+ 0x34c62434, 0xf1373e44, 0x158f3c42, 0x345324da,
+ 0xeeef3dae, 0x14133cc5, 0x33de257d, 0xecac3d02,
+ 0x12943d3e, 0x3367261f, 0xea713c42, 0x11113dae,
+ 0x32ee26c0, 0xe83d3b6c, 0x0f8c3e14, 0x3274275f,
+ 0xe6113a82, 0x0e053e71, 0x31f727fd, 0xe3ee3983,
+ 0x0c7c3ec5, 0x31792899, 0xe1d53871, 0x0af13f0e,
+ 0x30f82934, 0xdfc7374b, 0x09643f4e, 0x307629cd,
+ 0xddc33612, 0x07d53f84, 0x2ff12a65, 0xdbcc34c6,
+ 0x06453fb1, 0x2f6b2afa, 0xd9e13367, 0x04b53fd3,
+ 0x2ee32b8e, 0xd80331f7, 0x03233fec, 0x2e5a2c21,
+ 0xd6333076, 0x01923ffb, 0x2dce2cb2, 0xd4722ee3,
+ 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xfe6e3ffb,
+ 0x2cb22dce, 0xd11d2b8e, 0xfcdd3fec, 0x2c212e5a,
+ 0xcf8a29cd, 0xfb4b3fd3, 0x2b8e2ee3, 0xce0927fd,
+ 0xf9bb3fb1, 0x2afa2f6b, 0xcc99261f, 0xf82b3f84,
+ 0x2a652ff1, 0xcb3a2434, 0xf69c3f4e, 0x29cd3076,
+ 0xc9ee223d, 0xf50f3f0e, 0x293430f8, 0xc8b52039,
+ 0xf3843ec5, 0x28993179, 0xc78f1e2b, 0xf1fb3e71,
+ 0x27fd31f7, 0xc67d1c12, 0xf0743e14, 0x275f3274,
+ 0xc57e19ef, 0xeeef3dae, 0x26c032ee, 0xc49417c3,
+ 0xed6c3d3e, 0x261f3367, 0xc3be158f, 0xebed3cc5,
+ 0x257d33de, 0xc2fe1354, 0xea713c42, 0x24da3453,
+ 0xc2521111, 0xe8f83bb6, 0x243434c6, 0xc1bc0ec9,
+ 0xe7833b20, 0x238e3536, 0xc13b0c7c, 0xe6113a82,
+ 0x22e635a5, 0xc0d10a2a, 0xe4a339da, 0x223d3612,
+ 0xc07c07d5, 0xe33a392a, 0x2192367c, 0xc03d057d,
+ 0xe1d53871, 0x20e736e5, 0xc0140323, 0xe07537af,
+ 0x2039374b, 0xc00200c9, 0xdf1936e5, 0x1f8b37af,
+ 0xc005fe6e, 0xddc33612, 0x1edc3811, 0xc01ffc14,
+ 0xdc723536, 0x1e2b3871, 0xc04ff9bb, 0xdb263453,
+ 0x1d7938cf, 0xc096f764, 0xd9e13367, 0x1cc6392a,
+ 0xc0f2f50f, 0xd8a13274, 0x1c123983, 0xc164f2bf,
+ 0xd7673179, 0x1b5d39da, 0xc1ecf074, 0xd6333076,
+ 0x1aa63a2f, 0xc289ee2d, 0xd5062f6b, 0x19ef3a82,
+ 0xc33bebed, 0xd3df2e5a, 0x19373ad2, 0xc403e9b4,
+ 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xd1a62c21,
+ 0x17c33b6c, 0xc5d1e55a, 0xd0952afa, 0x17083bb6,
+ 0xc6d6e33a, 0xcf8a29cd, 0x164c3bfd, 0xc7efe124,
+ 0xce872899, 0x158f3c42, 0xc91bdf19, 0xcd8c275f,
+ 0x14d13c84, 0xca5bdd1a, 0xcc99261f, 0x14133cc5,
+ 0xcbaddb26, 0xcbad24da, 0x13543d02, 0xcd12d940,
+ 0xcaca238e, 0x12943d3e, 0xce87d767, 0xc9ee223d,
+ 0x11d33d77, 0xd00fd59b, 0xc91b20e7, 0x11113dae,
+ 0xd1a6d3df, 0xc8511f8b, 0x104f3de2, 0xd34ed232,
+ 0xc78f1e2b, 0x0f8c3e14, 0xd506d095, 0xc6d61cc6,
+ 0x0ec93e44, 0xd6cccf08, 0xc6261b5d, 0x0e053e71,
+ 0xd8a1cd8c, 0xc57e19ef, 0x0d413e9c, 0xda83cc22,
+ 0xc4e0187d, 0x0c7c3ec5, 0xdc72caca, 0xc44a1708,
+ 0x0bb63eeb, 0xde6ec984, 0xc3be158f, 0x0af13f0e,
+ 0xe075c851, 0xc33b1413, 0x0a2a3f2f, 0xe287c731,
+ 0xc2c21294, 0x09643f4e, 0xe4a3c626, 0xc2521111,
+ 0x089c3f6a, 0xe6c9c52e, 0xc1ec0f8c, 0x07d53f84,
+ 0xe8f8c44a, 0xc18f0e05, 0x070d3f9c, 0xeb2fc37c,
+ 0xc13b0c7c, 0x06453fb1, 0xed6cc2c2, 0xc0f20af1,
+ 0x057d3fc3, 0xefb1c21e, 0xc0b20964, 0x04b53fd3,
+ 0xf1fbc18f, 0xc07c07d5, 0x03ec3fe1, 0xf44ac115,
+ 0xc04f0645, 0x03233fec, 0xf69cc0b2, 0xc02d04b5,
+ 0x025b3ff4, 0xf8f3c064, 0xc0140323, 0x01923ffb,
+ 0xfb4bc02d, 0xc0050192, 0x00c93ffe, 0xfda5c00c
+};
+
+const int twidTab64[(4*6 + 16*6)/2] = {
+ 0x40000000, 0x40000000, 0x40000000, 0x2d412d41,
+ 0x3b20187d, 0x187d3b20, 0x00004000, 0x2d412d41,
+ 0xd2bf2d41, 0xd2bf2d41, 0x187d3b20, 0xc4e0e783,
+
+ 0x40000000, 0x40000000, 0x40000000, 0x3ec50c7c,
+ 0x3fb10645, 0x3d3e1294, 0x3b20187d, 0x3ec50c7c,
+ 0x3536238e, 0x3536238e, 0x3d3e1294, 0x28993179,
+ 0x2d412d41, 0x3b20187d, 0x187d3b20, 0x238e3536,
+ 0x38711e2b, 0x06453fb1, 0x187d3b20, 0x3536238e,
+ 0xf3843ec5, 0x0c7c3ec5, 0x31792899, 0xe1d53871,
+ 0x00004000, 0x2d412d41, 0xd2bf2d41, 0xf3843ec5,
+ 0x28993179, 0xc78f1e2b, 0xe7833b20, 0x238e3536,
+ 0xc13b0c7c, 0xdc723536, 0x1e2b3871, 0xc04ff9bb,
+ 0xd2bf2d41, 0x187d3b20, 0xc4e0e783, 0xcaca238e,
+ 0x12943d3e, 0xce87d767, 0xc4e0187d, 0x0c7c3ec5,
+ 0xdc72caca, 0xc13b0c7c, 0x06453fb1, 0xed6cc2c2
+};
+
+#elif defined ARMV7Neon
+/*
+ * Q29 for 128 and 1024
+ *
+ * for (i = 0; i < num/4; i++) {
+ * angle = (i + 0.125) * M_PI / num;
+ * x = cos(angle) * (1 << 29);
+ * x = sin(angle) * (1 << 29);
+ *
+ * angle = (num/2 - 1 - i + 0.125) * M_PI / num;
+ * x = cos(angle) * (1 << 29);
+ * x = sin(angle) * (1 << 29);
+ * }
+ */
+const int cossintab[128 + 1024] = {
+ /* 128 */
+ 0x1ffff621, 0x001921f9, 0x00afea69, 0x1ffe1c68, 0x1ffce09d, 0x00e22a7a, 0x0178dbaa, 0x1ff753bb,
+ 0x1ff4dc55, 0x01ab101c, 0x024192cf, 0x1feb9d25, 0x1fe7ea85, 0x0273b3e2, 0x0309f0e2, 0x1fdafa75,
+ 0x1fd60d2e, 0x033bf6dd, 0x03d1d700, 0x1fc56e3b, 0x1fbf470f, 0x0403ba2b, 0x04992653, 0x1faafbcb,
+ 0x1fa39bac, 0x04cadefe, 0x055fc022, 0x1f8ba738, 0x1f830f4a, 0x059146a1, 0x062585ca, 0x1f677557,
+ 0x1f5da6ed, 0x0656d27a, 0x06ea58cd, 0x1f3e6bbc, 0x1f33685a, 0x071b6415, 0x07ae1ad2, 0x1f1090bd,
+ 0x1f045a15, 0x07dedd20, 0x0870ada7, 0x1eddeb6a, 0x1ed0835f, 0x08a11f78, 0x0931f34d, 0x1ea68394,
+ 0x1e97ec36, 0x09620d27, 0x09f1cdf5, 0x1e6a61c5, 0x1e5a9d55, 0x0a21886e, 0x0ab02009, 0x1e298f44,
+ 0x1e18a030, 0x0adf73c6, 0x0b6ccc32, 0x1de4160f, 0x1dd1fef4, 0x0b9bb1e5, 0x0c27b555, 0x1d9a00de,
+ 0x1d86c484, 0x0c5625c3, 0x0ce0bea2, 0x1d4b5b1b, 0x1d36fc7c, 0x0d0eb2a2, 0x0d97cb8f, 0x1cf830e9,
+ 0x1ce2b328, 0x0dc53c0a, 0x0e4cbfe2, 0x1ca08f1a, 0x1c89f587, 0x0e79a5d7, 0x0eff7fb3, 0x1c448331,
+ 0x1c2cd149, 0x0f2bd437, 0x0fafef73, 0x1be41b61, 0x1bcb54cb, 0x0fdbabae, 0x105df3ec, 0x1b7f6687,
+ 0x1b658f15, 0x10891120, 0x11097249, 0x1b16742a, 0x1afb8fd9, 0x1133e9d0, 0x11b25017, 0x1aa9547a,
+ 0x1a8d676e, 0x11dc1b65, 0x1258734d, 0x1a38184a, 0x1a1b26d3, 0x12818bef, 0x12fbc24b, 0x19c2d111,
+ 0x19a4dfa4, 0x132421ec, 0x139c23e4, 0x194990e4, 0x192aa420, 0x13c3c44a, 0x14397f5b, 0x18cc6a75,
+ 0x18ac871f, 0x14605a69, 0x14d3bc6d, 0x184b7112, 0x182a9c14, 0x14f9cc26, 0x156ac352, 0x17c6b89d,
+ 0x17a4f708, 0x159001d6, 0x15fe7cbe, 0x173e558e, 0x171bac96, 0x1622e450, 0x168ed1eb, 0x16b25ced,
+ /* 1024 */
+ 0x1fffffd9, 0x0003243f, 0x0015fdba, 0x1ffff872, 0x1ffff382, 0x001c4637, 0x002f1fa6, 0x1fffdd4d,
+ 0x1fffd36f, 0x0035681d, 0x00484175, 0x1fffae6c, 0x1fff9f9e, 0x004e89e3, 0x00616318, 0x1fff6bce,
+ 0x1fff5811, 0x0067ab77, 0x007a847e, 0x1fff1572, 0x1ffefcc6, 0x0080cccc, 0x0093a599, 0x1ffeab5b,
+ 0x1ffe8dbf, 0x0099edd2, 0x00acc658, 0x1ffe2d86, 0x1ffe0afc, 0x00b30e78, 0x00c5e6ad, 0x1ffd9bf6,
+ 0x1ffd747c, 0x00cc2eb0, 0x00df0688, 0x1ffcf6aa, 0x1ffcca41, 0x00e54e6a, 0x00f825da, 0x1ffc3da2,
+ 0x1ffc0c4b, 0x00fe6d97, 0x01114492, 0x1ffb70e0, 0x1ffb3a9a, 0x01178c27, 0x012a62a2, 0x1ffa9063,
+ 0x1ffa552e, 0x0130aa0a, 0x01437ffa, 0x1ff99c2c, 0x1ff95c09, 0x0149c731, 0x015c9c8a, 0x1ff8943c,
+ 0x1ff84f2b, 0x0162e38d, 0x0175b843, 0x1ff77893, 0x1ff72e94, 0x017bff0e, 0x018ed316, 0x1ff64932,
+ 0x1ff5fa46, 0x019519a5, 0x01a7ecf2, 0x1ff5061b, 0x1ff4b240, 0x01ae3341, 0x01c105c9, 0x1ff3af4c,
+ 0x1ff35684, 0x01c74bd5, 0x01da1d8c, 0x1ff244c8, 0x1ff1e713, 0x01e0634f, 0x01f33429, 0x1ff0c68f,
+ 0x1ff063ed, 0x01f979a1, 0x020c4993, 0x1fef34a3, 0x1feecd14, 0x02128ebb, 0x02255db9, 0x1fed8f03,
+ 0x1fed2287, 0x022ba28f, 0x023e708d, 0x1febd5b2, 0x1feb644a, 0x0244b50b, 0x025781fe, 0x1fea08b0,
+ 0x1fe9925c, 0x025dc621, 0x027091fd, 0x1fe827fe, 0x1fe7acbe, 0x0276d5c1, 0x0289a07b, 0x1fe6339d,
+ 0x1fe5b372, 0x028fe3dd, 0x02a2ad69, 0x1fe42b90, 0x1fe3a679, 0x02a8f063, 0x02bbb8b6, 0x1fe20fd6,
+ 0x1fe185d5, 0x02c1fb46, 0x02d4c253, 0x1fdfe071, 0x1fdf5186, 0x02db0475, 0x02edca32, 0x1fdd9d64,
+ 0x1fdd098e, 0x02f40be2, 0x0306d042, 0x1fdb46ae, 0x1fdaadee, 0x030d117c, 0x031fd474, 0x1fd8dc51,
+ 0x1fd83ea8, 0x03261534, 0x0338d6b8, 0x1fd65e4f, 0x1fd5bbbd, 0x033f16fb, 0x0351d700, 0x1fd3ccaa,
+ 0x1fd32530, 0x035816c1, 0x036ad53c, 0x1fd12763, 0x1fd07b00, 0x03711477, 0x0383d15c, 0x1fce6e7c,
+ 0x1fcdbd31, 0x038a100e, 0x039ccb51, 0x1fcba1f5, 0x1fcaebc3, 0x03a30975, 0x03b5c30b, 0x1fc8c1d2,
+ 0x1fc806b9, 0x03bc009f, 0x03ceb87c, 0x1fc5ce14, 0x1fc50e14, 0x03d4f57a, 0x03e7ab93, 0x1fc2c6bd,
+ 0x1fc201d7, 0x03ede7f9, 0x04009c42, 0x1fbfabcd, 0x1fbee202, 0x0406d80b, 0x04198a78, 0x1fbc7d49,
+ 0x1fbbae99, 0x041fc5a1, 0x04327628, 0x1fb93b31, 0x1fb8679c, 0x0438b0ac, 0x044b5f40, 0x1fb5e587,
+ 0x1fb50d0e, 0x0451991d, 0x046445b2, 0x1fb27c4e, 0x1fb19ef1, 0x046a7ee3, 0x047d296f, 0x1faeff87,
+ 0x1fae1d47, 0x048361f0, 0x04960a67, 0x1fab6f35, 0x1faa8813, 0x049c4235, 0x04aee88b, 0x1fa7cb5a,
+ 0x1fa6df56, 0x04b51fa1, 0x04c7c3cb, 0x1fa413f8, 0x1fa32313, 0x04cdfa26, 0x04e09c18, 0x1fa04912,
+ 0x1f9f534c, 0x04e6d1b4, 0x04f97163, 0x1f9c6aa9, 0x1f9b7003, 0x04ffa63c, 0x0512439d, 0x1f9878c1,
+ 0x1f97793b, 0x051877af, 0x052b12b6, 0x1f94735b, 0x1f936ef6, 0x053145fd, 0x0543de9e, 0x1f905a7a,
+ 0x1f8f5137, 0x054a1117, 0x055ca748, 0x1f8c2e21, 0x1f8b2000, 0x0562d8ee, 0x05756ca2, 0x1f87ee52,
+ 0x1f86db55, 0x057b9d73, 0x058e2e9f, 0x1f839b10, 0x1f828336, 0x05945e95, 0x05a6ed2e, 0x1f7f345e,
+ 0x1f7e17a8, 0x05ad1c47, 0x05bfa840, 0x1f7aba3e, 0x1f7998ad, 0x05c5d678, 0x05d85fc7, 0x1f762cb2,
+ 0x1f750647, 0x05de8d19, 0x05f113b3, 0x1f718bbf, 0x1f70607a, 0x05f7401c, 0x0609c3f5, 0x1f6cd766,
+ 0x1f6ba748, 0x060fef71, 0x0622707d, 0x1f680fab, 0x1f66dab5, 0x06289b08, 0x063b193c, 0x1f633490,
+ 0x1f61fac3, 0x064142d3, 0x0653be23, 0x1f5e4619, 0x1f5d0775, 0x0659e6c2, 0x066c5f24, 0x1f594448,
+ 0x1f5800ce, 0x067286c6, 0x0684fc2e, 0x1f542f21, 0x1f52e6d2, 0x068b22d0, 0x069d9532, 0x1f4f06a6,
+ 0x1f4db983, 0x06a3bad0, 0x06b62a22, 0x1f49cadc, 0x1f4878e5, 0x06bc4eb9, 0x06cebaee, 0x1f447bc4,
+ 0x1f4324fb, 0x06d4de79, 0x06e74786, 0x1f3f1963, 0x1f3dbdc8, 0x06ed6a03, 0x06ffcfdd, 0x1f39a3bc,
+ 0x1f384350, 0x0705f147, 0x071853e3, 0x1f341ad2, 0x1f32b595, 0x071e7436, 0x0730d388, 0x1f2e7ea9,
+ 0x1f2d149d, 0x0736f2c0, 0x07494ebd, 0x1f28cf43, 0x1f276069, 0x074f6cd7, 0x0761c574, 0x1f230ca5,
+ 0x1f2198fd, 0x0767e26c, 0x077a379d, 0x1f1d36d2, 0x1f1bbe5d, 0x07805370, 0x0792a52a, 0x1f174dce,
+ 0x1f15d08d, 0x0798bfd3, 0x07ab0e0a, 0x1f11519c, 0x1f0fcf91, 0x07b12786, 0x07c37230, 0x1f0b4240,
+ 0x1f09bb6b, 0x07c98a7a, 0x07dbd18c, 0x1f051fbe, 0x1f03941f, 0x07e1e8a1, 0x07f42c0e, 0x1efeea19,
+ 0x1efd59b3, 0x07fa41eb, 0x080c81a9, 0x1ef8a155, 0x1ef70c28, 0x0812964a, 0x0824d24d, 0x1ef24577,
+ 0x1ef0ab84, 0x082ae5ad, 0x083d1dea, 0x1eebd682, 0x1eea37ca, 0x08433007, 0x08556473, 0x1ee5547a,
+ 0x1ee3b0fe, 0x085b7548, 0x086da5d8, 0x1edebf64, 0x1edd1724, 0x0873b562, 0x0885e209, 0x1ed81742,
+ 0x1ed66a41, 0x088bf044, 0x089e18f9, 0x1ed15c1a, 0x1ecfaa57, 0x08a425e1, 0x08b64a98, 0x1eca8def,
+ 0x1ec8d76c, 0x08bc562a, 0x08ce76d8, 0x1ec3acc6, 0x1ec1f184, 0x08d4810f, 0x08e69da8, 0x1ebcb8a3,
+ 0x1ebaf8a3, 0x08eca681, 0x08febefb, 0x1eb5b18a, 0x1eb3eccd, 0x0904c673, 0x0916dac2, 0x1eae977f,
+ 0x1eacce07, 0x091ce0d4, 0x092ef0ed, 0x1ea76a87, 0x1ea59c55, 0x0934f596, 0x0947016e, 0x1ea02aa7,
+ 0x1e9e57bb, 0x094d04aa, 0x095f0c36, 0x1e98d7e2, 0x1e97003e, 0x09650e01, 0x09771136, 0x1e91723e,
+ 0x1e8f95e3, 0x097d118d, 0x098f1060, 0x1e89f9bf, 0x1e8818ad, 0x09950f3f, 0x09a709a4, 0x1e826e69,
+ 0x1e8088a2, 0x09ad0707, 0x09befcf4, 0x1e7ad041, 0x1e78e5c7, 0x09c4f8d8, 0x09d6ea40, 0x1e731f4c,
+ 0x1e71301f, 0x09dce4a1, 0x09eed17b, 0x1e6b5b8f, 0x1e6967b1, 0x09f4ca56, 0x0a06b296, 0x1e63850e,
+ 0x1e618c80, 0x0a0ca9e6, 0x0a1e8d81, 0x1e5b9bce, 0x1e599e91, 0x0a248343, 0x0a36622e, 0x1e539fd4,
+ 0x1e519dea, 0x0a3c565e, 0x0a4e308f, 0x1e4b9126, 0x1e498a8e, 0x0a542329, 0x0a65f894, 0x1e436fc7,
+ 0x1e416485, 0x0a6be995, 0x0a7dba2f, 0x1e3b3bbd, 0x1e392bd1, 0x0a83a993, 0x0a957551, 0x1e32f50e,
+ 0x1e30e079, 0x0a9b6315, 0x0aad29ec, 0x1e2a9bbd, 0x1e288281, 0x0ab3160c, 0x0ac4d7f1, 0x1e222fd1,
+ 0x1e2011ee, 0x0acac26a, 0x0adc7f52, 0x1e19b14f, 0x1e178ec7, 0x0ae2681f, 0x0af41fff, 0x1e11203b,
+ 0x1e0ef910, 0x0afa071d, 0x0b0bb9eb, 0x1e087c9b, 0x1e0650ce, 0x0b119f56, 0x0b234d07, 0x1dffc674,
+ 0x1dfd9606, 0x0b2930bb, 0x0b3ad943, 0x1df6fdcc, 0x1df4c8bf, 0x0b40bb3e, 0x0b525e92, 0x1dee22a9,
+ 0x1debe8fd, 0x0b583ecf, 0x0b69dce6, 0x1de5350f, 0x1de2f6c6, 0x0b6fbb62, 0x0b81542f, 0x1ddc3504,
+ 0x1dd9f220, 0x0b8730e6, 0x0b98c45f, 0x1dd3228e, 0x1dd0db10, 0x0b9e9f4d, 0x0bb02d68, 0x1dc9fdb2,
+ 0x1dc7b19b, 0x0bb6068a, 0x0bc78f3b, 0x1dc0c676, 0x1dbe75c8, 0x0bcd668e, 0x0bdee9ca, 0x1db77cdf,
+ 0x1db5279c, 0x0be4bf4a, 0x0bf63d07, 0x1dae20f4, 0x1dabc71d, 0x0bfc10af, 0x0c0d88e2, 0x1da4b2ba,
+ 0x1da25450, 0x0c135ab0, 0x0c24cd4e, 0x1d9b3237, 0x1d98cf3b, 0x0c2a9d3e, 0x0c3c0a3d, 0x1d919f70,
+ 0x1d8f37e5, 0x0c41d84b, 0x0c533fa0, 0x1d87fa6d, 0x1d858e53, 0x0c590bc9, 0x0c6a6d68, 0x1d7e4332,
+ 0x1d7bd28b, 0x0c7037a8, 0x0c819388, 0x1d7479c5, 0x1d720493, 0x0c875bdb, 0x0c98b1f0, 0x1d6a9e2e,
+ 0x1d682472, 0x0c9e7854, 0x0cafc894, 0x1d60b070, 0x1d5e322c, 0x0cb58d04, 0x0cc6d764, 0x1d56b094,
+ 0x1d542dc9, 0x0ccc99de, 0x0cddde53, 0x1d4c9e9f, 0x1d4a174f, 0x0ce39ed2, 0x0cf4dd52, 0x1d427a97,
+ 0x1d3feec3, 0x0cfa9bd2, 0x0d0bd452, 0x1d384483, 0x1d35b42d, 0x0d1190d1, 0x0d22c347, 0x1d2dfc68,
+ 0x1d2b6791, 0x0d287dc1, 0x0d39aa21, 0x1d23a24e, 0x1d2108f8, 0x0d3f6292, 0x0d5088d3, 0x1d19363a,
+ 0x1d169867, 0x0d563f38, 0x0d675f4e, 0x1d0eb833, 0x1d0c15e4, 0x0d6d13a3, 0x0d7e2d85, 0x1d04283f,
+ 0x1d018176, 0x0d83dfc6, 0x0d94f369, 0x1cf98666, 0x1cf6db24, 0x0d9aa393, 0x0dabb0ec, 0x1ceed2ad,
+ 0x1cec22f4, 0x0db15efc, 0x0dc26600, 0x1ce40d1b, 0x1ce158ed, 0x0dc811f3, 0x0dd91298, 0x1cd935b7,
+ 0x1cd67d15, 0x0ddebc69, 0x0defb6a5, 0x1cce4c87, 0x1ccb8f74, 0x0df55e51, 0x0e065219, 0x1cc35192,
+ 0x1cc0900f, 0x0e0bf79c, 0x0e1ce4e6, 0x1cb844df, 0x1cb57eee, 0x0e22883e, 0x0e336eff, 0x1cad2675,
+ 0x1caa5c17, 0x0e391027, 0x0e49f055, 0x1ca1f65b, 0x1c9f2792, 0x0e4f8f4b, 0x0e6068db, 0x1c96b497,
+ 0x1c93e165, 0x0e66059a, 0x0e76d883, 0x1c8b6131, 0x1c888997, 0x0e7c7308, 0x0e8d3f3e, 0x1c7ffc2f,
+ 0x1c7d202f, 0x0e92d787, 0x0ea39d00, 0x1c748599, 0x1c71a535, 0x0ea93308, 0x0eb9f1ba, 0x1c68fd75,
+ 0x1c6618ae, 0x0ebf857d, 0x0ed03d5e, 0x1c5d63ca, 0x1c5a7aa4, 0x0ed5ceda, 0x0ee67fdf, 0x1c51b8a1,
+ 0x1c4ecb1c, 0x0eec0f10, 0x0efcb92f, 0x1c45fc00, 0x1c430a1d, 0x0f024612, 0x0f12e941, 0x1c3a2ded,
+ 0x1c3737b0, 0x0f1873d2, 0x0f291006, 0x1c2e4e72, 0x1c2b53db, 0x0f2e9842, 0x0f3f2d71, 0x1c225d94,
+ 0x1c1f5ea6, 0x0f44b354, 0x0f554175, 0x1c165b5b, 0x1c135818, 0x0f5ac4fc, 0x0f6b4c03, 0x1c0a47cf,
+ 0x1c074038, 0x0f70cd2a, 0x0f814d0e, 0x1bfe22f8, 0x1bfb170f, 0x0f86cbd3, 0x0f974489, 0x1bf1ecdb,
+ 0x1beedca2, 0x0f9cc0e7, 0x0fad3265, 0x1be5a582, 0x1be290fb, 0x0fb2ac5a, 0x0fc31697, 0x1bd94cf4,
+ 0x1bd63421, 0x0fc88e1e, 0x0fd8f10f, 0x1bcce337, 0x1bc9c61a, 0x0fde6626, 0x0feec1c0, 0x1bc06855,
+ 0x1bbd46f0, 0x0ff43464, 0x1004889e, 0x1bb3dc55, 0x1bb0b6a9, 0x1009f8cb, 0x101a459a, 0x1ba73f3d,
+ 0x1ba4154d, 0x101fb34d, 0x102ff8a8, 0x1b9a9117, 0x1b9762e4, 0x103563dc, 0x1045a1b9, 0x1b8dd1ea,
+ 0x1b8a9f77, 0x104b0a6c, 0x105b40c1, 0x1b8101be, 0x1b7dcb0c, 0x1060a6ef, 0x1070d5b1, 0x1b74209b,
+ 0x1b70e5ac, 0x10763958, 0x1086607e, 0x1b672e88, 0x1b63ef5f, 0x108bc19a, 0x109be119, 0x1b5a2b8e,
+ 0x1b56e82c, 0x10a13fa6, 0x10b15775, 0x1b4d17b4, 0x1b49d01c, 0x10b6b371, 0x10c6c385, 0x1b3ff304,
+ 0x1b3ca737, 0x10cc1cec, 0x10dc253c, 0x1b32bd84, 0x1b2f6d85, 0x10e17c0b, 0x10f17c8d, 0x1b25773d,
+ 0x1b22230e, 0x10f6d0c0, 0x1106c96a, 0x1b182038, 0x1b14c7da, 0x110c1afe, 0x111c0bc6, 0x1b0ab87c,
+ 0x1b075bf1, 0x11215ab8, 0x11314395, 0x1afd4012, 0x1af9df5d, 0x11368fe1, 0x114670c8, 0x1aefb702,
+ 0x1aec5225, 0x114bba6b, 0x115b9354, 0x1ae21d54, 0x1adeb451, 0x1160da4b, 0x1170ab2a, 0x1ad47311,
+ 0x1ad105e9, 0x1175ef72, 0x1185b83f, 0x1ac6b841, 0x1ac346f8, 0x118af9d4, 0x119aba84, 0x1ab8ecec,
+ 0x1ab57784, 0x119ff964, 0x11afb1ee, 0x1aab111c, 0x1aa79796, 0x11b4ee14, 0x11c49e6f, 0x1a9d24d9,
+ 0x1a99a737, 0x11c9d7d9, 0x11d97ff9, 0x1a8f282b, 0x1a8ba670, 0x11deb6a4, 0x11ee5682, 0x1a811b1b,
+ 0x1a7d9549, 0x11f38a6a, 0x120321fa, 0x1a72fdb2, 0x1a6f73ca, 0x1208531c, 0x1217e256, 0x1a64cff8,
+ 0x1a6141fd, 0x121d10af, 0x122c9789, 0x1a5691f5, 0x1a52ffeb, 0x1231c316, 0x12414186, 0x1a4843b4,
+ 0x1a44ad9b, 0x12466a44, 0x1255e041, 0x1a39e53d, 0x1a364b17, 0x125b062b, 0x126a73ac, 0x1a2b7698,
+ 0x1a27d868, 0x126f96c1, 0x127efbbb, 0x1a1cf7ce, 0x1a195597, 0x12841bf6, 0x12937861, 0x1a0e68e9,
+ 0x1a0ac2ac, 0x129895c0, 0x12a7e991, 0x19ffc9f1, 0x19fc1fb1, 0x12ad0412, 0x12bc4f40, 0x19f11af0,
+ 0x19ed6caf, 0x12c166de, 0x12d0a960, 0x19e25bee, 0x19dea9ae, 0x12d5be18, 0x12e4f7e5, 0x19d38cf4,
+ 0x19cfd6b8, 0x12ea09b4, 0x12f93ac2, 0x19c4ae0c, 0x19c0f3d6, 0x12fe49a6, 0x130d71eb, 0x19b5bf3f,
+ 0x19b20111, 0x13127de0, 0x13219d53, 0x19a6c096, 0x19a2fe73, 0x1326a656, 0x1335bcef, 0x1997b21b,
+ 0x1993ec04, 0x133ac2fc, 0x1349d0b0, 0x198893d6, 0x1984c9ce, 0x134ed3c5, 0x135dd88c, 0x197965d0,
+ 0x197597da, 0x1362d8a6, 0x1371d476, 0x196a2815, 0x19665632, 0x1376d191, 0x1385c461, 0x195adaab,
+ 0x195704df, 0x138abe7b, 0x1399a841, 0x194b7d9e, 0x1947a3eb, 0x139e9f56, 0x13ad800a, 0x193c10f7,
+ 0x1938335e, 0x13b27417, 0x13c14bb0, 0x192c94bf, 0x1928b343, 0x13c63cb2, 0x13d50b26, 0x191d08ff,
+ 0x191923a3, 0x13d9f91b, 0x13e8be60, 0x190d6dc1, 0x19098488, 0x13eda944, 0x13fc6553, 0x18fdc310,
+ 0x18f9d5fa, 0x14014d23, 0x140ffff1, 0x18ee08f4, 0x18ea1805, 0x1414e4aa, 0x14238e2f, 0x18de3f77,
+ 0x18da4ab2, 0x14286fce, 0x14371001, 0x18ce66a3, 0x18ca6e0a, 0x143bee83, 0x144a855b, 0x18be7e82,
+ 0x18ba8217, 0x144f60bd, 0x145dee30, 0x18ae871e, 0x18aa86e3, 0x1462c670, 0x14714a76, 0x189e8080,
+ 0x189a7c78, 0x14761f8f, 0x14849a1f, 0x188e6ab2, 0x188a62e0, 0x14896c0f, 0x1497dd20, 0x187e45be,
+ 0x187a3a25, 0x149cabe4, 0x14ab136d, 0x186e11af, 0x186a0250, 0x14afdf03, 0x14be3cfa, 0x185dce8e,
+ 0x1859bb6c, 0x14c3055e, 0x14d159bc, 0x184d7c65, 0x18496583, 0x14d61eeb, 0x14e469a6, 0x183d1b3e,
+ 0x1839009e, 0x14e92b9e, 0x14f76cad, 0x182cab24, 0x18288cc8, 0x14fc2b6a, 0x150a62c6, 0x181c2c20,
+ 0x18180a0c, 0x150f1e45, 0x151d4be3, 0x180b9e3d, 0x18077873, 0x15220422, 0x153027fb, 0x17fb0185,
+ 0x17f6d807, 0x1534dcf6, 0x1542f700, 0x17ea5602, 0x17e628d3, 0x1547a8b5, 0x1555b8e8, 0x17d99bbe,
+ 0x17d56ae0, 0x155a6754, 0x15686da7, 0x17c8d2c4, 0x17c49e3b, 0x156d18c7, 0x157b1532, 0x17b7fb1f,
+ 0x17b3c2ec, 0x157fbd03, 0x158daf7c, 0x17a714d7, 0x17a2d8fe, 0x159253fb, 0x15a03c7a, 0x17961ff9,
+ 0x1791e07b, 0x15a4dda5, 0x15b2bc22, 0x17851c8e, 0x1780d96f, 0x15b759f5, 0x15c52e67, 0x17740aa1,
+ 0x176fc3e3, 0x15c9c8e0, 0x15d7933f, 0x1762ea3d, 0x175e9fe2, 0x15dc2a5a, 0x15e9ea9d, 0x1751bb6b,
+ 0x174d6d77, 0x15ee7e58, 0x15fc3477, 0x17407e37, 0x173c2cac, 0x1600c4cf, 0x160e70c1, 0x172f32ab,
+ 0x172add8c, 0x1612fdb3, 0x16209f70, 0x171dd8d2, 0x17198021, 0x162528fa, 0x1632c078, 0x170c70b7,
+ 0x17081477, 0x16374697, 0x1644d3d0, 0x16fafa64, 0x16f69a97, 0x16495680, 0x1656d96a, 0x16e975e4,
+ 0x16e5128e, 0x165b58aa, 0x1668d13e, 0x16d7e341, 0x16d37c65, 0x166d4d0a, 0x167abb3e, 0x16c64288,
+ 0x16c1d827, 0x167f3394, 0x168c9760, 0x16b493c2, 0x16b025e0, 0x16910c3d, 0x169e659a, 0x16a2d6fb
+};
+
+const int twidTab512[8*6 + 32*6 + 128*6] = {
+ 0x20000000, 0x00000000, 0x1d906bcf, 0x0c3ef153, 0x16a09e66, 0x16a09e66, 0x0c3ef153, 0x1d906bcf,
+ 0x20000000, 0x00000000, 0x1f6297d0, 0x063e2e0f, 0x1d906bcf, 0x0c3ef153, 0x1a9b6629, 0x11c73b3a,
+ 0x20000000, 0x00000000, 0x1a9b6629, 0x11c73b3a, 0x0c3ef153, 0x1d906bcf, 0xf9c1d1f1, 0x1f6297d0,
+ 0x00000000, 0x20000000, 0xf3c10ead, 0x1d906bcf, 0xe95f619a, 0x16a09e66, 0xe26f9431, 0x0c3ef153,
+ 0x16a09e66, 0x16a09e66, 0x11c73b3a, 0x1a9b6629, 0x0c3ef153, 0x1d906bcf, 0x063e2e0f, 0x1f6297d0,
+ 0xe95f619a, 0x16a09e66, 0xe09d6830, 0x063e2e0f, 0xe26f9431, 0xf3c10ead, 0xee38c4c6, 0xe56499d7,
+
+ 0x20000000, 0x00000000, 0x1fd88da4, 0x0322f4d8, 0x1f6297d0, 0x063e2e0f, 0x1e9f4157, 0x094a0317,
+ 0x20000000, 0x00000000, 0x1ff621e3, 0x0191f65f, 0x1fd88da4, 0x0322f4d8, 0x1fa7557f, 0x04b2041c,
+ 0x20000000, 0x00000000, 0x1fa7557f, 0x04b2041c, 0x1e9f4157, 0x094a0317, 0x1ced7af4, 0x0dae8805,
+ 0x1d906bcf, 0x0c3ef153, 0x1c38b2f2, 0x0f15ae9c, 0x1a9b6629, 0x11c73b3a, 0x18bc806b, 0x144cf325,
+ 0x1f6297d0, 0x063e2e0f, 0x1f0a7efc, 0x07c67e5f, 0x1e9f4157, 0x094a0317, 0x1e212105, 0x0ac7cd3b,
+ 0x1a9b6629, 0x11c73b3a, 0x17b5df22, 0x157d6935, 0x144cf325, 0x18bc806b, 0x10738799, 0x1b728345,
+ 0x16a09e66, 0x16a09e66, 0x144cf325, 0x18bc806b, 0x11c73b3a, 0x1a9b6629, 0x0f15ae9c, 0x1c38b2f2,
+ 0x1d906bcf, 0x0c3ef153, 0x1ced7af4, 0x0dae8805, 0x1c38b2f2, 0x0f15ae9c, 0x1b728345, 0x10738799,
+ 0x0c3ef153, 0x1d906bcf, 0x07c67e5f, 0x1f0a7efc, 0x0322f4d8, 0x1fd88da4, 0xfe6e09a1, 0x1ff621e3,
+ 0x0c3ef153, 0x1d906bcf, 0x094a0317, 0x1e9f4157, 0x063e2e0f, 0x1f6297d0, 0x0322f4d8, 0x1fd88da4,
+ 0x1a9b6629, 0x11c73b3a, 0x19b3e048, 0x130ff7fd, 0x18bc806b, 0x144cf325, 0x17b5df22, 0x157d6935,
+ 0xf9c1d1f1, 0x1f6297d0, 0xf53832c5, 0x1e212105, 0xf0ea5164, 0x1c38b2f2, 0xecf00803, 0x19b3e048,
+ 0x00000000, 0x20000000, 0xfcdd0b28, 0x1fd88da4, 0xf9c1d1f1, 0x1f6297d0, 0xf6b5fce9, 0x1e9f4157,
+ 0x16a09e66, 0x16a09e66, 0x157d6935, 0x17b5df22, 0x144cf325, 0x18bc806b, 0x130ff7fd, 0x19b3e048,
+ 0xe95f619a, 0x16a09e66, 0xe64c1fb8, 0x130ff7fd, 0xe3c74d0e, 0x0f15ae9c, 0xe1dedefb, 0x0ac7cd3b,
+ 0xf3c10ead, 0x1d906bcf, 0xf0ea5164, 0x1c38b2f2, 0xee38c4c6, 0x1a9b6629, 0xebb30cdb, 0x18bc806b,
+ 0x11c73b3a, 0x1a9b6629, 0x10738799, 0x1b728345, 0x0f15ae9c, 0x1c38b2f2, 0x0dae8805, 0x1ced7af4,
+ 0xe09d6830, 0x063e2e0f, 0xe009de1d, 0x0191f65f, 0xe027725c, 0xfcdd0b28, 0xe0f58104, 0xf83981a1,
+ 0xe95f619a, 0x16a09e66, 0xe7437f95, 0x144cf325, 0xe56499d7, 0x11c73b3a, 0xe3c74d0e, 0x0f15ae9c,
+ 0x0c3ef153, 0x1d906bcf, 0x0ac7cd3b, 0x1e212105, 0x094a0317, 0x1e9f4157, 0x07c67e5f, 0x1f0a7efc,
+ 0xe26f9431, 0xf3c10ead, 0xe48d7cbb, 0xef8c7867, 0xe7437f95, 0xebb30cdb, 0xea8296cb, 0xe84a20de,
+ 0xe26f9431, 0x0c3ef153, 0xe160bea9, 0x094a0317, 0xe09d6830, 0x063e2e0f, 0xe027725c, 0x0322f4d8,
+ 0x063e2e0f, 0x1f6297d0, 0x04b2041c, 0x1fa7557f, 0x0322f4d8, 0x1fd88da4, 0x0191f65f, 0x1ff621e3,
+ 0xee38c4c6, 0xe56499d7, 0xf25177fb, 0xe312850c, 0xf6b5fce9, 0xe160bea9, 0xfb4dfbe4, 0xe058aa81,
+
+ 0x20000000, 0x00000000, 0x1ffd8861, 0x00c90ab0, 0x1ff621e3, 0x0191f65f, 0x1fe9cdad, 0x025aa412,
+ 0x20000000, 0x00000000, 0x1fff6217, 0x00648748, 0x1ffd8861, 0x00c90ab0, 0x1ffa72f0, 0x012d8657,
+ 0x20000000, 0x00000000, 0x1ffa72f0, 0x012d8657, 0x1fe9cdad, 0x025aa412, 0x1fce15fd, 0x0386f0b9,
+ 0x1fd88da4, 0x0322f4d8, 0x1fc26471, 0x03eac9cb, 0x1fa7557f, 0x04b2041c, 0x1f8764fa, 0x05788511,
+ 0x1ff621e3, 0x0191f65f, 0x1ff09566, 0x01f656e8, 0x1fe9cdad, 0x025aa412, 0x1fe1cafd, 0x02beda01,
+ 0x1fa7557f, 0x04b2041c, 0x1f7599a4, 0x05db7678, 0x1f38f3ac, 0x0702e09b, 0x1ef178a4, 0x0827dc07,
+ 0x1f6297d0, 0x063e2e0f, 0x1f38f3ac, 0x0702e09b, 0x1f0a7efc, 0x07c67e5f, 0x1ed740e7, 0x0888e931,
+ 0x1fd88da4, 0x0322f4d8, 0x1fce15fd, 0x0386f0b9, 0x1fc26471, 0x03eac9cb, 0x1fb57972, 0x044e7c34,
+ 0x1e9f4157, 0x094a0317, 0x1e426a4b, 0x0a68f121, 0x1ddb13b7, 0x0b844298, 0x1d696174, 0x0c9b9532,
+ 0x1e9f4157, 0x094a0317, 0x1e6288ec, 0x0a09ae4a, 0x1e212105, 0x0ac7cd3b, 0x1ddb13b7, 0x0b844298,
+ 0x1fa7557f, 0x04b2041c, 0x1f97f925, 0x05155dac, 0x1f8764fa, 0x05788511, 0x1f7599a4, 0x05db7678,
+ 0x1ced7af4, 0x0dae8805, 0x1c678b35, 0x0ebcbbae, 0x1bd7c0ac, 0x0fc5d26e, 0x1b3e4d3f, 0x10c9704d,
+ 0x1d906bcf, 0x0c3ef153, 0x1d4134d1, 0x0cf7bca2, 0x1ced7af4, 0x0dae8805, 0x1c954b21, 0x0e63374d,
+ 0x1f6297d0, 0x063e2e0f, 0x1f4e603b, 0x06a0a809, 0x1f38f3ac, 0x0702e09b, 0x1f2252f7, 0x0764d3f9,
+ 0x1a9b6629, 0x11c73b3a, 0x19ef43ef, 0x12bedb26, 0x193a224a, 0x13affa29, 0x187c4010, 0x149a449c,
+ 0x1c38b2f2, 0x0f15ae9c, 0x1bd7c0ac, 0x0fc5d26e, 0x1b728345, 0x10738799, 0x1b090a58, 0x111eb354,
+ 0x1f0a7efc, 0x07c67e5f, 0x1ef178a4, 0x0827dc07, 0x1ed740e7, 0x0888e931, 0x1ebbd8c9, 0x08e9a220,
+ 0x17b5df22, 0x157d6935, 0x16e74455, 0x16591926, 0x1610b755, 0x172d0838, 0x15328293, 0x17f8ece3,
+ 0x1a9b6629, 0x11c73b3a, 0x1a29a7a0, 0x126d054d, 0x19b3e048, 0x130ff7fd, 0x193a224a, 0x13affa29,
+ 0x1e9f4157, 0x094a0317, 0x1e817bab, 0x09aa0861, 0x1e6288ec, 0x0a09ae4a, 0x1e426a4b, 0x0a68f121,
+ 0x144cf325, 0x18bc806b, 0x136058b1, 0x19777ef5, 0x126d054d, 0x1a29a7a0, 0x11734d64, 0x1ad2bc9e,
+ 0x18bc806b, 0x144cf325, 0x183b0e0c, 0x14e6cabc, 0x17b5df22, 0x157d6935, 0x172d0838, 0x1610b755,
+ 0x1e212105, 0x0ac7cd3b, 0x1dfeae62, 0x0b263eef, 0x1ddb13b7, 0x0b844298, 0x1db65262, 0x0be1d499,
+ 0x10738799, 0x1b728345, 0x0f6e0ca9, 0x1c08c426, 0x0e63374d, 0x1c954b21, 0x0d536416, 0x1d17e774,
+ 0x16a09e66, 0x16a09e66, 0x1610b755, 0x172d0838, 0x157d6935, 0x17b5df22, 0x14e6cabc, 0x183b0e0c,
+ 0x1d906bcf, 0x0c3ef153, 0x1d696174, 0x0c9b9532, 0x1d4134d1, 0x0cf7bca2, 0x1d17e774, 0x0d536416,
+ 0x0c3ef153, 0x1d906bcf, 0x0b263eef, 0x1dfeae62, 0x0a09ae4a, 0x1e6288ec, 0x08e9a220, 0x1ebbd8c9,
+ 0x144cf325, 0x18bc806b, 0x13affa29, 0x193a224a, 0x130ff7fd, 0x19b3e048, 0x126d054d, 0x1a29a7a0,
+ 0x1ced7af4, 0x0dae8805, 0x1cc1f0f4, 0x0e0924ec, 0x1c954b21, 0x0e63374d, 0x1c678b35, 0x0ebcbbae,
+ 0x07c67e5f, 0x1f0a7efc, 0x06a0a809, 0x1f4e603b, 0x05788511, 0x1f8764fa, 0x044e7c34, 0x1fb57972,
+ 0x11c73b3a, 0x1a9b6629, 0x111eb354, 0x1b090a58, 0x10738799, 0x1b728345, 0x0fc5d26e, 0x1bd7c0ac,
+ 0x1c38b2f2, 0x0f15ae9c, 0x1c08c426, 0x0f6e0ca9, 0x1bd7c0ac, 0x0fc5d26e, 0x1ba5aa67, 0x101cfc87,
+ 0x0322f4d8, 0x1fd88da4, 0x01f656e8, 0x1ff09566, 0x00c90ab0, 0x1ffd8861, 0xff9b78b8, 0x1fff6217,
+ 0x0f15ae9c, 0x1c38b2f2, 0x0e63374d, 0x1c954b21, 0x0dae8805, 0x1ced7af4, 0x0cf7bca2, 0x1d4134d1,
+ 0x1b728345, 0x10738799, 0x1b3e4d3f, 0x10c9704d, 0x1b090a58, 0x111eb354, 0x1ad2bc9e, 0x11734d64,
+ 0xfe6e09a1, 0x1ff621e3, 0xfd4125ff, 0x1fe1cafd, 0xfc153635, 0x1fc26471, 0xfaeaa254, 0x1f97f925,
+ 0x0c3ef153, 0x1d906bcf, 0x0b844298, 0x1ddb13b7, 0x0ac7cd3b, 0x1e212105, 0x0a09ae4a, 0x1e6288ec,
+ 0x1a9b6629, 0x11c73b3a, 0x1a63091b, 0x121a7999, 0x1a29a7a0, 0x126d054d, 0x19ef43ef, 0x12bedb26,
+ 0xf9c1d1f1, 0x1f6297d0, 0xf89b2c07, 0x1f2252f7, 0xf77716cf, 0x1ed740e7, 0xf655f79f, 0x1e817bab,
+ 0x094a0317, 0x1e9f4157, 0x0888e931, 0x1ed740e7, 0x07c67e5f, 0x1f0a7efc, 0x0702e09b, 0x1f38f3ac,
+ 0x19b3e048, 0x130ff7fd, 0x19777ef5, 0x136058b1, 0x193a224a, 0x13affa29, 0x18fbcca4, 0x13fed953,
+ 0xf53832c5, 0x1e212105, 0xf41e2b67, 0x1db65262, 0xf308435e, 0x1d4134d1, 0xf1f6db14, 0x1cc1f0f4,
+ 0x063e2e0f, 0x1f6297d0, 0x05788511, 0x1f8764fa, 0x04b2041c, 0x1fa7557f, 0x03eac9cb, 0x1fc26471,
+ 0x18bc806b, 0x144cf325, 0x187c4010, 0x149a449c, 0x183b0e0c, 0x14e6cabc, 0x17f8ece3, 0x15328293,
+ 0xf0ea5164, 0x1c38b2f2, 0xefe30379, 0x1ba5aa67, 0xeee14cac, 0x1b090a58, 0xede58667, 0x1a63091b,
+ 0x0322f4d8, 0x1fd88da4, 0x025aa412, 0x1fe9cdad, 0x0191f65f, 0x1ff621e3, 0x00c90ab0, 0x1ffd8861,
+ 0x17b5df22, 0x157d6935, 0x1771e75f, 0x15c77bbe, 0x172d0838, 0x1610b755, 0x16e74455, 0x16591926,
+ 0xecf00803, 0x19b3e048, 0xec0126ad, 0x18fbcca4, 0xeb193544, 0x183b0e0c, 0xea388442, 0x1771e75f,
+ 0x00000000, 0x20000000, 0xff36f550, 0x1ffd8861, 0xfe6e09a1, 0x1ff621e3, 0xfda55bee, 0x1fe9cdad,
+ 0x16a09e66, 0x16a09e66, 0x16591926, 0x16e74455, 0x1610b755, 0x172d0838, 0x15c77bbe, 0x1771e75f,
+ 0xe95f619a, 0x16a09e66, 0xe88e18a1, 0x15c77bbe, 0xe7c4f1f4, 0x14e6cabc, 0xe704335c, 0x13fed953,
+ 0xfcdd0b28, 0x1fd88da4, 0xfc153635, 0x1fc26471, 0xfb4dfbe4, 0x1fa7557f, 0xfa877aef, 0x1f8764fa,
+ 0x157d6935, 0x17b5df22, 0x15328293, 0x17f8ece3, 0x14e6cabc, 0x183b0e0c, 0x149a449c, 0x187c4010,
+ 0xe64c1fb8, 0x130ff7fd, 0xe59cf6e5, 0x121a7999, 0xe4f6f5a8, 0x111eb354, 0xe45a5599, 0x101cfc87,
+ 0xf9c1d1f1, 0x1f6297d0, 0xf8fd1f65, 0x1f38f3ac, 0xf83981a1, 0x1f0a7efc, 0xf77716cf, 0x1ed740e7,
+ 0x144cf325, 0x18bc806b, 0x13fed953, 0x18fbcca4, 0x13affa29, 0x193a224a, 0x136058b1, 0x19777ef5,
+ 0xe3c74d0e, 0x0f15ae9c, 0xe33e0f0c, 0x0e0924ec, 0xe2becb2f, 0x0cf7bca2, 0xe249ad9e, 0x0be1d499,
+ 0xf6b5fce9, 0x1e9f4157, 0xf5f651b6, 0x1e6288ec, 0xf53832c5, 0x1e212105, 0xf47bbd68, 0x1ddb13b7,
+ 0x130ff7fd, 0x19b3e048, 0x12bedb26, 0x19ef43ef, 0x126d054d, 0x1a29a7a0, 0x121a7999, 0x1a63091b,
+ 0xe1dedefb, 0x0ac7cd3b, 0xe17e8455, 0x09aa0861, 0xe128bf19, 0x0888e931, 0xe0ddad09, 0x0764d3f9,
+ 0xf3c10ead, 0x1d906bcf, 0xf308435e, 0x1d4134d1, 0xf25177fb, 0x1ced7af4, 0xf19cc8b3, 0x1c954b21,
+ 0x11c73b3a, 0x1a9b6629, 0x11734d64, 0x1ad2bc9e, 0x111eb354, 0x1b090a58, 0x10c9704d, 0x1b3e4d3f,
+ 0xe09d6830, 0x063e2e0f, 0xe06806db, 0x05155dac, 0xe03d9b8f, 0x03eac9cb, 0xe01e3503, 0x02beda01,
+ 0xf0ea5164, 0x1c38b2f2, 0xf03a2d92, 0x1bd7c0ac, 0xef8c7867, 0x1b728345, 0xeee14cac, 0x1b090a58,
+ 0x10738799, 0x1b728345, 0x101cfc87, 0x1ba5aa67, 0x0fc5d26e, 0x1bd7c0ac, 0x0f6e0ca9, 0x1c08c426,
+ 0xe009de1d, 0x0191f65f, 0xe0009de9, 0x00648748, 0xe002779f, 0xff36f550, 0xe00f6a9a, 0xfe09a918,
+ 0xee38c4c6, 0x1a9b6629, 0xed92fab3, 0x1a29a7a0, 0xecf00803, 0x19b3e048, 0xec5005d7, 0x193a224a,
+ 0x0f15ae9c, 0x1c38b2f2, 0x0ebcbbae, 0x1c678b35, 0x0e63374d, 0x1c954b21, 0x0e0924ec, 0x1cc1f0f4,
+ 0xe027725c, 0xfcdd0b28, 0xe04a868e, 0xfbb183cc, 0xe0789b06, 0xfa877aef, 0xe0b19fc5, 0xf95f57f7,
+ 0xebb30cdb, 0x18bc806b, 0xeb193544, 0x183b0e0c, 0xea8296cb, 0x17b5df22, 0xe9ef48ab, 0x172d0838,
+ 0x0dae8805, 0x1ced7af4, 0x0d536416, 0x1d17e774, 0x0cf7bca2, 0x1d4134d1, 0x0c9b9532, 0x1d696174,
+ 0xe0f58104, 0xf83981a1, 0xe1442737, 0xf7165de0, 0xe19d7714, 0xf5f651b6, 0xe201519e, 0xf4d9c111,
+ 0xe95f619a, 0x16a09e66, 0xe8d2f7c8, 0x1610b755, 0xe84a20de, 0x157d6935, 0xe7c4f1f4, 0x14e6cabc,
+ 0x0c3ef153, 0x1d906bcf, 0x0be1d499, 0x1db65262, 0x0b844298, 0x1ddb13b7, 0x0b263eef, 0x1dfeae62,
+ 0xe26f9431, 0xf3c10ead, 0xe2e8188c, 0xf2ac9bea, 0xe36ab4df, 0xf19cc8b3, 0xe3f73bda, 0xf091f357,
+ 0xe7437f95, 0x144cf325, 0xe6c5ddb6, 0x13affa29, 0xe64c1fb8, 0x130ff7fd, 0xe5d65860, 0x126d054d,
+ 0x0ac7cd3b, 0x1e212105, 0x0a68f121, 0x1e426a4b, 0x0a09ae4a, 0x1e6288ec, 0x09aa0861, 0x1e817bab,
+ 0xe48d7cbb, 0xef8c7867, 0xe52d4362, 0xee8cb29c, 0xe5d65860, 0xed92fab3, 0xe688810b, 0xec9fa74f,
+ 0xe56499d7, 0x11c73b3a, 0xe4f6f5a8, 0x111eb354, 0xe48d7cbb, 0x10738799, 0xe4283f54, 0x0fc5d26e,
+ 0x094a0317, 0x1e9f4157, 0x08e9a220, 0x1ebbd8c9, 0x0888e931, 0x1ed740e7, 0x0827dc07, 0x1ef178a4,
+ 0xe7437f95, 0xebb30cdb, 0xe807131d, 0xeacd7d6d, 0xe8d2f7c8, 0xe9ef48ab, 0xe9a6e6da, 0xe918bbab,
+ 0xe3c74d0e, 0x0f15ae9c, 0xe36ab4df, 0x0e63374d, 0xe312850c, 0x0dae8805, 0xe2becb2f, 0x0cf7bca2,
+ 0x07c67e5f, 0x1f0a7efc, 0x0764d3f9, 0x1f2252f7, 0x0702e09b, 0x1f38f3ac, 0x06a0a809, 0x1f4e603b,
+ 0xea8296cb, 0xe84a20de, 0xeb65bb64, 0xe783bff0, 0xec5005d7, 0xe6c5ddb6, 0xed4124da, 0xe610bc11,
+ 0xe26f9431, 0x0c3ef153, 0xe224ec49, 0x0b844298, 0xe1dedefb, 0x0ac7cd3b, 0xe19d7714, 0x0a09ae4a,
+ 0x063e2e0f, 0x1f6297d0, 0x05db7678, 0x1f7599a4, 0x05788511, 0x1f8764fa, 0x05155dac, 0x1f97f925,
+ 0xee38c4c6, 0xe56499d7, 0xef368fb3, 0xe4c1b2c1, 0xf03a2d92, 0xe4283f54, 0xf1434452, 0xe39874cb,
+ 0xe160bea9, 0x094a0317, 0xe128bf19, 0x0888e931, 0xe0f58104, 0x07c67e5f, 0xe0c70c54, 0x0702e09b,
+ 0x04b2041c, 0x1fa7557f, 0x044e7c34, 0x1fb57972, 0x03eac9cb, 0x1fc26471, 0x0386f0b9, 0x1fce15fd,
+ 0xf25177fb, 0xe312850c, 0xf3646ace, 0xe2969e8c, 0xf47bbd68, 0xe224ec49, 0xf5970edf, 0xe1bd95b5,
+ 0xe09d6830, 0x063e2e0f, 0xe0789b06, 0x05788511, 0xe058aa81, 0x04b2041c, 0xe03d9b8f, 0x03eac9cb,
+ 0x0322f4d8, 0x1fd88da4, 0x02beda01, 0x1fe1cafd, 0x025aa412, 0x1fe9cdad, 0x01f656e8, 0x1ff09566,
+ 0xf6b5fce9, 0xe160bea9, 0xf7d823f9, 0xe10e875c, 0xf8fd1f65, 0xe0c70c54, 0xfa248988, 0xe08a665c,
+ 0xe027725c, 0x0322f4d8, 0xe0163253, 0x025aa412, 0xe009de1d, 0x0191f65f, 0xe002779f, 0x00c90ab0,
+ 0x0191f65f, 0x1ff621e3, 0x012d8657, 0x1ffa72f0, 0x00c90ab0, 0x1ffd8861, 0x00648748, 0x1fff6217,
+ 0xfb4dfbe4, 0xe058aa81, 0xfc790f47, 0xe031ea03, 0xfda55bee, 0xe0163253, 0xfed279a9, 0xe0058d10
+};
+
+const int twidTab64[4*6 + 16*6] = {
+ 0x20000000, 0x00000000, 0x16a09e66, 0x16a09e66, 0x00000000, 0x20000000, 0xe95f619a, 0x16a09e66,
+ 0x20000000, 0x00000000, 0x1d906bcf, 0x0c3ef153, 0x16a09e66, 0x16a09e66, 0x0c3ef153, 0x1d906bcf,
+ 0x20000000, 0x00000000, 0x0c3ef153, 0x1d906bcf, 0xe95f619a, 0x16a09e66, 0xe26f9431, 0xf3c10ead,
+
+ 0x20000000, 0x00000000, 0x1f6297d0, 0x063e2e0f, 0x1d906bcf, 0x0c3ef153, 0x1a9b6629, 0x11c73b3a,
+ 0x20000000, 0x00000000, 0x1fd88da4, 0x0322f4d8, 0x1f6297d0, 0x063e2e0f, 0x1e9f4157, 0x094a0317,
+ 0x20000000, 0x00000000, 0x1e9f4157, 0x094a0317, 0x1a9b6629, 0x11c73b3a, 0x144cf325, 0x18bc806b,
+ 0x16a09e66, 0x16a09e66, 0x11c73b3a, 0x1a9b6629, 0x0c3ef153, 0x1d906bcf, 0x063e2e0f, 0x1f6297d0,
+ 0x1d906bcf, 0x0c3ef153, 0x1c38b2f2, 0x0f15ae9c, 0x1a9b6629, 0x11c73b3a, 0x18bc806b, 0x144cf325,
+ 0x0c3ef153, 0x1d906bcf, 0x0322f4d8, 0x1fd88da4, 0xf9c1d1f1, 0x1f6297d0, 0xf0ea5164, 0x1c38b2f2,
+ 0x00000000, 0x20000000, 0xf9c1d1f1, 0x1f6297d0, 0xf3c10ead, 0x1d906bcf, 0xee38c4c6, 0x1a9b6629,
+ 0x16a09e66, 0x16a09e66, 0x144cf325, 0x18bc806b, 0x11c73b3a, 0x1a9b6629, 0x0f15ae9c, 0x1c38b2f2,
+ 0xe95f619a, 0x16a09e66, 0xe3c74d0e, 0x0f15ae9c, 0xe09d6830, 0x063e2e0f, 0xe027725c, 0xfcdd0b28,
+ 0xe95f619a, 0x16a09e66, 0xe56499d7, 0x11c73b3a, 0xe26f9431, 0x0c3ef153, 0xe09d6830, 0x063e2e0f,
+ 0x0c3ef153, 0x1d906bcf, 0x094a0317, 0x1e9f4157, 0x063e2e0f, 0x1f6297d0, 0x0322f4d8, 0x1fd88da4,
+ 0xe26f9431, 0xf3c10ead, 0xe7437f95, 0xebb30cdb, 0xee38c4c6, 0xe56499d7, 0xf6b5fce9, 0xe160bea9
+};
+
+#else
+
+/*
+ * Q30 for 128 and 1024
+ *
+ * for (i = 0; i < num/4; i++) {
+ * angle = (i + 0.125) * M_PI / num;
+ * x = cos(angle) * (1 << 30);
+ * x = sin(angle) * (1 << 30);
+ *
+ * angle = (num/2 - 1 - i + 0.125) * M_PI / num;
+ * x = cos(angle) * (1 << 30);
+ * x = sin(angle) * (1 << 30);
+ * }
+ */
+const int cossintab[128 + 1024] = {
+ /* 128 */
+ 0x3fffec43, 0x003243f1, 0x015fd4d2, 0x3ffc38d1, 0x3ff9c13a, 0x01c454f5, 0x02f1b755, 0x3feea776,
+ 0x3fe9b8a9, 0x03562038, 0x0483259d, 0x3fd73a4a, 0x3fcfd50b, 0x04e767c5, 0x0613e1c5, 0x3fb5f4ea,
+ 0x3fac1a5b, 0x0677edbb, 0x07a3adff, 0x3f8adc77, 0x3f7e8e1e, 0x08077457, 0x09324ca7, 0x3f55f796,
+ 0x3f473759, 0x0995bdfd, 0x0abf8043, 0x3f174e70, 0x3f061e95, 0x0b228d42, 0x0c4b0b94, 0x3eceeaad,
+ 0x3ebb4ddb, 0x0cada4f5, 0x0dd4b19a, 0x3e7cd778, 0x3e66d0b4, 0x0e36c82a, 0x0f5c35a3, 0x3e212179,
+ 0x3e08b42a, 0x0fbdba40, 0x10e15b4e, 0x3dbbd6d4, 0x3da106bd, 0x11423ef0, 0x1263e699, 0x3d4d0728,
+ 0x3d2fd86c, 0x12c41a4f, 0x13e39be9, 0x3cd4c38b, 0x3cb53aaa, 0x144310dd, 0x15604013, 0x3c531e88,
+ 0x3c314060, 0x15bee78c, 0x16d99864, 0x3bc82c1f, 0x3ba3fde7, 0x173763c9, 0x184f6aab, 0x3b3401bb,
+ 0x3b0d8909, 0x18ac4b87, 0x19c17d44, 0x3a96b636, 0x3a6df8f8, 0x1a1d6544, 0x1b2f971e, 0x39f061d2,
+ 0x39c5664f, 0x1b8a7815, 0x1c997fc4, 0x39411e33, 0x3913eb0e, 0x1cf34baf, 0x1dfeff67, 0x38890663,
+ 0x3859a292, 0x1e57a86d, 0x1f5fdee6, 0x37c836c2, 0x3796a996, 0x1fb7575c, 0x20bbe7d8, 0x36fecd0e,
+ 0x36cb1e2a, 0x21122240, 0x2212e492, 0x362ce855, 0x35f71fb1, 0x2267d3a0, 0x2364a02e, 0x3552a8f4,
+ 0x351acedd, 0x23b836ca, 0x24b0e699, 0x34703095, 0x34364da6, 0x250317df, 0x25f78497, 0x3385a222,
+ 0x3349bf48, 0x264843d9, 0x273847c8, 0x329321c7, 0x32554840, 0x27878893, 0x2872feb6, 0x3198d4ea,
+ 0x31590e3e, 0x28c0b4d2, 0x29a778db, 0x3096e223, 0x30553828, 0x29f3984c, 0x2ad586a3, 0x2f8d713a,
+ 0x2f49ee0f, 0x2b2003ac, 0x2bfcf97c, 0x2e7cab1c, 0x2e37592c, 0x2c45c8a0, 0x2d1da3d5, 0x2d64b9da,
+ /* 1024 */
+ 0x3fffffb1, 0x0006487f, 0x002bfb74, 0x3ffff0e3, 0x3fffe705, 0x00388c6e, 0x005e3f4c, 0x3fffba9b,
+ 0x3fffa6de, 0x006ad03b, 0x009082ea, 0x3fff5cd8, 0x3fff3f3c, 0x009d13c5, 0x00c2c62f, 0x3ffed79b,
+ 0x3ffeb021, 0x00cf56ef, 0x00f508fc, 0x3ffe2ae5, 0x3ffdf98c, 0x01019998, 0x01274b31, 0x3ffd56b5,
+ 0x3ffd1b7e, 0x0133dba3, 0x01598cb1, 0x3ffc5b0c, 0x3ffc15f7, 0x01661cf0, 0x018bcd5b, 0x3ffb37ec,
+ 0x3ffae8f9, 0x01985d60, 0x01be0d11, 0x3ff9ed53, 0x3ff99483, 0x01ca9cd4, 0x01f04bb4, 0x3ff87b44,
+ 0x3ff81896, 0x01fcdb2e, 0x02228924, 0x3ff6e1bf, 0x3ff67534, 0x022f184d, 0x0254c544, 0x3ff520c5,
+ 0x3ff4aa5d, 0x02615414, 0x0286fff3, 0x3ff33858, 0x3ff2b813, 0x02938e62, 0x02b93914, 0x3ff12878,
+ 0x3ff09e56, 0x02c5c71a, 0x02eb7086, 0x3feef126, 0x3fee5d28, 0x02f7fe1c, 0x031da62b, 0x3fec9265,
+ 0x3febf48b, 0x032a3349, 0x034fd9e5, 0x3fea0c35, 0x3fe96480, 0x035c6682, 0x03820b93, 0x3fe75e98,
+ 0x3fe6ad08, 0x038e97a9, 0x03b43b17, 0x3fe48990, 0x3fe3ce26, 0x03c0c69e, 0x03e66852, 0x3fe18d1f,
+ 0x3fe0c7da, 0x03f2f342, 0x04189326, 0x3fde6945, 0x3fdd9a27, 0x04251d77, 0x044abb73, 0x3fdb1e06,
+ 0x3fda450f, 0x0457451d, 0x047ce11a, 0x3fd7ab64, 0x3fd6c894, 0x04896a16, 0x04af03fc, 0x3fd4115f,
+ 0x3fd324b7, 0x04bb8c42, 0x04e123fa, 0x3fd04ffc, 0x3fcf597c, 0x04edab83, 0x051340f6, 0x3fcc673b,
+ 0x3fcb66e4, 0x051fc7b9, 0x05455ad1, 0x3fc8571f, 0x3fc74cf3, 0x0551e0c7, 0x0577716b, 0x3fc41fac,
+ 0x3fc30baa, 0x0583f68c, 0x05a984a6, 0x3fbfc0e3, 0x3fbea30c, 0x05b608eb, 0x05db9463, 0x3fbb3ac7,
+ 0x3fba131b, 0x05e817c3, 0x060da083, 0x3fb68d5b, 0x3fb55bdc, 0x061a22f7, 0x063fa8e7, 0x3fb1b8a2,
+ 0x3fb07d50, 0x064c2a67, 0x0671ad71, 0x3facbc9f, 0x3fab777b, 0x067e2df5, 0x06a3ae00, 0x3fa79954,
+ 0x3fa64a5f, 0x06b02d81, 0x06d5aa77, 0x3fa24ec6, 0x3fa0f600, 0x06e228ee, 0x0707a2b7, 0x3f9cdcf7,
+ 0x3f9b7a62, 0x0714201b, 0x073996a1, 0x3f9743eb, 0x3f95d787, 0x074612eb, 0x076b8616, 0x3f9183a5,
+ 0x3f900d72, 0x0778013d, 0x079d70f7, 0x3f8b9c28, 0x3f8a1c29, 0x07a9eaf5, 0x07cf5726, 0x3f858d79,
+ 0x3f8403ae, 0x07dbcff2, 0x08013883, 0x3f7f579b, 0x3f7dc405, 0x080db016, 0x083314f1, 0x3f78fa92,
+ 0x3f775d31, 0x083f8b43, 0x0864ec4f, 0x3f727661, 0x3f70cf38, 0x08716159, 0x0896be80, 0x3f6bcb0e,
+ 0x3f6a1a1c, 0x08a3323a, 0x08c88b65, 0x3f64f89b, 0x3f633de2, 0x08d4fdc6, 0x08fa52de, 0x3f5dff0e,
+ 0x3f5c3a8f, 0x0906c3e0, 0x092c14ce, 0x3f56de6a, 0x3f551026, 0x09388469, 0x095dd116, 0x3f4f96b4,
+ 0x3f4dbeac, 0x096a3f42, 0x098f8796, 0x3f4827f0, 0x3f464626, 0x099bf44c, 0x09c13831, 0x3f409223,
+ 0x3f3ea697, 0x09cda368, 0x09f2e2c7, 0x3f38d552, 0x3f36e006, 0x09ff4c78, 0x0a24873a, 0x3f30f181,
+ 0x3f2ef276, 0x0a30ef5e, 0x0a56256c, 0x3f28e6b6, 0x3f26ddec, 0x0a628bfa, 0x0a87bd3d, 0x3f20b4f5,
+ 0x3f1ea26e, 0x0a94222f, 0x0ab94e8f, 0x3f185c43, 0x3f164001, 0x0ac5b1dc, 0x0aead944, 0x3f0fdca5,
+ 0x3f0db6a9, 0x0af73ae5, 0x0b1c5d3d, 0x3f073621, 0x3f05066d, 0x0b28bd2a, 0x0b4dda5c, 0x3efe68bc,
+ 0x3efc2f50, 0x0b5a388d, 0x0b7f5081, 0x3ef5747b, 0x3ef3315a, 0x0b8bacf0, 0x0bb0bf8f, 0x3eec5965,
+ 0x3eea0c8e, 0x0bbd1a33, 0x0be22766, 0x3ee3177e, 0x3ee0c0f4, 0x0bee8038, 0x0c1387e9, 0x3ed9aecc,
+ 0x3ed74e91, 0x0c1fdee1, 0x0c44e0f9, 0x3ed01f55, 0x3ecdb56a, 0x0c513610, 0x0c763278, 0x3ec66920,
+ 0x3ec3f585, 0x0c8285a5, 0x0ca77c47, 0x3ebc8c31, 0x3eba0ee9, 0x0cb3cd84, 0x0cd8be47, 0x3eb2888f,
+ 0x3eb0019c, 0x0ce50d8c, 0x0d09f85b, 0x3ea85e41, 0x3ea5cda3, 0x0d1645a0, 0x0d3b2a64, 0x3e9e0d4c,
+ 0x3e9b7306, 0x0d4775a1, 0x0d6c5443, 0x3e9395b7, 0x3e90f1ca, 0x0d789d71, 0x0d9d75db, 0x3e88f788,
+ 0x3e8649f5, 0x0da9bcf2, 0x0dce8f0d, 0x3e7e32c6, 0x3e7b7b90, 0x0ddad406, 0x0dff9fba, 0x3e734778,
+ 0x3e70869f, 0x0e0be28e, 0x0e30a7c5, 0x3e6835a4, 0x3e656b2b, 0x0e3ce86b, 0x0e61a70f, 0x3e5cfd51,
+ 0x3e5a2939, 0x0e6de580, 0x0e929d7a, 0x3e519e86, 0x3e4ec0d1, 0x0e9ed9af, 0x0ec38ae8, 0x3e46194a,
+ 0x3e4331fa, 0x0ecfc4d9, 0x0ef46f3b, 0x3e3a6da4, 0x3e377cbb, 0x0f00a6df, 0x0f254a53, 0x3e2e9b9c,
+ 0x3e2ba11b, 0x0f317fa5, 0x0f561c15, 0x3e22a338, 0x3e1f9f21, 0x0f624f0c, 0x0f86e460, 0x3e168480,
+ 0x3e1376d5, 0x0f9314f5, 0x0fb7a317, 0x3e0a3f7b, 0x3e07283f, 0x0fc3d143, 0x0fe8581d, 0x3dfdd432,
+ 0x3dfab365, 0x0ff483d7, 0x10190352, 0x3df142ab, 0x3dee1851, 0x10252c94, 0x1049a49a, 0x3de48aef,
+ 0x3de15708, 0x1055cb5b, 0x107a3bd5, 0x3dd7ad05, 0x3dd46f94, 0x1086600e, 0x10aac8e6, 0x3dcaa8f5,
+ 0x3dc761fc, 0x10b6ea90, 0x10db4baf, 0x3dbd7ec7, 0x3dba2e48, 0x10e76ac3, 0x110bc413, 0x3db02e84,
+ 0x3dacd481, 0x1117e088, 0x113c31f3, 0x3da2b834, 0x3d9f54af, 0x11484bc2, 0x116c9531, 0x3d951bde,
+ 0x3d91aed9, 0x1178ac53, 0x119cedaf, 0x3d87598c, 0x3d83e309, 0x11a9021d, 0x11cd3b50, 0x3d797145,
+ 0x3d75f147, 0x11d94d02, 0x11fd7df6, 0x3d6b6313, 0x3d67d99b, 0x12098ce5, 0x122db583, 0x3d5d2efe,
+ 0x3d599c0e, 0x1239c1a7, 0x125de1da, 0x3d4ed50f, 0x3d4b38aa, 0x1269eb2b, 0x128e02dc, 0x3d40554e,
+ 0x3d3caf76, 0x129a0954, 0x12be186c, 0x3d31afc5, 0x3d2e007c, 0x12ca1c03, 0x12ee226c, 0x3d22e47c,
+ 0x3d1f2bc5, 0x12fa231b, 0x131e20c0, 0x3d13f37e, 0x3d10315a, 0x132a1e7e, 0x134e1348, 0x3d04dcd2,
+ 0x3d011145, 0x135a0e0e, 0x137df9e7, 0x3cf5a082, 0x3cf1cb8e, 0x1389f1af, 0x13add481, 0x3ce63e98,
+ 0x3ce2603f, 0x13b9c943, 0x13dda2f7, 0x3cd6b71e, 0x3cd2cf62, 0x13e994ab, 0x140d652c, 0x3cc70a1c,
+ 0x3cc318ff, 0x141953cb, 0x143d1b02, 0x3cb7379c, 0x3cb33d22, 0x14490685, 0x146cc45c, 0x3ca73fa9,
+ 0x3ca33bd3, 0x1478acbc, 0x149c611d, 0x3c97224c, 0x3c93151d, 0x14a84652, 0x14cbf127, 0x3c86df8e,
+ 0x3c82c909, 0x14d7d32a, 0x14fb745e, 0x3c76777b, 0x3c7257a2, 0x15075327, 0x152aeaa3, 0x3c65ea1c,
+ 0x3c61c0f1, 0x1536c62b, 0x155a53d9, 0x3c55377b, 0x3c510501, 0x15662c18, 0x1589afe3, 0x3c445fa2,
+ 0x3c4023dd, 0x159584d3, 0x15b8fea4, 0x3c33629d, 0x3c2f1d8e, 0x15c4d03e, 0x15e83fff, 0x3c224075,
+ 0x3c1df21f, 0x15f40e3a, 0x161773d6, 0x3c10f935, 0x3c0ca19b, 0x16233eac, 0x16469a0d, 0x3bff8ce8,
+ 0x3bfb2c0c, 0x16526176, 0x1675b286, 0x3bedfb99, 0x3be9917e, 0x1681767c, 0x16a4bd25, 0x3bdc4552,
+ 0x3bd7d1fa, 0x16b07d9f, 0x16d3b9cc, 0x3bca6a1d, 0x3bc5ed8d, 0x16df76c3, 0x1702a85e, 0x3bb86a08,
+ 0x3bb3e440, 0x170e61cc, 0x173188be, 0x3ba6451b, 0x3ba1b620, 0x173d3e9b, 0x17605ad0, 0x3b93fb63,
+ 0x3b8f6337, 0x176c0d15, 0x178f1e76, 0x3b818ceb, 0x3b7ceb90, 0x179acd1c, 0x17bdd394, 0x3b6ef9be,
+ 0x3b6a4f38, 0x17c97e93, 0x17ec7a0d, 0x3b5c41e8, 0x3b578e39, 0x17f8215e, 0x181b11c4, 0x3b496574,
+ 0x3b44a8a0, 0x1826b561, 0x18499a9d, 0x3b36646e, 0x3b319e77, 0x18553a7d, 0x1878147a, 0x3b233ee1,
+ 0x3b1e6fca, 0x1883b097, 0x18a67f3f, 0x3b0ff4d9, 0x3b0b1ca6, 0x18b21791, 0x18d4dad0, 0x3afc8663,
+ 0x3af7a516, 0x18e06f50, 0x1903270f, 0x3ae8f38b, 0x3ae40926, 0x190eb7b7, 0x193163e1, 0x3ad53c5b,
+ 0x3ad048e3, 0x193cf0a9, 0x195f9128, 0x3ac160e1, 0x3abc6458, 0x196b1a09, 0x198daec8, 0x3aad6129,
+ 0x3aa85b92, 0x199933bb, 0x19bbbca6, 0x3a993d3e, 0x3a942e9d, 0x19c73da3, 0x19e9baa3, 0x3a84f52f,
+ 0x3a7fdd86, 0x19f537a4, 0x1a17a8a5, 0x3a708906, 0x3a6b6859, 0x1a2321a2, 0x1a45868e, 0x3a5bf8d1,
+ 0x3a56cf23, 0x1a50fb81, 0x1a735442, 0x3a47449c, 0x3a4211f0, 0x1a7ec524, 0x1aa111a6, 0x3a326c74,
+ 0x3a2d30cd, 0x1aac7e6f, 0x1acebe9d, 0x3a1d7066, 0x3a182bc8, 0x1ada2746, 0x1afc5b0a, 0x3a08507f,
+ 0x3a0302ed, 0x1b07bf8c, 0x1b29e6d2, 0x39f30ccc, 0x39edb649, 0x1b354727, 0x1b5761d8, 0x39dda55a,
+ 0x39d845e9, 0x1b62bdf8, 0x1b84cc01, 0x39c81a36, 0x39c2b1da, 0x1b9023e5, 0x1bb22530, 0x39b26b6d,
+ 0x39acfa2b, 0x1bbd78d2, 0x1bdf6d4a, 0x399c990d, 0x39971ee7, 0x1beabca1, 0x1c0ca432, 0x3986a324,
+ 0x3981201e, 0x1c17ef39, 0x1c39c9cd, 0x397089bf, 0x396afddc, 0x1c45107c, 0x1c66ddfe, 0x395a4ceb,
+ 0x3954b82e, 0x1c72204f, 0x1c93e0ab, 0x3943ecb6, 0x393e4f23, 0x1c9f1e96, 0x1cc0d1b6, 0x392d692f,
+ 0x3927c2c9, 0x1ccc0b35, 0x1cedb106, 0x3916c262, 0x3911132d, 0x1cf8e611, 0x1d1a7e7d, 0x38fff85e,
+ 0x38fa405e, 0x1d25af0d, 0x1d473a00, 0x38e90b31, 0x38e34a69, 0x1d52660f, 0x1d73e374, 0x38d1fae9,
+ 0x38cc315d, 0x1d7f0afb, 0x1da07abc, 0x38bac795, 0x38b4f547, 0x1dab9db5, 0x1dccffbf, 0x38a37142,
+ 0x389d9637, 0x1dd81e21, 0x1df9725f, 0x388bf7ff, 0x3886143b, 0x1e048c24, 0x1e25d282, 0x38745bdb,
+ 0x386e6f60, 0x1e30e7a4, 0x1e52200c, 0x385c9ce3, 0x3856a7b6, 0x1e5d3084, 0x1e7e5ae2, 0x3844bb28,
+ 0x383ebd4c, 0x1e8966a8, 0x1eaa82e9, 0x382cb6b7, 0x3826b030, 0x1eb589f7, 0x1ed69805, 0x38148f9f,
+ 0x380e8071, 0x1ee19a54, 0x1f029a1c, 0x37fc45ef, 0x37f62e1d, 0x1f0d97a5, 0x1f2e8911, 0x37e3d9b7,
+ 0x37ddb945, 0x1f3981ce, 0x1f5a64cb, 0x37cb4b04, 0x37c521f6, 0x1f6558b5, 0x1f862d2d, 0x37b299e7,
+ 0x37ac6841, 0x1f911c3d, 0x1fb1e21d, 0x3799c66f, 0x37938c34, 0x1fbccc4d, 0x1fdd8381, 0x3780d0aa,
+ 0x377a8ddf, 0x1fe868c8, 0x2009113c, 0x3767b8a9, 0x37616d51, 0x2013f196, 0x20348b35, 0x374e7e7b,
+ 0x37482a9a, 0x203f6699, 0x205ff14f, 0x3735222f, 0x372ec5c9, 0x206ac7b8, 0x208b4372, 0x371ba3d4,
+ 0x37153eee, 0x209614d9, 0x20b68181, 0x3702037c, 0x36fb9618, 0x20c14ddf, 0x20e1ab63, 0x36e84135,
+ 0x36e1cb58, 0x20ec72b1, 0x210cc0fc, 0x36ce5d10, 0x36c7debd, 0x21178334, 0x2137c232, 0x36b4571b,
+ 0x36add058, 0x21427f4d, 0x2162aeea, 0x369a2f69, 0x3693a038, 0x216d66e2, 0x218d870b, 0x367fe608,
+ 0x36794e6e, 0x219839d8, 0x21b84a79, 0x36657b08, 0x365edb09, 0x21c2f815, 0x21e2f91a, 0x364aee7b,
+ 0x3644461b, 0x21eda17f, 0x220d92d4, 0x36304070, 0x36298fb4, 0x221835fb, 0x2238178d, 0x361570f8,
+ 0x360eb7e3, 0x2242b56f, 0x22628729, 0x35fa8023, 0x35f3beba, 0x226d1fc1, 0x228ce191, 0x35df6e03,
+ 0x35d8a449, 0x229774d7, 0x22b726a8, 0x35c43aa7, 0x35bd68a1, 0x22c1b496, 0x22e15655, 0x35a8e621,
+ 0x35a20bd3, 0x22ebdee5, 0x230b707e, 0x358d7081, 0x35868def, 0x2315f3a8, 0x23357509, 0x3571d9d9,
+ 0x356aef08, 0x233ff2c8, 0x235f63dc, 0x35562239, 0x354f2f2c, 0x2369dc29, 0x23893cdd, 0x353a49b2,
+ 0x35334e6f, 0x2393afb2, 0x23b2fff3, 0x351e5056, 0x35174ce0, 0x23bd6d48, 0x23dcad03, 0x35023636,
+ 0x34fb2a92, 0x23e714d3, 0x240643f4, 0x34e5fb63, 0x34dee795, 0x2410a639, 0x242fc4ad, 0x34c99fef,
+ 0x34c283fb, 0x243a215f, 0x24592f13, 0x34ad23eb, 0x34a5ffd5, 0x2463862c, 0x2482830d, 0x34908768,
+ 0x34895b36, 0x248cd487, 0x24abc082, 0x3473ca79, 0x346c962f, 0x24b60c57, 0x24d4e757, 0x3456ed2f,
+ 0x344fb0d1, 0x24df2d81, 0x24fdf775, 0x3439ef9c, 0x3432ab2e, 0x250837ed, 0x2526f0c1, 0x341cd1d2,
+ 0x34158559, 0x25312b81, 0x254fd323, 0x33ff93e2, 0x33f83f62, 0x255a0823, 0x25789e80, 0x33e235df,
+ 0x33dad95e, 0x2582cdbc, 0x25a152c0, 0x33c4b7db, 0x33bd535c, 0x25ab7c30, 0x25c9efca, 0x33a719e8,
+ 0x339fad70, 0x25d41369, 0x25f27584, 0x33895c18, 0x3381e7ac, 0x25fc934b, 0x261ae3d6, 0x336b7e7e,
+ 0x33640223, 0x2624fbbf, 0x26433aa7, 0x334d812d, 0x3345fce6, 0x264d4cac, 0x266b79dd, 0x332f6435,
+ 0x3327d808, 0x267585f8, 0x2693a161, 0x331127ab, 0x3309939c, 0x269da78b, 0x26bbb119, 0x32f2cba1,
+ 0x32eb2fb5, 0x26c5b14c, 0x26e3a8ec, 0x32d45029, 0x32ccac64, 0x26eda322, 0x270b88c2, 0x32b5b557,
+ 0x32ae09be, 0x27157cf5, 0x27335082, 0x3296fb3d, 0x328f47d5, 0x273d3eac, 0x275b0014, 0x327821ee,
+ 0x327066bc, 0x2764e82f, 0x27829760, 0x3259297d, 0x32516686, 0x278c7965, 0x27aa164c, 0x323a11fe,
+ 0x32324746, 0x27b3f235, 0x27d17cc1, 0x321adb83, 0x3213090f, 0x27db5288, 0x27f8caa5, 0x31fb8620,
+ 0x31f3abf5, 0x28029a45, 0x281fffe2, 0x31dc11e8, 0x31d4300b, 0x2829c954, 0x28471c5e, 0x31bc7eee,
+ 0x31b49564, 0x2850df9d, 0x286e2002, 0x319ccd46, 0x3194dc14, 0x2877dd07, 0x28950ab6, 0x317cfd04,
+ 0x3175042e, 0x289ec17a, 0x28bbdc61, 0x315d0e3b, 0x31550dc6, 0x28c58cdf, 0x28e294eb, 0x313d00ff,
+ 0x3134f8f1, 0x28ec3f1e, 0x2909343e, 0x311cd564, 0x3114c5c0, 0x2912d81f, 0x292fba40, 0x30fc8b7d,
+ 0x30f47449, 0x293957c9, 0x295626da, 0x30dc235e, 0x30d404a0, 0x295fbe06, 0x297c79f5, 0x30bb9d1c,
+ 0x30b376d8, 0x29860abd, 0x29a2b378, 0x309af8ca, 0x3092cb05, 0x29ac3dd7, 0x29c8d34d, 0x307a367c,
+ 0x3072013c, 0x29d2573c, 0x29eed95b, 0x30595648, 0x30511991, 0x29f856d5, 0x2a14c58b, 0x30385840,
+ 0x30301418, 0x2a1e3c8a, 0x2a3a97c7, 0x30173c7a, 0x300ef0e5, 0x2a440844, 0x2a604ff5, 0x2ff6030a,
+ 0x2fedb00d, 0x2a69b9ec, 0x2a85ee00, 0x2fd4ac04, 0x2fcc51a5, 0x2a8f516b, 0x2aab71d0, 0x2fb3377c,
+ 0x2faad5c1, 0x2ab4cea9, 0x2ad0db4e, 0x2f91a589, 0x2f893c75, 0x2ada318e, 0x2af62a63, 0x2f6ff63d,
+ 0x2f6785d7, 0x2aff7a05, 0x2b1b5ef8, 0x2f4e29af, 0x2f45b1fb, 0x2b24a7f6, 0x2b4078f5, 0x2f2c3ff2,
+ 0x2f23c0f6, 0x2b49bb4a, 0x2b657844, 0x2f0a391d, 0x2f01b2de, 0x2b6eb3ea, 0x2b8a5cce, 0x2ee81543,
+ 0x2edf87c6, 0x2b9391c0, 0x2baf267d, 0x2ec5d479, 0x2ebd3fc4, 0x2bb854b4, 0x2bd3d53a, 0x2ea376d6,
+ 0x2e9adaee, 0x2bdcfcb0, 0x2bf868ed, 0x2e80fc6e, 0x2e785958, 0x2c01899e, 0x2c1ce181, 0x2e5e6556,
+ 0x2e55bb17, 0x2c25fb66, 0x2c413edf, 0x2e3bb1a4, 0x2e330042, 0x2c4a51f3, 0x2c6580f1, 0x2e18e16d,
+ 0x2e1028ed, 0x2c6e8d2e, 0x2c89a79f, 0x2df5f4c7, 0x2ded352f, 0x2c92ad01, 0x2cadb2d5, 0x2dd2ebc7,
+ 0x2dca251c, 0x2cb6b155, 0x2cd1a27b, 0x2dafc683, 0x2da6f8ca, 0x2cda9a14, 0x2cf5767c, 0x2d8c8510,
+ 0x2d83b04f, 0x2cfe6728, 0x2d192ec1, 0x2d692784, 0x2d604bc0, 0x2d22187a, 0x2d3ccb34, 0x2d45adf6
+};
+
+const int twidTab512[8*6 + 32*6 + 128*6] = {
+ 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3b20d79e, 0x187de2a6,
+ 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6,
+ 0x187de2a6, 0x3b20d79e, 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f,
+ 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xe7821d5a, 0x3b20d79e,
+ 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e,
+ 0xc4df2862, 0xe7821d5a, 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae,
+
+ 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3fb11b47, 0x0645e9af,
+ 0x3fec43c6, 0x0323ecbe, 0x3f4eaafe, 0x09640837, 0x3ec52f9f, 0x0c7c5c1e, 0x3fb11b47, 0x0645e9af,
+ 0x3d3e82ad, 0x1294062e, 0x3d3e82ad, 0x1294062e, 0x3f4eaafe, 0x09640837, 0x39daf5e8, 0x1b5d1009,
+ 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x387165e3, 0x1e2b5d38,
+ 0x3e14fdf7, 0x0f8cfcbd, 0x2f6bbe44, 0x2afad269, 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e,
+ 0x2899e64a, 0x317900d6, 0x317900d6, 0x2899e64a, 0x3c424209, 0x158f9a75, 0x20e70f32, 0x36e5068a,
+ 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x2899e64a, 0x317900d6,
+ 0x39daf5e8, 0x1b5d1009, 0x0f8cfcbd, 0x3e14fdf7, 0x238e7673, 0x3536cc52, 0x387165e3, 0x1e2b5d38,
+ 0x0645e9af, 0x3fb11b47, 0x1e2b5d38, 0x387165e3, 0x36e5068a, 0x20e70f32, 0xfcdc1342, 0x3fec43c6,
+ 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 0x1294062e, 0x3d3e82ad,
+ 0x3367c08f, 0x261feff9, 0xea70658b, 0x3c424209, 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a,
+ 0xe1d4a2c8, 0x387165e3, 0x0645e9af, 0x3fb11b47, 0x2f6bbe44, 0x2afad269, 0xd9e01007, 0x3367c08f,
+ 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xf9ba1651, 0x3fb11b47,
+ 0x2afad269, 0x2f6bbe44, 0xcc983f71, 0x261feff9, 0xf383a3e2, 0x3ec52f9f, 0x2899e64a, 0x317900d6,
+ 0xc78e9a1d, 0x1e2b5d38, 0xed6bf9d2, 0x3d3e82ad, 0x261feff9, 0x3367c08f, 0xc3bdbdf7, 0x158f9a75,
+ 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xe1d4a2c8, 0x387165e3,
+ 0x20e70f32, 0x36e5068a, 0xc013bc3a, 0x0323ecbe, 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3,
+ 0xc04ee4b9, 0xf9ba1651, 0xd76619b6, 0x317900d6, 0x1b5d1009, 0x39daf5e8, 0xc1eb0209, 0xf0730343,
+ 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xce86ff2a, 0x2899e64a,
+ 0x158f9a75, 0x3c424209, 0xc91af976, 0xdf18f0ce, 0xcac933ae, 0x238e7673, 0x1294062e, 0x3d3e82ad,
+ 0xce86ff2a, 0xd76619b6, 0xc78e9a1d, 0x1e2b5d38, 0x0f8cfcbd, 0x3e14fdf7, 0xd5052d97, 0xd09441bc,
+ 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 0xc2c17d53, 0x1294062e,
+ 0x09640837, 0x3f4eaafe, 0xe4a2eff7, 0xc6250a18, 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47,
+ 0xed6bf9d2, 0xc2c17d53, 0xc04ee4b9, 0x0645e9af, 0x0323ecbe, 0x3fec43c6, 0xf69bf7c9, 0xc0b15502,
+
+ 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3ffb10c1, 0x0192155f,
+ 0x3ffec42d, 0x00c90e8f, 0x3ff4e5df, 0x025b0cae, 0x3fec43c6, 0x0323ecbe, 0x3ffb10c1, 0x0192155f,
+ 0x3fd39b5a, 0x04b54824, 0x3fd39b5a, 0x04b54824, 0x3ff4e5df, 0x025b0cae, 0x3f9c2bfa, 0x070de171,
+ 0x3fb11b47, 0x0645e9af, 0x3fec43c6, 0x0323ecbe, 0x3f4eaafe, 0x09640837, 0x3f84c8e1, 0x07d59395,
+ 0x3fe12acb, 0x03ecadcf, 0x3eeb3347, 0x0bb6ecef, 0x3f4eaafe, 0x09640837, 0x3fd39b5a, 0x04b54824,
+ 0x3e71e758, 0x0e05c135, 0x3f0ec9f4, 0x0af10a22, 0x3fc395f9, 0x057db402, 0x3de2f147, 0x104fb80e,
+ 0x3ec52f9f, 0x0c7c5c1e, 0x3fb11b47, 0x0645e9af, 0x3d3e82ad, 0x1294062e, 0x3e71e758, 0x0e05c135,
+ 0x3f9c2bfa, 0x070de171, 0x3c84d496, 0x14d1e242, 0x3e14fdf7, 0x0f8cfcbd, 0x3f84c8e1, 0x07d59395,
+ 0x3bb6276d, 0x17088530, 0x3dae81ce, 0x1111d262, 0x3f6af2e3, 0x089cf867, 0x3ad2c2e7, 0x19372a63,
+ 0x3d3e82ad, 0x1294062e, 0x3f4eaafe, 0x09640837, 0x39daf5e8, 0x1b5d1009, 0x3cc511d8, 0x14135c94,
+ 0x3f2ff249, 0x0a2abb58, 0x38cf1669, 0x1d79775b, 0x3c424209, 0x158f9a75, 0x3f0ec9f4, 0x0af10a22,
+ 0x37af8158, 0x1f8ba4db, 0x3bb6276d, 0x17088530, 0x3eeb3347, 0x0bb6ecef, 0x367c9a7d, 0x2192e09a,
+ 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e, 0x3536cc52, 0x238e7673, 0x3a8269a2, 0x19ef7943,
+ 0x3e9cc076, 0x0d415012, 0x33de87de, 0x257db64b, 0x39daf5e8, 0x1b5d1009, 0x3e71e758, 0x0e05c135,
+ 0x32744493, 0x275ff452, 0x392a9642, 0x1cc66e99, 0x3e44a5ee, 0x0ec9a7f2, 0x30f8801f, 0x29348937,
+ 0x387165e3, 0x1e2b5d38, 0x3e14fdf7, 0x0f8cfcbd, 0x2f6bbe44, 0x2afad269, 0x37af8158, 0x1f8ba4db,
+ 0x3de2f147, 0x104fb80e, 0x2dce88a9, 0x2cb2324b, 0x36e5068a, 0x20e70f32, 0x3dae81ce, 0x1111d262,
+ 0x2c216eaa, 0x2e5a106f, 0x361214b0, 0x223d66a8, 0x3d77b191, 0x11d3443f, 0x2a650525, 0x2ff1d9c6,
+ 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 0x2899e64a, 0x317900d6, 0x34534f40, 0x24da0a99,
+ 0x3d02f756, 0x135410c2, 0x26c0b162, 0x32eefde9, 0x3367c08f, 0x261feff9, 0x3cc511d8, 0x14135c94,
+ 0x24da0a99, 0x34534f40, 0x32744493, 0x275ff452, 0x3c84d496, 0x14d1e242, 0x22e69ac7, 0x35a5793c,
+ 0x317900d6, 0x2899e64a, 0x3c424209, 0x158f9a75, 0x20e70f32, 0x36e5068a, 0x30761c17, 0x29cd9577,
+ 0x3bfd5cc4, 0x164c7ddd, 0x1edc1952, 0x3811884c, 0x2f6bbe44, 0x2afad269, 0x3bb6276d, 0x17088530,
+ 0x1cc66e99, 0x392a9642, 0x2e5a106f, 0x2c216eaa, 0x3b6ca4c4, 0x17c3a931, 0x1aa6c82b, 0x3a2fcee8,
+ 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x2c216eaa, 0x2e5a106f,
+ 0x3ad2c2e7, 0x19372a63, 0x164c7ddd, 0x3bfd5cc4, 0x2afad269, 0x2f6bbe44, 0x3a8269a2, 0x19ef7943,
+ 0x14135c94, 0x3cc511d8, 0x29cd9577, 0x30761c17, 0x3a2fcee8, 0x1aa6c82b, 0x11d3443f, 0x3d77b191,
+ 0x2899e64a, 0x317900d6, 0x39daf5e8, 0x1b5d1009, 0x0f8cfcbd, 0x3e14fdf7, 0x275ff452, 0x32744493,
+ 0x3983e1e7, 0x1c1249d8, 0x0d415012, 0x3e9cc076, 0x261feff9, 0x3367c08f, 0x392a9642, 0x1cc66e99,
+ 0x0af10a22, 0x3f0ec9f4, 0x24da0a99, 0x34534f40, 0x38cf1669, 0x1d79775b, 0x089cf867, 0x3f6af2e3,
+ 0x238e7673, 0x3536cc52, 0x387165e3, 0x1e2b5d38, 0x0645e9af, 0x3fb11b47, 0x223d66a8, 0x361214b0,
+ 0x3811884c, 0x1edc1952, 0x03ecadcf, 0x3fe12acb, 0x20e70f32, 0x36e5068a, 0x37af8158, 0x1f8ba4db,
+ 0x0192155f, 0x3ffb10c1, 0x1f8ba4db, 0x37af8158, 0x374b54ce, 0x2039f90e, 0xff36f171, 0x3ffec42d,
+ 0x1e2b5d38, 0x387165e3, 0x36e5068a, 0x20e70f32, 0xfcdc1342, 0x3fec43c6, 0x1cc66e99, 0x392a9642,
+ 0x367c9a7d, 0x2192e09a, 0xfa824bfe, 0x3fc395f9, 0x1b5d1009, 0x39daf5e8, 0x361214b0, 0x223d66a8,
+ 0xf82a6c6b, 0x3f84c8e1, 0x19ef7943, 0x3a8269a2, 0x35a5793c, 0x22e69ac7, 0xf5d544a8, 0x3f2ff249,
+ 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673, 0xf383a3e2, 0x3ec52f9f, 0x17088530, 0x3bb6276d,
+ 0x34c61236, 0x2434f332, 0xf136580e, 0x3e44a5ee, 0x158f9a75, 0x3c424209, 0x34534f40, 0x24da0a99,
+ 0xeeee2d9e, 0x3dae81ce, 0x14135c94, 0x3cc511d8, 0x33de87de, 0x257db64b, 0xecabef3e, 0x3d02f756,
+ 0x1294062e, 0x3d3e82ad, 0x3367c08f, 0x261feff9, 0xea70658b, 0x3c424209, 0x1111d262, 0x3dae81ce,
+ 0x32eefde9, 0x26c0b162, 0xe83c56cf, 0x3b6ca4c4, 0x0f8cfcbd, 0x3e14fdf7, 0x32744493, 0x275ff452,
+ 0xe61086bd, 0x3a8269a2, 0x0e05c135, 0x3e71e758, 0x31f79947, 0x27fdb2a6, 0xe3edb628, 0x3983e1e7,
+ 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 0xe1d4a2c8, 0x387165e3, 0x0af10a22, 0x3f0ec9f4,
+ 0x30f8801f, 0x29348937, 0xdfc606f2, 0x374b54ce, 0x09640837, 0x3f4eaafe, 0x30761c17, 0x29cd9577,
+ 0xddc29958, 0x361214b0, 0x07d59395, 0x3f84c8e1, 0x2ff1d9c6, 0x2a650525, 0xdbcb0cce, 0x34c61236,
+ 0x0645e9af, 0x3fb11b47, 0x2f6bbe44, 0x2afad269, 0xd9e01007, 0x3367c08f, 0x04b54824, 0x3fd39b5a,
+ 0x2ee3cebe, 0x2b8ef77c, 0xd8024d5a, 0x31f79947, 0x0323ecbe, 0x3fec43c6, 0x2e5a106f, 0x2c216eaa,
+ 0xd6326a89, 0x30761c17, 0x0192155f, 0x3ffb10c1, 0x2dce88a9, 0x2cb2324b, 0xd4710884, 0x2ee3cebe,
+ 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xfe6deaa1, 0x3ffb10c1,
+ 0x2cb2324b, 0x2dce88a9, 0xd11c3142, 0x2b8ef77c, 0xfcdc1342, 0x3fec43c6, 0x2c216eaa, 0x2e5a106f,
+ 0xcf89e3e9, 0x29cd9577, 0xfb4ab7dc, 0x3fd39b5a, 0x2b8ef77c, 0x2ee3cebe, 0xce0866b9, 0x27fdb2a6,
+ 0xf9ba1651, 0x3fb11b47, 0x2afad269, 0x2f6bbe44, 0xcc983f71, 0x261feff9, 0xf82a6c6b, 0x3f84c8e1,
+ 0x2a650525, 0x2ff1d9c6, 0xcb39edca, 0x2434f332, 0xf69bf7c9, 0x3f4eaafe, 0x29cd9577, 0x30761c17,
+ 0xc9edeb50, 0x223d66a8, 0xf50ef5de, 0x3f0ec9f4, 0x29348937, 0x30f8801f, 0xc8b4ab32, 0x2039f90e,
+ 0xf383a3e2, 0x3ec52f9f, 0x2899e64a, 0x317900d6, 0xc78e9a1d, 0x1e2b5d38, 0xf1fa3ecb, 0x3e71e758,
+ 0x27fdb2a6, 0x31f79947, 0xc67c1e19, 0x1c1249d8, 0xf0730343, 0x3e14fdf7, 0x275ff452, 0x32744493,
+ 0xc57d965e, 0x19ef7943, 0xeeee2d9e, 0x3dae81ce, 0x26c0b162, 0x32eefde9, 0xc4935b3c, 0x17c3a931,
+ 0xed6bf9d2, 0x3d3e82ad, 0x261feff9, 0x3367c08f, 0xc3bdbdf7, 0x158f9a75, 0xebeca36c, 0x3cc511d8,
+ 0x257db64b, 0x33de87de, 0xc2fd08aa, 0x135410c2, 0xea70658b, 0x3c424209, 0x24da0a99, 0x34534f40,
+ 0xc2517e32, 0x1111d262, 0xe8f77ad0, 0x3bb6276d, 0x2434f332, 0x34c61236, 0xc1bb5a12, 0x0ec9a7f2,
+ 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52, 0xc13ad061, 0x0c7c5c1e, 0xe61086bd, 0x3a8269a2,
+ 0x22e69ac7, 0x35a5793c, 0xc0d00db7, 0x0a2abb58, 0xe4a2eff7, 0x39daf5e8, 0x223d66a8, 0x361214b0,
+ 0xc07b371f, 0x07d59395, 0xe3399167, 0x392a9642, 0x2192e09a, 0x367c9a7d, 0xc03c6a07, 0x057db402,
+ 0xe1d4a2c8, 0x387165e3, 0x20e70f32, 0x36e5068a, 0xc013bc3a, 0x0323ecbe, 0xe0745b25, 0x37af8158,
+ 0x2039f90e, 0x374b54ce, 0xc0013bd3, 0x00c90e8f, 0xdf18f0ce, 0x36e5068a, 0x1f8ba4db, 0x37af8158,
+ 0xc004ef3f, 0xfe6deaa1, 0xddc29958, 0x361214b0, 0x1edc1952, 0x3811884c, 0xc01ed535, 0xfc135231,
+ 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 0xc04ee4b9, 0xf9ba1651, 0xdb25f567, 0x34534f40,
+ 0x1d79775b, 0x38cf1669, 0xc0950d1d, 0xf7630799, 0xd9e01007, 0x3367c08f, 0x1cc66e99, 0x392a9642,
+ 0xc0f1360c, 0xf50ef5de, 0xd8a00bae, 0x32744493, 0x1c1249d8, 0x3983e1e7, 0xc1633f8a, 0xf2beafee,
+ 0xd76619b6, 0x317900d6, 0x1b5d1009, 0x39daf5e8, 0xc1eb0209, 0xf0730343, 0xd6326a89, 0x30761c17,
+ 0x1aa6c82b, 0x3a2fcee8, 0xc2884e6f, 0xee2cbbc1, 0xd5052d97, 0x2f6bbe44, 0x19ef7943, 0x3a8269a2,
+ 0xc33aee28, 0xebeca36c, 0xd3de9156, 0x2e5a106f, 0x19372a63, 0x3ad2c2e7, 0xc402a33c, 0xe9b38223,
+ 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xd1a5ef91, 0x2c216eaa,
+ 0x17c3a931, 0x3b6ca4c4, 0xc5d03118, 0xe55937d5, 0xd09441bc, 0x2afad269, 0x17088530, 0x3bb6276d,
+ 0xc6d569be, 0xe3399167, 0xcf89e3e9, 0x29cd9577, 0x164c7ddd, 0x3bfd5cc4, 0xc7ee77b4, 0xe123e6ae,
+ 0xce86ff2a, 0x2899e64a, 0x158f9a75, 0x3c424209, 0xc91af976, 0xdf18f0ce, 0xcd8bbb6d, 0x275ff452,
+ 0x14d1e242, 0x3c84d496, 0xca5a86c4, 0xdd196539, 0xcc983f71, 0x261feff9, 0x14135c94, 0x3cc511d8,
+ 0xcbacb0c0, 0xdb25f567, 0xcbacb0c0, 0x24da0a99, 0x135410c2, 0x3d02f756, 0xcd110217, 0xd93f4e9e,
+ 0xcac933ae, 0x238e7673, 0x1294062e, 0x3d3e82ad, 0xce86ff2a, 0xd76619b6, 0xc9edeb50, 0x223d66a8,
+ 0x11d3443f, 0x3d77b191, 0xd00e263a, 0xd59afadb, 0xc91af976, 0x20e70f32, 0x1111d262, 0x3dae81ce,
+ 0xd1a5ef91, 0xd3de9156, 0xc8507ea8, 0x1f8ba4db, 0x104fb80e, 0x3de2f147, 0xd34dcdb5, 0xd2317757,
+ 0xc78e9a1d, 0x1e2b5d38, 0x0f8cfcbd, 0x3e14fdf7, 0xd5052d97, 0xd09441bc, 0xc6d569be, 0x1cc66e99,
+ 0x0ec9a7f2, 0x3e44a5ee, 0xd6cb76c9, 0xcf077fe1, 0xc6250a18, 0x1b5d1009, 0x0e05c135, 0x3e71e758,
+ 0xd8a00bae, 0xcd8bbb6d, 0xc57d965e, 0x19ef7943, 0x0d415012, 0x3e9cc076, 0xda8249b5, 0xcc217822,
+ 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f, 0xdc71898d, 0xcac933ae, 0xc449d893, 0x17088530,
+ 0x0bb6ecef, 0x3eeb3347, 0xde6d1f66, 0xc9836583, 0xc3bdbdf7, 0x158f9a75, 0x0af10a22, 0x3f0ec9f4,
+ 0xe0745b25, 0xc8507ea8, 0xc33aee28, 0x14135c94, 0x0a2abb58, 0x3f2ff249, 0xe28688a5, 0xc730e997,
+ 0xc2c17d53, 0x1294062e, 0x09640837, 0x3f4eaafe, 0xe4a2eff7, 0xc6250a18, 0xc2517e32, 0x1111d262,
+ 0x089cf867, 0x3f6af2e3, 0xe6c8d59d, 0xc52d3d19, 0xc1eb0209, 0x0f8cfcbd, 0x07d59395, 0x3f84c8e1,
+ 0xe8f77ad0, 0xc449d893, 0xc18e18a8, 0x0e05c135, 0x070de171, 0x3f9c2bfa, 0xeb2e1dbe, 0xc37b2b6a,
+ 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 0xed6bf9d2, 0xc2c17d53, 0xc0f1360c, 0x0af10a22,
+ 0x057db402, 0x3fc395f9, 0xefb047f2, 0xc21d0eb9, 0xc0b15502, 0x09640837, 0x04b54824, 0x3fd39b5a,
+ 0xf1fa3ecb, 0xc18e18a8, 0xc07b371f, 0x07d59395, 0x03ecadcf, 0x3fe12acb, 0xf4491311, 0xc114ccb9,
+ 0xc04ee4b9, 0x0645e9af, 0x0323ecbe, 0x3fec43c6, 0xf69bf7c9, 0xc0b15502, 0xc02c64a6, 0x04b54824,
+ 0x025b0cae, 0x3ff4e5df, 0xf8f21e8f, 0xc063d406, 0xc013bc3a, 0x0323ecbe, 0x0192155f, 0x3ffb10c1,
+ 0xfb4ab7dc, 0xc02c64a6, 0xc004ef3f, 0x0192155f, 0x00c90e8f, 0x3ffec42d, 0xfda4f352, 0xc00b1a21
+};
+
+const int twidTab64[4*6 + 16*6] = {
+ 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x2d413ccc, 0x2d413ccc,
+ 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc,
+ 0xd2bec334, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a,
+
+ 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00000000, 0x3ec52f9f, 0x0c7c5c1e,
+ 0x3fb11b47, 0x0645e9af, 0x3d3e82ad, 0x1294062e, 0x3b20d79e, 0x187de2a6, 0x3ec52f9f, 0x0c7c5c1e,
+ 0x3536cc52, 0x238e7673, 0x3536cc52, 0x238e7673, 0x3d3e82ad, 0x1294062e, 0x2899e64a, 0x317900d6,
+ 0x2d413ccc, 0x2d413ccc, 0x3b20d79e, 0x187de2a6, 0x187de2a6, 0x3b20d79e, 0x238e7673, 0x3536cc52,
+ 0x387165e3, 0x1e2b5d38, 0x0645e9af, 0x3fb11b47, 0x187de2a6, 0x3b20d79e, 0x3536cc52, 0x238e7673,
+ 0xf383a3e2, 0x3ec52f9f, 0x0c7c5c1e, 0x3ec52f9f, 0x317900d6, 0x2899e64a, 0xe1d4a2c8, 0x387165e3,
+ 0x00000000, 0x40000000, 0x2d413ccc, 0x2d413ccc, 0xd2bec334, 0x2d413ccc, 0xf383a3e2, 0x3ec52f9f,
+ 0x2899e64a, 0x317900d6, 0xc78e9a1d, 0x1e2b5d38, 0xe7821d5a, 0x3b20d79e, 0x238e7673, 0x3536cc52,
+ 0xc13ad061, 0x0c7c5c1e, 0xdc71898d, 0x3536cc52, 0x1e2b5d38, 0x387165e3, 0xc04ee4b9, 0xf9ba1651,
+ 0xd2bec334, 0x2d413ccc, 0x187de2a6, 0x3b20d79e, 0xc4df2862, 0xe7821d5a, 0xcac933ae, 0x238e7673,
+ 0x1294062e, 0x3d3e82ad, 0xce86ff2a, 0xd76619b6, 0xc4df2862, 0x187de2a6, 0x0c7c5c1e, 0x3ec52f9f,
+ 0xdc71898d, 0xcac933ae, 0xc13ad061, 0x0c7c5c1e, 0x0645e9af, 0x3fb11b47, 0xed6bf9d2, 0xc2c17d53
+};
+#endif //ARMV5E
+
+const int ShortWindowSine[FRAME_LEN_SHORT/2] ={
+ 0x00c97fff, 0x025b7ffa, 0x03ed7ff1, 0x057f7fe2, 0x07117fce, 0x08a27fb5, 0x0a337f98, 0x0bc47f75,
+ 0x0d547f4e, 0x0ee47f22, 0x10737ef0, 0x12017eba, 0x138f7e7f, 0x151c7e3f, 0x16a87dfb, 0x18337db1,
+ 0x19be7d63, 0x1b477d0f, 0x1cd07cb7, 0x1e577c5a, 0x1fdd7bf9, 0x21627b92, 0x22e57b27, 0x24677ab7,
+ 0x25e87a42, 0x276879c9, 0x28e5794a, 0x2a6278c8, 0x2bdc7840, 0x2d5577b4, 0x2ecc7723, 0x3042768e,
+ 0x31b575f4, 0x33277556, 0x349774b3, 0x3604740b, 0x3770735f, 0x38d972af, 0x3a4071fa, 0x3ba57141,
+ 0x3d087083, 0x3e686fc2, 0x3fc66efb, 0x41216e31, 0x427a6d62, 0x43d16c8f, 0x45246bb8, 0x46756add,
+ 0x47c469fd, 0x490f691a, 0x4a586832, 0x4b9e6747, 0x4ce16657, 0x4e216564, 0x4f5e646c, 0x50986371,
+ 0x51cf6272, 0x5303616f, 0x54336068, 0x55605f5e, 0x568a5e50, 0x57b15d3e, 0x58d45c29, 0x59f45b10
+};
+
+const int LongWindowKBD[FRAME_LEN_LONG/2]={
+ 0x000a7fff, 0x000e7fff, 0x00127fff, 0x00157fff, 0x00197fff, 0x001c7fff, 0x00207fff, 0x00237fff,
+ 0x00267fff, 0x002a7fff, 0x002d7fff, 0x00307fff, 0x00347fff, 0x00387fff, 0x003b7fff, 0x003f7fff,
+ 0x00437fff, 0x00477fff, 0x004b7fff, 0x004f7fff, 0x00537fff, 0x00577fff, 0x005b7fff, 0x00607fff,
+ 0x00647fff, 0x00697fff, 0x006d7fff, 0x00727fff, 0x00777fff, 0x007c7fff, 0x00817fff, 0x00867fff,
+ 0x008b7fff, 0x00917fff, 0x00967fff, 0x009c7fff, 0x00a17fff, 0x00a77fff, 0x00ad7fff, 0x00b37fff,
+ 0x00b97fff, 0x00bf7fff, 0x00c67fff, 0x00cc7fff, 0x00d37fff, 0x00da7fff, 0x00e07fff, 0x00e77fff,
+ 0x00ee7fff, 0x00f57fff, 0x00fd7fff, 0x01047fff, 0x010c7fff, 0x01137fff, 0x011b7fff, 0x01237fff,
+ 0x012b7fff, 0x01337fff, 0x013c7ffe, 0x01447ffe, 0x014d7ffe, 0x01567ffe, 0x015f7ffe, 0x01687ffe,
+ 0x01717ffe, 0x017a7ffe, 0x01837ffe, 0x018d7ffe, 0x01977ffd, 0x01a17ffd, 0x01ab7ffd, 0x01b57ffd,
+ 0x01bf7ffd, 0x01ca7ffd, 0x01d47ffd, 0x01df7ffc, 0x01ea7ffc, 0x01f57ffc, 0x02007ffc, 0x020c7ffc,
+ 0x02177ffc, 0x02237ffb, 0x022f7ffb, 0x023b7ffb, 0x02477ffb, 0x02537ffb, 0x02607ffa, 0x026d7ffa,
+ 0x027a7ffa, 0x02877ffa, 0x02947ff9, 0x02a17ff9, 0x02af7ff9, 0x02bc7ff9, 0x02ca7ff8, 0x02d87ff8,
+ 0x02e77ff8, 0x02f57ff7, 0x03047ff7, 0x03127ff7, 0x03217ff6, 0x03317ff6, 0x03407ff5, 0x034f7ff5,
+ 0x035f7ff5, 0x036f7ff4, 0x037f7ff4, 0x038f7ff3, 0x03a07ff3, 0x03b07ff2, 0x03c17ff2, 0x03d27ff1,
+ 0x03e37ff1, 0x03f57ff0, 0x04067ff0, 0x04187fef, 0x042a7fef, 0x043c7fee, 0x044f7fed, 0x04617fed,
+ 0x04747fec, 0x04877feb, 0x049a7feb, 0x04ae7fea, 0x04c17fe9, 0x04d57fe9, 0x04e97fe8, 0x04fd7fe7,
+ 0x05127fe6, 0x05277fe5, 0x053b7fe5, 0x05507fe4, 0x05667fe3, 0x057b7fe2, 0x05917fe1, 0x05a77fe0,
+ 0x05bd7fdf, 0x05d37fde, 0x05ea7fdd, 0x06017fdc, 0x06187fdb, 0x062f7fda, 0x06467fd9, 0x065e7fd7,
+ 0x06767fd6, 0x068e7fd5, 0x06a67fd4, 0x06bf7fd2, 0x06d87fd1, 0x06f17fd0, 0x070a7fce, 0x07237fcd,
+ 0x073d7fcc, 0x07577fca, 0x07717fc9, 0x078c7fc7, 0x07a67fc5, 0x07c17fc4, 0x07dc7fc2, 0x07f77fc0,
+ 0x08137fbf, 0x082f7fbd, 0x084b7fbb, 0x08677fb9, 0x08847fb7, 0x08a07fb6, 0x08bd7fb4, 0x08da7fb2,
+ 0x08f87faf, 0x09167fad, 0x09347fab, 0x09527fa9, 0x09707fa7, 0x098f7fa5, 0x09ae7fa2, 0x09cd7fa0,
+ 0x09ec7f9d, 0x0a0c7f9b, 0x0a2c7f98, 0x0a4c7f96, 0x0a6c7f93, 0x0a8d7f91, 0x0aae7f8e, 0x0acf7f8b,
+ 0x0af07f88, 0x0b127f85, 0x0b337f82, 0x0b557f7f, 0x0b787f7c, 0x0b9a7f79, 0x0bbd7f76, 0x0be07f73,
+ 0x0c047f6f, 0x0c277f6c, 0x0c4b7f69, 0x0c6f7f65, 0x0c937f61, 0x0cb87f5e, 0x0cdd7f5a, 0x0d027f56,
+ 0x0d277f53, 0x0d4d7f4f, 0x0d737f4b, 0x0d997f47, 0x0dbf7f43, 0x0de67f3e, 0x0e0c7f3a, 0x0e347f36,
+ 0x0e5b7f31, 0x0e837f2d, 0x0eaa7f28, 0x0ed37f24, 0x0efb7f1f, 0x0f237f1a, 0x0f4c7f15, 0x0f757f10,
+ 0x0f9f7f0b, 0x0fc87f06, 0x0ff27f01, 0x101c7efb, 0x10477ef6, 0x10717ef0, 0x109c7eeb, 0x10c87ee5,
+ 0x10f37edf, 0x111f7eda, 0x114a7ed4, 0x11777ece, 0x11a37ec7, 0x11d07ec1, 0x11fd7ebb, 0x122a7eb4,
+ 0x12577eae, 0x12857ea7, 0x12b37ea0, 0x12e17e9a, 0x130f7e93, 0x133e7e8c, 0x136d7e84, 0x139c7e7d,
+ 0x13cc7e76, 0x13fb7e6e, 0x142b7e67, 0x145b7e5f, 0x148c7e57, 0x14bc7e4f, 0x14ed7e47, 0x151e7e3f,
+ 0x15507e37, 0x15817e2e, 0x15b37e26, 0x15e57e1d, 0x16187e14, 0x164a7e0b, 0x167d7e02, 0x16b07df9,
+ 0x16e47df0, 0x17177de6, 0x174b7ddd, 0x177f7dd3, 0x17b37dc9, 0x17e87dbf, 0x181d7db5, 0x18527dab,
+ 0x18877da1, 0x18bc7d96, 0x18f27d8c, 0x19287d81, 0x195e7d76, 0x19957d6b, 0x19cb7d60, 0x1a027d54,
+ 0x1a397d49, 0x1a717d3d, 0x1aa87d31, 0x1ae07d26, 0x1b187d19, 0x1b507d0d, 0x1b897d01, 0x1bc27cf4,
+ 0x1bfb7ce8, 0x1c347cdb, 0x1c6d7cce, 0x1ca77cc1, 0x1ce17cb3, 0x1d1b7ca6, 0x1d557c98, 0x1d8f7c8a,
+ 0x1dca7c7c, 0x1e057c6e, 0x1e407c60, 0x1e7b7c51, 0x1eb77c43, 0x1ef37c34, 0x1f2f7c25, 0x1f6b7c16,
+ 0x1fa77c06, 0x1fe47bf7, 0x20217be7, 0x205e7bd7, 0x209b7bc7, 0x20d87bb7, 0x21167ba6, 0x21547b96,
+ 0x21927b85, 0x21d07b74, 0x220e7b63, 0x224d7b52, 0x228c7b40, 0x22cb7b2e, 0x230a7b1c, 0x23497b0a,
+ 0x23897af8, 0x23c87ae6, 0x24087ad3, 0x24487ac0, 0x24897aad, 0x24c97a9a, 0x250a7a86, 0x254b7a73,
+ 0x258c7a5f, 0x25cd7a4b, 0x260e7a36, 0x26507a22, 0x26917a0d, 0x26d379f8, 0x271579e3, 0x275779ce,
+ 0x279a79b8, 0x27dc79a3, 0x281f798d, 0x28627977, 0x28a57960, 0x28e8794a, 0x292b7933, 0x296f791c,
+ 0x29b27905, 0x29f678ed, 0x2a3a78d6, 0x2a7e78be, 0x2ac278a6, 0x2b07788d, 0x2b4b7875, 0x2b90785c,
+ 0x2bd47843, 0x2c19782a, 0x2c5e7810, 0x2ca477f7, 0x2ce977dd, 0x2d2e77c3, 0x2d7477a8, 0x2dba778e,
+ 0x2dff7773, 0x2e457758, 0x2e8b773d, 0x2ed27721, 0x2f187706, 0x2f5e76ea, 0x2fa576cd, 0x2fec76b1,
+ 0x30327694, 0x30797677, 0x30c0765a, 0x3107763d, 0x314e761f, 0x31967601, 0x31dd75e3, 0x322575c5,
+ 0x326c75a6, 0x32b47588, 0x32fc7569, 0x33447549, 0x338c752a, 0x33d4750a, 0x341c74ea, 0x346474ca,
+ 0x34ac74a9, 0x34f57488, 0x353d7467, 0x35857446, 0x35ce7424, 0x36177403, 0x365f73e1, 0x36a873be,
+ 0x36f1739c, 0x373a7379, 0x37837356, 0x37cc7333, 0x3815730f, 0x385e72ec, 0x38a772c8, 0x38f172a3,
+ 0x393a727f, 0x3983725a, 0x39cd7235, 0x3a167210, 0x3a6071ea, 0x3aa971c4, 0x3af3719e, 0x3b3c7178,
+ 0x3b867151, 0x3bd0712b, 0x3c197104, 0x3c6370dc, 0x3cad70b5, 0x3cf7708d, 0x3d407065, 0x3d8a703c,
+ 0x3dd47014, 0x3e1e6feb, 0x3e686fc2, 0x3eb16f98, 0x3efb6f6f, 0x3f456f45, 0x3f8f6f1b, 0x3fd96ef0,
+ 0x40236ec6, 0x406d6e9b, 0x40b66e70, 0x41006e44, 0x414a6e19, 0x41946ded, 0x41de6dc1, 0x42286d94,
+ 0x42716d68, 0x42bb6d3b, 0x43056d0d, 0x434f6ce0, 0x43986cb2, 0x43e26c84, 0x442c6c56, 0x44756c28,
+ 0x44bf6bf9, 0x45086bca, 0x45526b9b, 0x459b6b6b, 0x45e56b3c, 0x462e6b0c, 0x46786adb, 0x46c16aab,
+ 0x470a6a7a, 0x47536a49, 0x479c6a18, 0x47e569e7, 0x482e69b5, 0x48776983, 0x48c06951, 0x4909691e,
+ 0x495268ec, 0x499b68b9, 0x49e36885, 0x4a2c6852, 0x4a74681e, 0x4abd67ea, 0x4b0567b6, 0x4b4d6782,
+ 0x4b95674d, 0x4bde6718, 0x4c2666e3, 0x4c6d66ae, 0x4cb56678, 0x4cfd6642, 0x4d45660c, 0x4d8c65d6,
+ 0x4dd4659f, 0x4e1b6568, 0x4e626531, 0x4ea964fa, 0x4ef064c3, 0x4f37648b, 0x4f7e6453, 0x4fc5641b,
+ 0x500b63e2, 0x505263aa, 0x50986371, 0x50df6338, 0x512562fe, 0x516b62c5, 0x51b1628b, 0x51f66251,
+ 0x523c6217, 0x528161dc, 0x52c761a2, 0x530c6167, 0x5351612c, 0x539660f1, 0x53db60b5, 0x54206079,
+ 0x5464603d, 0x54a96001, 0x54ed5fc5, 0x55315f88, 0x55755f4b, 0x55b95f0e, 0x55fc5ed1, 0x56405e94,
+ 0x56835e56, 0x56c75e18, 0x570a5dda, 0x574d5d9c, 0x578f5d5e, 0x57d25d1f, 0x58145ce0, 0x58565ca1,
+ 0x58995c62, 0x58da5c23, 0x591c5be3, 0x595e5ba4, 0x599f5b64, 0x59e05b24, 0x5a215ae3, 0x5a625aa3
+};
+
+
+/*
+ form factor
+*/
+/* sqrt(((i+(1<<(FF_SQRT_BITS-2)+0.5)/2^31) */
+const Word32 formfac_sqrttable[96] = {
+ 0x000407f8, 0x000417b9, 0x0004273f, 0x0004368c, 0x000445a1, 0x00045483, 0x00046332, 0x000471b0,
+ 0x00048000, 0x00048e22, 0x00049c1a, 0x0004a9e7, 0x0004b78c, 0x0004c50a, 0x0004d263, 0x0004df96,
+ 0x0004eca7, 0x0004f995, 0x00050662, 0x0005130e, 0x00051f9c, 0x00052c0a, 0x0005385b, 0x00054490,
+ 0x000550a8, 0x00055ca5, 0x00056888, 0x00057450, 0x00058000, 0x00058b96, 0x00059715, 0x0005a27c,
+ 0x0005adcc, 0x0005b906, 0x0005c42b, 0x0005cf39, 0x0005da33, 0x0005e519, 0x0005efea, 0x0005faa8,
+ 0x00060552, 0x00060fea, 0x00061a70, 0x000624e3, 0x00062f45, 0x00063996, 0x000643d5, 0x00064e04,
+ 0x00065823, 0x00066231, 0x00066c30, 0x0006761f, 0x00068000, 0x000689d1, 0x00069393, 0x00069d47,
+ 0x0006a6ed, 0x0006b085, 0x0006ba10, 0x0006c38d, 0x0006ccfc, 0x0006d65f, 0x0006dfb5, 0x0006e8fe,
+ 0x0006f23b, 0x0006fb6c, 0x00070490, 0x00070da9, 0x000716b6, 0x00071fb8, 0x000728ae, 0x00073199,
+ 0x00073a79, 0x0007434e, 0x00074c19, 0x000754d9, 0x00075d8e, 0x0007663a, 0x00076edb, 0x00077772,
+ 0x00078000, 0x00078883, 0x000790fd, 0x0007996e, 0x0007a1d5, 0x0007aa33, 0x0007b288, 0x0007bad4,
+ 0x0007c318, 0x0007cb52, 0x0007d384, 0x0007dbad, 0x0007e3ce, 0x0007ebe6, 0x0007f3f6, 0x0007fbfe
+};
+
+
+
+/*!
+ \name quantizer and inverse quantizer tables
+
+ \brief these tables are used for the non
+ linear quantizer and inverse quantizer
+
+*/
+const Word32 mTab_3_4[512] = {
+ 0x4c1bf829, 0x4c3880de, 0x4c550603, 0x4c71879c,
+ 0x4c8e05aa, 0x4caa8030, 0x4cc6f72f, 0x4ce36aab,
+ 0x4cffdaa4, 0x4d1c471d, 0x4d38b019, 0x4d55159a,
+ 0x4d7177a1, 0x4d8dd631, 0x4daa314b, 0x4dc688f3,
+ 0x4de2dd2a, 0x4dff2df2, 0x4e1b7b4d, 0x4e37c53d,
+ 0x4e540bc5, 0x4e704ee6, 0x4e8c8ea3, 0x4ea8cafd,
+ 0x4ec503f7, 0x4ee13992, 0x4efd6bd0, 0x4f199ab4,
+ 0x4f35c640, 0x4f51ee75, 0x4f6e1356, 0x4f8a34e4,
+ 0x4fa65321, 0x4fc26e10, 0x4fde85b2, 0x4ffa9a0a,
+ 0x5016ab18, 0x5032b8e0, 0x504ec362, 0x506acaa1,
+ 0x5086cea0, 0x50a2cf5e, 0x50becce0, 0x50dac725,
+ 0x50f6be31, 0x5112b205, 0x512ea2a3, 0x514a900d,
+ 0x51667a45, 0x5182614c, 0x519e4524, 0x51ba25cf,
+ 0x51d60350, 0x51f1dda7, 0x520db4d6, 0x522988e0,
+ 0x524559c6, 0x52612789, 0x527cf22d, 0x5298b9b1,
+ 0x52b47e19, 0x52d03f65, 0x52ebfd98, 0x5307b8b4,
+ 0x532370b9, 0x533f25aa, 0x535ad789, 0x53768656,
+ 0x53923215, 0x53addac6, 0x53c9806b, 0x53e52306,
+ 0x5400c298, 0x541c5f24, 0x5437f8ab, 0x54538f2e,
+ 0x546f22af, 0x548ab330, 0x54a640b3, 0x54c1cb38,
+ 0x54dd52c2, 0x54f8d753, 0x551458eb, 0x552fd78d,
+ 0x554b5339, 0x5566cbf3, 0x558241bb, 0x559db492,
+ 0x55b9247b, 0x55d49177, 0x55effb87, 0x560b62ad,
+ 0x5626c6eb, 0x56422842, 0x565d86b4, 0x5678e242,
+ 0x56943aee, 0x56af90b9, 0x56cae3a4, 0x56e633b2,
+ 0x570180e4, 0x571ccb3b, 0x573812b8, 0x5753575e,
+ 0x576e992e, 0x5789d829, 0x57a51450, 0x57c04da6,
+ 0x57db842b, 0x57f6b7e1, 0x5811e8c9, 0x582d16e6,
+ 0x58484238, 0x58636ac0, 0x587e9081, 0x5899b37c,
+ 0x58b4d3b1, 0x58cff123, 0x58eb0bd3, 0x590623c2,
+ 0x592138f2, 0x593c4b63, 0x59575b19, 0x59726812,
+ 0x598d7253, 0x59a879da, 0x59c37eab, 0x59de80c6,
+ 0x59f9802d, 0x5a147ce0, 0x5a2f76e2, 0x5a4a6e34,
+ 0x5a6562d6, 0x5a8054cb, 0x5a9b4414, 0x5ab630b2,
+ 0x5ad11aa6, 0x5aec01f1, 0x5b06e696, 0x5b21c895,
+ 0x5b3ca7ef, 0x5b5784a6, 0x5b725ebc, 0x5b8d3631,
+ 0x5ba80b06, 0x5bc2dd3e, 0x5bddacd9, 0x5bf879d8,
+ 0x5c13443d, 0x5c2e0c09, 0x5c48d13e, 0x5c6393dc,
+ 0x5c7e53e5, 0x5c99115a, 0x5cb3cc3c, 0x5cce848d,
+ 0x5ce93a4e, 0x5d03ed80, 0x5d1e9e24, 0x5d394c3b,
+ 0x5d53f7c7, 0x5d6ea0c9, 0x5d894742, 0x5da3eb33,
+ 0x5dbe8c9e, 0x5dd92b84, 0x5df3c7e5, 0x5e0e61c3,
+ 0x5e28f920, 0x5e438dfc, 0x5e5e2059, 0x5e78b037,
+ 0x5e933d99, 0x5eadc87e, 0x5ec850e9, 0x5ee2d6da,
+ 0x5efd5a53, 0x5f17db54, 0x5f3259e0, 0x5f4cd5f6,
+ 0x5f674f99, 0x5f81c6c8, 0x5f9c3b87, 0x5fb6add4,
+ 0x5fd11db3, 0x5feb8b23, 0x6005f626, 0x60205ebd,
+ 0x603ac4e9, 0x605528ac, 0x606f8a05, 0x6089e8f7,
+ 0x60a44583, 0x60be9fa9, 0x60d8f76b, 0x60f34cca,
+ 0x610d9fc7, 0x6127f062, 0x61423e9e, 0x615c8a7a,
+ 0x6176d3f9, 0x61911b1b, 0x61ab5fe1, 0x61c5a24d,
+ 0x61dfe25f, 0x61fa2018, 0x62145b7a, 0x622e9485,
+ 0x6248cb3b, 0x6262ff9d, 0x627d31ab, 0x62976167,
+ 0x62b18ed1, 0x62cbb9eb, 0x62e5e2b6, 0x63000933,
+ 0x631a2d62, 0x63344f45, 0x634e6edd, 0x63688c2b,
+ 0x6382a730, 0x639cbfec, 0x63b6d661, 0x63d0ea90,
+ 0x63eafc7a, 0x64050c1f, 0x641f1982, 0x643924a2,
+ 0x64532d80, 0x646d341f, 0x6487387e, 0x64a13a9e,
+ 0x64bb3a81, 0x64d53828, 0x64ef3393, 0x65092cc4,
+ 0x652323bb, 0x653d1879, 0x65570b00, 0x6570fb50,
+ 0x658ae96b, 0x65a4d550, 0x65bebf01, 0x65d8a680,
+ 0x65f28bcc, 0x660c6ee8, 0x66264fd3, 0x66402e8f,
+ 0x665a0b1c, 0x6673e57d, 0x668dbdb0, 0x66a793b8,
+ 0x66c16795, 0x66db3949, 0x66f508d4, 0x670ed636,
+ 0x6728a172, 0x67426a87, 0x675c3177, 0x6775f643,
+ 0x678fb8eb, 0x67a97971, 0x67c337d5, 0x67dcf418,
+ 0x67f6ae3b, 0x6810663f, 0x682a1c25, 0x6843cfed,
+ 0x685d8199, 0x68773129, 0x6890de9f, 0x68aa89fa,
+ 0x68c4333d, 0x68ddda67, 0x68f77f7a, 0x69112277,
+ 0x692ac35e, 0x69446230, 0x695dfeee, 0x6977999a,
+ 0x69913232, 0x69aac8ba, 0x69c45d31, 0x69ddef98,
+ 0x69f77ff0, 0x6a110e3a, 0x6a2a9a77, 0x6a4424a8,
+ 0x6a5daccc, 0x6a7732e6, 0x6a90b6f6, 0x6aaa38fd,
+ 0x6ac3b8fb, 0x6add36f2, 0x6af6b2e2, 0x6b102ccd,
+ 0x6b29a4b2, 0x6b431a92, 0x6b5c8e6f, 0x6b76004a,
+ 0x6b8f7022, 0x6ba8ddf9, 0x6bc249d0, 0x6bdbb3a7,
+ 0x6bf51b80, 0x6c0e815a, 0x6c27e537, 0x6c414718,
+ 0x6c5aa6fd, 0x6c7404e7, 0x6c8d60d7, 0x6ca6bace,
+ 0x6cc012cc, 0x6cd968d2, 0x6cf2bce1, 0x6d0c0ef9,
+ 0x6d255f1d, 0x6d3ead4b, 0x6d57f985, 0x6d7143cc,
+ 0x6d8a8c21, 0x6da3d283, 0x6dbd16f5, 0x6dd65976,
+ 0x6def9a08, 0x6e08d8ab, 0x6e221560, 0x6e3b5027,
+ 0x6e548902, 0x6e6dbff1, 0x6e86f4f5, 0x6ea0280e,
+ 0x6eb9593e, 0x6ed28885, 0x6eebb5e3, 0x6f04e15a,
+ 0x6f1e0aea, 0x6f373294, 0x6f505859, 0x6f697c39,
+ 0x6f829e35, 0x6f9bbe4e, 0x6fb4dc85, 0x6fcdf8d9,
+ 0x6fe7134d, 0x70002be0, 0x70194293, 0x70325767,
+ 0x704b6a5d, 0x70647b76, 0x707d8ab1, 0x70969811,
+ 0x70afa394, 0x70c8ad3d, 0x70e1b50c, 0x70fabb01,
+ 0x7113bf1d, 0x712cc161, 0x7145c1ce, 0x715ec064,
+ 0x7177bd24, 0x7190b80f, 0x71a9b124, 0x71c2a866,
+ 0x71db9dd4, 0x71f49170, 0x720d8339, 0x72267331,
+ 0x723f6159, 0x72584db0, 0x72713838, 0x728a20f1,
+ 0x72a307db, 0x72bbecf9, 0x72d4d049, 0x72edb1ce,
+ 0x73069187, 0x731f6f75, 0x73384b98, 0x735125f3,
+ 0x7369fe84, 0x7382d54d, 0x739baa4e, 0x73b47d89,
+ 0x73cd4efd, 0x73e61eab, 0x73feec94, 0x7417b8b8,
+ 0x74308319, 0x74494bb6, 0x74621291, 0x747ad7aa,
+ 0x74939b02, 0x74ac5c98, 0x74c51c6f, 0x74ddda86,
+ 0x74f696de, 0x750f5178, 0x75280a54, 0x7540c174,
+ 0x755976d7, 0x75722a7e, 0x758adc69, 0x75a38c9b,
+ 0x75bc3b12, 0x75d4e7cf, 0x75ed92d4, 0x76063c21,
+ 0x761ee3b6, 0x76378994, 0x76502dbc, 0x7668d02e,
+ 0x768170eb, 0x769a0ff3, 0x76b2ad47, 0x76cb48e7,
+ 0x76e3e2d5, 0x76fc7b10, 0x7715119a, 0x772da673,
+ 0x7746399b, 0x775ecb13, 0x77775adc, 0x778fe8f6,
+ 0x77a87561, 0x77c1001f, 0x77d98930, 0x77f21095,
+ 0x780a964d, 0x78231a5b, 0x783b9cbd, 0x78541d75,
+ 0x786c9c84, 0x788519e9, 0x789d95a6, 0x78b60fbb,
+ 0x78ce8828, 0x78e6feef, 0x78ff740f, 0x7917e78a,
+ 0x7930595f, 0x7948c990, 0x7961381d, 0x7979a506,
+ 0x7992104c, 0x79aa79f0, 0x79c2e1f1, 0x79db4852,
+ 0x79f3ad11, 0x7a0c1031, 0x7a2471b0, 0x7a3cd191,
+ 0x7a552fd3, 0x7a6d8c76, 0x7a85e77d, 0x7a9e40e6,
+ 0x7ab698b2, 0x7aceeee3, 0x7ae74378, 0x7aff9673,
+ 0x7b17e7d2, 0x7b303799, 0x7b4885c5, 0x7b60d259,
+ 0x7b791d55, 0x7b9166b9, 0x7ba9ae86, 0x7bc1f4bc,
+ 0x7bda395c, 0x7bf27c66, 0x7c0abddb, 0x7c22fdbb,
+ 0x7c3b3c07, 0x7c5378c0, 0x7c6bb3e5, 0x7c83ed78,
+ 0x7c9c2579, 0x7cb45be9, 0x7ccc90c7, 0x7ce4c414,
+ 0x7cfcf5d2, 0x7d152600, 0x7d2d549f, 0x7d4581b0,
+ 0x7d5dad32, 0x7d75d727, 0x7d8dff8f, 0x7da6266a,
+ 0x7dbe4bba, 0x7dd66f7d, 0x7dee91b6, 0x7e06b264,
+ 0x7e1ed188, 0x7e36ef22, 0x7e4f0b34, 0x7e6725bd,
+ 0x7e7f3ebd, 0x7e975636, 0x7eaf6c28, 0x7ec78093,
+ 0x7edf9378, 0x7ef7a4d7, 0x7f0fb4b1, 0x7f27c307,
+ 0x7f3fcfd8, 0x7f57db25, 0x7f6fe4ef, 0x7f87ed36,
+ 0x7f9ff3fb, 0x7fb7f93e, 0x7fcffcff, 0x7fe7ff40
+};
+
+const Word32 mTab_4_3[512]={
+ 0x32cbfd4a, 0x32eddd70, 0x330fc339, 0x3331aea3,
+ 0x33539fac, 0x33759652, 0x33979294, 0x33b99470,
+ 0x33db9be4, 0x33fda8ed, 0x341fbb8b, 0x3441d3bb,
+ 0x3463f17c, 0x348614cc, 0x34a83da8, 0x34ca6c10,
+ 0x34eca001, 0x350ed979, 0x35311877, 0x35535cfa,
+ 0x3575a6fe, 0x3597f683, 0x35ba4b87, 0x35dca607,
+ 0x35ff0603, 0x36216b78, 0x3643d665, 0x366646c7,
+ 0x3688bc9e, 0x36ab37e8, 0x36cdb8a2, 0x36f03ecb,
+ 0x3712ca62, 0x37355b64, 0x3757f1d1, 0x377a8da5,
+ 0x379d2ee0, 0x37bfd580, 0x37e28184, 0x380532e8,
+ 0x3827e9ad, 0x384aa5d0, 0x386d674f, 0x38902e2a,
+ 0x38b2fa5d, 0x38d5cbe9, 0x38f8a2ca, 0x391b7eff,
+ 0x393e6088, 0x39614761, 0x3984338a, 0x39a72501,
+ 0x39ca1bc4, 0x39ed17d1, 0x3a101928, 0x3a331fc6,
+ 0x3a562baa, 0x3a793cd2, 0x3a9c533d, 0x3abf6ee9,
+ 0x3ae28fd5, 0x3b05b5ff, 0x3b28e165, 0x3b4c1206,
+ 0x3b6f47e0, 0x3b9282f2, 0x3bb5c33a, 0x3bd908b7,
+ 0x3bfc5368, 0x3c1fa349, 0x3c42f85b, 0x3c66529c,
+ 0x3c89b209, 0x3cad16a2, 0x3cd08065, 0x3cf3ef51,
+ 0x3d176364, 0x3d3adc9c, 0x3d5e5af8, 0x3d81de77,
+ 0x3da56717, 0x3dc8f4d6, 0x3dec87b4, 0x3e101fae,
+ 0x3e33bcc3, 0x3e575ef2, 0x3e7b063a, 0x3e9eb298,
+ 0x3ec2640c, 0x3ee61a93, 0x3f09d62d, 0x3f2d96d8,
+ 0x3f515c93, 0x3f75275b, 0x3f98f731, 0x3fbccc11,
+ 0x3fe0a5fc, 0x400484ef, 0x402868ea, 0x404c51e9,
+ 0x40703fee, 0x409432f5, 0x40b82afd, 0x40dc2806,
+ 0x41002a0d, 0x41243111, 0x41483d12, 0x416c4e0d,
+ 0x41906401, 0x41b47eed, 0x41d89ecf, 0x41fcc3a7,
+ 0x4220ed72, 0x42451c30, 0x42694fde, 0x428d887d,
+ 0x42b1c609, 0x42d60883, 0x42fa4fe8, 0x431e9c37,
+ 0x4342ed70, 0x43674390, 0x438b9e96, 0x43affe82,
+ 0x43d46351, 0x43f8cd03, 0x441d3b95, 0x4441af08,
+ 0x44662758, 0x448aa487, 0x44af2690, 0x44d3ad75,
+ 0x44f83933, 0x451cc9c8, 0x45415f35, 0x4565f977,
+ 0x458a988d, 0x45af3c76, 0x45d3e531, 0x45f892bc,
+ 0x461d4516, 0x4641fc3e, 0x4666b832, 0x468b78f2,
+ 0x46b03e7c, 0x46d508cf, 0x46f9d7e9, 0x471eabca,
+ 0x47438470, 0x476861d9, 0x478d4406, 0x47b22af3,
+ 0x47d716a1, 0x47fc070e, 0x4820fc39, 0x4845f620,
+ 0x486af4c3, 0x488ff820, 0x48b50035, 0x48da0d03,
+ 0x48ff1e87, 0x492434c0, 0x49494fad, 0x496e6f4d,
+ 0x4993939f, 0x49b8bca2, 0x49ddea54, 0x4a031cb4,
+ 0x4a2853c1, 0x4a4d8f7a, 0x4a72cfde, 0x4a9814eb,
+ 0x4abd5ea1, 0x4ae2acfd, 0x4b080000, 0x4b2d57a8,
+ 0x4b52b3f3, 0x4b7814e1, 0x4b9d7a70, 0x4bc2e49f,
+ 0x4be8536e, 0x4c0dc6db, 0x4c333ee4, 0x4c58bb89,
+ 0x4c7e3cc9, 0x4ca3c2a2, 0x4cc94d14, 0x4ceedc1c,
+ 0x4d146fbb, 0x4d3a07ef, 0x4d5fa4b6, 0x4d854611,
+ 0x4daaebfd, 0x4dd09679, 0x4df64585, 0x4e1bf91f,
+ 0x4e41b146, 0x4e676dfa, 0x4e8d2f38, 0x4eb2f501,
+ 0x4ed8bf52, 0x4efe8e2b, 0x4f24618a, 0x4f4a3970,
+ 0x4f7015d9, 0x4f95f6c6, 0x4fbbdc36, 0x4fe1c626,
+ 0x5007b497, 0x502da787, 0x50539ef5, 0x50799ae1,
+ 0x509f9b48, 0x50c5a02a, 0x50eba985, 0x5111b75a,
+ 0x5137c9a6, 0x515de069, 0x5183fba2, 0x51aa1b4f,
+ 0x51d03f70, 0x51f66803, 0x521c9508, 0x5242c67d,
+ 0x5268fc62, 0x528f36b5, 0x52b57575, 0x52dbb8a2,
+ 0x5302003a, 0x53284c3c, 0x534e9ca8, 0x5374f17c,
+ 0x539b4ab7, 0x53c1a858, 0x53e80a5f, 0x540e70ca,
+ 0x5434db98, 0x545b4ac8, 0x5481be5a, 0x54a8364b,
+ 0x54ceb29c, 0x54f5334c, 0x551bb858, 0x554241c1,
+ 0x5568cf85, 0x558f61a3, 0x55b5f81b, 0x55dc92eb,
+ 0x56033212, 0x5629d590, 0x56507d63, 0x5677298a,
+ 0x569dda05, 0x56c48ed3, 0x56eb47f2, 0x57120562,
+ 0x5738c721, 0x575f8d2f, 0x5786578a, 0x57ad2633,
+ 0x57d3f927, 0x57fad066, 0x5821abef, 0x58488bc0,
+ 0x586f6fda, 0x5896583b, 0x58bd44e2, 0x58e435ce,
+ 0x590b2aff, 0x59322473, 0x59592229, 0x59802420,
+ 0x59a72a59, 0x59ce34d0, 0x59f54387, 0x5a1c567b,
+ 0x5a436dac, 0x5a6a8919, 0x5a91a8c1, 0x5ab8cca3,
+ 0x5adff4be, 0x5b072111, 0x5b2e519c, 0x5b55865e,
+ 0x5b7cbf54, 0x5ba3fc80, 0x5bcb3ddf, 0x5bf28371,
+ 0x5c19cd35, 0x5c411b2a, 0x5c686d4f, 0x5c8fc3a4,
+ 0x5cb71e27, 0x5cde7cd7, 0x5d05dfb4, 0x5d2d46bd,
+ 0x5d54b1f0, 0x5d7c214e, 0x5da394d4, 0x5dcb0c83,
+ 0x5df28859, 0x5e1a0856, 0x5e418c78, 0x5e6914be,
+ 0x5e90a129, 0x5eb831b7, 0x5edfc667, 0x5f075f38,
+ 0x5f2efc29, 0x5f569d3a, 0x5f7e426a, 0x5fa5ebb7,
+ 0x5fcd9921, 0x5ff54aa8, 0x601d004a, 0x6044ba06,
+ 0x606c77dc, 0x609439ca, 0x60bbffd0, 0x60e3c9ee,
+ 0x610b9821, 0x61336a6a, 0x615b40c8, 0x61831b39,
+ 0x61aaf9bd, 0x61d2dc53, 0x61fac2fa, 0x6222adb2,
+ 0x624a9c79, 0x62728f4f, 0x629a8633, 0x62c28123,
+ 0x62ea8020, 0x63128329, 0x633a8a3c, 0x63629559,
+ 0x638aa47f, 0x63b2b7ad, 0x63dacee2, 0x6402ea1e,
+ 0x642b0960, 0x64532ca6, 0x647b53f1, 0x64a37f3f,
+ 0x64cbae8f, 0x64f3e1e2, 0x651c1935, 0x65445488,
+ 0x656c93db, 0x6594d72c, 0x65bd1e7b, 0x65e569c7,
+ 0x660db90f, 0x66360c53, 0x665e6391, 0x6686bec9,
+ 0x66af1dfa, 0x66d78123, 0x66ffe844, 0x6728535b,
+ 0x6750c268, 0x6779356b, 0x67a1ac62, 0x67ca274c,
+ 0x67f2a629, 0x681b28f9, 0x6843afb9, 0x686c3a6a,
+ 0x6894c90b, 0x68bd5b9b, 0x68e5f219, 0x690e8c84,
+ 0x69372add, 0x695fcd21, 0x69887350, 0x69b11d6a,
+ 0x69d9cb6d, 0x6a027d5a, 0x6a2b332f, 0x6a53eceb,
+ 0x6a7caa8d, 0x6aa56c16, 0x6ace3184, 0x6af6fad6,
+ 0x6b1fc80c, 0x6b489925, 0x6b716e20, 0x6b9a46fd,
+ 0x6bc323bb, 0x6bec0458, 0x6c14e8d5, 0x6c3dd130,
+ 0x6c66bd69, 0x6c8fad80, 0x6cb8a172, 0x6ce19940,
+ 0x6d0a94e9, 0x6d33946d, 0x6d5c97ca, 0x6d859eff,
+ 0x6daeaa0d, 0x6dd7b8f1, 0x6e00cbad, 0x6e29e23e,
+ 0x6e52fca4, 0x6e7c1adf, 0x6ea53cee, 0x6ece62cf,
+ 0x6ef78c83, 0x6f20ba09, 0x6f49eb5f, 0x6f732085,
+ 0x6f9c597b, 0x6fc59640, 0x6feed6d3, 0x70181b33,
+ 0x70416360, 0x706aaf59, 0x7093ff1d, 0x70bd52ab,
+ 0x70e6aa04, 0x71100525, 0x7139640f, 0x7162c6c1,
+ 0x718c2d3a, 0x71b5977a, 0x71df057f, 0x72087749,
+ 0x7231ecd8, 0x725b662a, 0x7284e33f, 0x72ae6417,
+ 0x72d7e8b0, 0x7301710a, 0x732afd24, 0x73548cfe,
+ 0x737e2097, 0x73a7b7ee, 0x73d15303, 0x73faf1d5,
+ 0x74249462, 0x744e3aac, 0x7477e4b0, 0x74a1926e,
+ 0x74cb43e6, 0x74f4f917, 0x751eb201, 0x75486ea1,
+ 0x75722ef9, 0x759bf307, 0x75c5baca, 0x75ef8642,
+ 0x7619556f, 0x7643284f, 0x766cfee2, 0x7696d928,
+ 0x76c0b71f, 0x76ea98c7, 0x77147e20, 0x773e6728,
+ 0x776853df, 0x77924445, 0x77bc3858, 0x77e63019,
+ 0x78102b85, 0x783a2a9e, 0x78642d62, 0x788e33d1,
+ 0x78b83de9, 0x78e24bab, 0x790c5d15, 0x79367228,
+ 0x79608ae1, 0x798aa742, 0x79b4c748, 0x79deeaf4,
+ 0x7a091245, 0x7a333d3a, 0x7a5d6bd2, 0x7a879e0e,
+ 0x7ab1d3ec, 0x7adc0d6b, 0x7b064a8c, 0x7b308b4d,
+ 0x7b5acfae, 0x7b8517ae, 0x7baf634c, 0x7bd9b289,
+ 0x7c040563, 0x7c2e5bda, 0x7c58b5ec, 0x7c83139b,
+ 0x7cad74e4, 0x7cd7d9c7, 0x7d024244, 0x7d2cae5a,
+ 0x7d571e09, 0x7d81914f, 0x7dac082d, 0x7dd682a1,
+ 0x7e0100ac, 0x7e2b824b, 0x7e560780, 0x7e809048,
+ 0x7eab1ca5, 0x7ed5ac94, 0x7f004015, 0x7f2ad729,
+ 0x7f5571cd, 0x7f801003, 0x7faab1c8, 0x7fd5571d
+};
+
+
+const Word32 invSBF[24] = {
+ 0x3FFD34FC, 0x2D3F8000, 0x24F18C7E, 0x1FFE9A7E,
+ 0x1C9DF10C, 0x1A1F851A, 0x182FE994, 0x169FC000,
+ 0x15542AAA, 0x143C31C2, 0x134B1B6C, 0x127920BE,
+ 0x11BF2FCC, 0x111A749E, 0x1085FC42, 0x0FFFA7BE,
+ 0x0F855818, 0x0F14EE56, 0x0EAE6A78, 0x0E4EF886,
+ 0x0DF69880, 0x0DA49568, 0x0D578542, 0x0D101D0C
+};
+
+const Word16 pow2tominusNover16[17] = {
+ 0x7fff, 0x7a93, 0x7560, 0x7066,
+ 0x6ba2, 0x6712, 0x62b4, 0x5e84,
+ 0x5a82, 0x56ac, 0x52ff, 0x4f7b,
+ 0x4c1c, 0x48e2, 0x45cb, 0x42d5,
+ 0x4000
+};
+
+const Word16 sideInfoTabLong[MAX_SFB_LONG + 1] = {
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14
+};
+
+const Word16 sideInfoTabShort[MAX_SFB_SHORT + 1] = {
+ 7, 7, 7, 7, 7, 7, 7, 10, 10,
+ 10, 10, 10, 10, 10, 13, 13
+};
+
+Word32 specExpMantTableComb_enc[4][14] =
+{
+ {0x40000000, 0x50a28be6, 0x6597fa95, 0x40000000,
+ 0x50a28be6, 0x6597fa95, 0x40000000, 0x50a28be6,
+ 0x6597fa95, 0x40000000, 0x50a28be6, 0x6597fa95,
+ 0x40000000, 0x50a28be6},
+
+ {0x4c1bf829, 0x5fe4435e, 0x78d0df9c, 0x4c1bf829,
+ 0x5fe4435e, 0x78d0df9c, 0x4c1bf829, 0x5fe4435e,
+ 0x78d0df9c, 0x4c1bf829, 0x5fe4435e, 0x78d0df9c,
+ 0x4c1bf829, 0x5fe4435e},
+
+ {0x5a82799a, 0x7208f81d, 0x47d66b0f, 0x5a82799a,
+ 0x7208f81d, 0x47d66b0f, 0x5a82799a, 0x7208f81d,
+ 0x47d66b0f, 0x5a82799a, 0x7208f81d, 0x47d66b0f,
+ 0x5a82799a, 0x7208f81d},
+
+ {0x6ba27e65, 0x43ce3e4b, 0x556e0424, 0x6ba27e65,
+ 0x43ce3e4b, 0x556e0424, 0x6ba27e65, 0x43ce3e4b,
+ 0x556e0424, 0x6ba27e65, 0x43ce3e4b, 0x556e0424,
+ 0x6ba27e65, 0x43ce3e4b}
+};
+
+const UWord8 specExpTableComb_enc[4][14] =
+{
+ {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18},
+ {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18},
+ {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18},
+ {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19}
+};
+
+const Word16 quantBorders[4][4] = {
+ /* pow(1.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */
+ {0x0400, 0x0ee7, 0x1c86, 0x2c0d},
+ /* pow(2.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */
+ {0x04c2, 0x11b9, 0x21eb, 0x3463},
+ /* pow(3.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */
+ {0x05a8, 0x1514, 0x2856, 0x3e4c},
+ /* pow(4.0-0.4054, 4/3)/16 * pow(2, (0..3)/4) */
+ {0x06ba, 0x1911, 0x2ff8, 0x4a16},
+};
+
+const Word16 quantRecon[4][3] = {
+ {0x0800, 0x1429, 0x229d},
+ {0x0983, 0x17f9, 0x292a},
+ {0x0b50, 0x1c82, 0x30f4},
+ {0x0d74, 0x21e7, 0x3a37},
+};
+
+const int sampRateTab[NUM_SAMPLE_RATES] = {
+ 96000, 88200, 64000, 48000, 44100, 32000,
+ 24000, 22050, 16000, 12000, 11025, 8000
+};
+
+
+const int rates[8] = {
+ 160, 240, 320, 400, 480, 560, 640, 0
+};
+
+const int BandwithCoefTab[8][NUM_SAMPLE_RATES] = {
+ { 7000, 7000, 4666, 3500, 3500, 2800, 2800, 2800, 2800, 2000, 2000, 2000},
+ {12000, 12000, 8000, 6000, 6000, 6000, 4000, 4000, 4000, 3000, 3000, 3000},
+ {18000, 18000, 12000, 9000, 9000, 9000, 7000, 7000, 7000, 5000, 5000, 5000},
+ {20000, 20000, 16000, 12000, 12000, 12000, 9000, 9000, 9000, 6000, 6000, 6000},
+ {20000, 20000, 18666, 14000, 14000, 14000, 10000, 10000, 10000, 7000, 7000, 7000},
+ {20000, 20000, 20000, 16000, 16000, 16000, 12000, 12000, 12000, 8000, 8000, 8000},
+ {20000, 20000, 20000, 20000, 20000, 20000, 15000, 15000, 15000, 10000, 10000, 10000},
+ {20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000, 20000}
+};
+
+
+/* total number of scale factor bands in one window */
+const UWord8 sfBandTotalShort[NUM_SAMPLE_RATES] = {
+ 12, 12, 12, 14, 14, 14, 15, 15, 15, 15, 15, 15
+};
+
+const UWord8 sfBandTotalLong[NUM_SAMPLE_RATES] = {
+ 41, 41, 47, 49, 49, 51, 47, 47, 43, 43, 43, 40
+};
+
+/* scale factor band tables */
+const int sfBandTabShortOffset[NUM_SAMPLE_RATES] = {0, 0, 0, 13, 13, 13, 28, 28, 44, 44, 44, 60};
+
+const short sfBandTabShort[76] = {
+ /* short block 64, 88, 96 kHz [13] */
+ 0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 92, 128,
+
+ /* short block 32, 44, 48 kHz [15] */
+ 0, 4, 8, 12, 16, 20, 28, 36, 44, 56, 68, 80, 96, 112, 128,
+
+ /* short block 22, 24 kHz [16] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 64, 76, 92, 108, 128,
+
+ /* short block 11, 12, 16 kHz [16] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 40, 48, 60, 72, 88, 108, 128,
+
+ /* short block 8 kHz [16] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 36, 44, 52, 60, 72, 88, 108, 128
+};
+
+const int sfBandTabLongOffset[NUM_SAMPLE_RATES] = {0, 0, 42, 90, 90, 140, 192, 192, 240, 240, 240, 284};
+
+const short sfBandTabLong[325] = {
+ /* long block 88, 96 kHz [42] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
+ 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212,
+ 240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024,
+
+ /* long block 64 kHz [48] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 64,
+ 72, 80, 88, 100, 112, 124, 140, 156, 172, 192, 216, 240, 268, 304, 344, 384,
+ 424, 464, 504, 544, 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024,
+
+ /* long block 44, 48 kHz [50] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88,
+ 96, 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448,
+ 480, 512, 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024,
+
+ /* long block 32 kHz [52] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 88, 96,
+ 108, 120, 132, 144, 160, 176, 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512,
+ 544, 576, 608, 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024,
+
+ /* long block 22, 24 kHz [48] */
+ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 52, 60, 68, 76,
+ 84, 92, 100, 108, 116, 124, 136, 148, 160, 172, 188, 204, 220, 240, 260, 284,
+ 308, 336, 364, 396, 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024,
+
+ /* long block 11, 12, 16 kHz [44] */
+ 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124,
+ 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368,
+ 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024,
+
+ /* long block 8 kHz [41] */
+ 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156,
+ 172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420,
+ 448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024
+};
+
+/*
+ these tables are used only for counting and
+ are stored in packed format
+*/
+const UWord16 huff_ltab1_2[3][3][3][3]=
+{
+ {
+ {
+ {0x0b09,0x0907,0x0b09},
+ {0x0a08,0x0706,0x0a08},
+ {0x0b09,0x0908,0x0b09}
+ },
+ {
+ {0x0a08,0x0706,0x0a07},
+ {0x0706,0x0505,0x0706},
+ {0x0907,0x0706,0x0a08}
+ },
+ {
+ {0x0b09,0x0907,0x0b08},
+ {0x0908,0x0706,0x0908},
+ {0x0b09,0x0907,0x0b09}
+ }
+ },
+ {
+ {
+ {0x0908,0x0706,0x0907},
+ {0x0706,0x0505,0x0706},
+ {0x0907,0x0706,0x0908}
+ },
+ {
+ {0x0706,0x0505,0x0706},
+ {0x0505,0x0103,0x0505},
+ {0x0706,0x0505,0x0706}
+ },
+ {
+ {0x0908,0x0706,0x0907},
+ {0x0706,0x0505,0x0706},
+ {0x0908,0x0706,0x0908}
+ }
+ },
+ {
+ {
+ {0x0b09,0x0907,0x0b09},
+ {0x0908,0x0706,0x0908},
+ {0x0b08,0x0907,0x0b09}
+ },
+ {
+ {0x0a08,0x0706,0x0907},
+ {0x0706,0x0504,0x0706},
+ {0x0908,0x0706,0x0a07}
+ },
+ {
+ {0x0b09,0x0907,0x0b09},
+ {0x0a07,0x0706,0x0908},
+ {0x0b09,0x0907,0x0b09}
+ }
+ }
+};
+
+
+const UWord16 huff_ltab3_4[3][3][3][3]=
+{
+ {
+ {
+ {0x0104,0x0405,0x0808},
+ {0x0405,0x0504,0x0808},
+ {0x0909,0x0908,0x0a0b}
+ },
+ {
+ {0x0405,0x0605,0x0908},
+ {0x0605,0x0604,0x0908},
+ {0x0908,0x0907,0x0a0a}
+ },
+ {
+ {0x0909,0x0a08,0x0d0b},
+ {0x0908,0x0908,0x0b0a},
+ {0x0b0b,0x0a0a,0x0c0b}
+ }
+ },
+ {
+ {
+ {0x0404,0x0605,0x0a08},
+ {0x0604,0x0704,0x0a08},
+ {0x0a08,0x0a08,0x0c0a}
+ },
+ {
+ {0x0504,0x0704,0x0b08},
+ {0x0604,0x0704,0x0a07},
+ {0x0908,0x0907,0x0b09}
+ },
+ {
+ {0x0908,0x0a08,0x0d0a},
+ {0x0807,0x0907,0x0c09},
+ {0x0a0a,0x0b09,0x0c0a}
+ }
+ },
+ {
+ {
+ {0x0808,0x0a08,0x0f0b},
+ {0x0908,0x0b07,0x0f0a},
+ {0x0d0b,0x0e0a,0x100c}
+ },
+ {
+ {0x0808,0x0a07,0x0e0a},
+ {0x0907,0x0a07,0x0e09},
+ {0x0c0a,0x0c09,0x0f0b}
+ },
+ {
+ {0x0b0b,0x0c0a,0x100c},
+ {0x0a0a,0x0b09,0x0f0b},
+ {0x0c0b,0x0c0a,0x0f0b}
+ }
+ }
+};
+
+const UWord16 huff_ltab5_6[9][9]=
+{
+ {0x0d0b,0x0c0a,0x0b09,0x0b09,0x0a09,0x0b09,0x0b09,0x0c0a,0x0d0b},
+ {0x0c0a,0x0b09,0x0a08,0x0907,0x0807,0x0907,0x0a08,0x0b09,0x0c0a},
+ {0x0c09,0x0a08,0x0906,0x0806,0x0706,0x0806,0x0906,0x0a08,0x0b09},
+ {0x0b09,0x0907,0x0806,0x0504,0x0404,0x0504,0x0806,0x0907,0x0b09},
+ {0x0a09,0x0807,0x0706,0x0404,0x0104,0x0404,0x0706,0x0807,0x0b09},
+ {0x0b09,0x0907,0x0806,0x0504,0x0404,0x0504,0x0806,0x0907,0x0b09},
+ {0x0b09,0x0a08,0x0906,0x0806,0x0706,0x0806,0x0906,0x0a08,0x0b09},
+ {0x0c0a,0x0b09,0x0a08,0x0907,0x0807,0x0907,0x0a07,0x0b08,0x0c0a},
+ {0x0d0b,0x0c0a,0x0c09,0x0b09,0x0a09,0x0a09,0x0b09,0x0c0a,0x0d0b}
+};
+
+const UWord16 huff_ltab7_8[8][8]=
+{
+ {0x0105,0x0304,0x0605,0x0706,0x0807,0x0908,0x0a09,0x0b0a},
+ {0x0304,0x0403,0x0604,0x0705,0x0806,0x0807,0x0907,0x0908},
+ {0x0605,0x0604,0x0704,0x0805,0x0806,0x0907,0x0907,0x0a08},
+ {0x0706,0x0705,0x0805,0x0806,0x0906,0x0907,0x0a08,0x0a08},
+ {0x0807,0x0806,0x0906,0x0906,0x0a07,0x0a07,0x0a08,0x0b09},
+ {0x0908,0x0807,0x0906,0x0907,0x0a07,0x0a08,0x0b08,0x0b0a},
+ {0x0a09,0x0907,0x0907,0x0a08,0x0a08,0x0b08,0x0c09,0x0c09},
+ {0x0b0a,0x0a08,0x0a08,0x0a08,0x0b09,0x0b09,0x0c09,0x0c0a}
+};
+
+const UWord16 huff_ltab9_10[13][13]=
+{
+ {0x0106,0x0305,0x0606,0x0806,0x0907,0x0a08,0x0a09,0x0b0a,0x0b0a,0x0c0a,0x0c0b,0x0d0b,0x0d0c},
+ {0x0305,0x0404,0x0604,0x0705,0x0806,0x0807,0x0907,0x0a08,0x0a08,0x0a09,0x0b0a,0x0c0a,0x0c0b},
+ {0x0606,0x0604,0x0705,0x0805,0x0806,0x0906,0x0a07,0x0a08,0x0a08,0x0b09,0x0c09,0x0c0a,0x0c0a},
+ {0x0806,0x0705,0x0805,0x0905,0x0906,0x0a07,0x0a07,0x0b08,0x0b08,0x0b09,0x0c09,0x0c0a,0x0d0a},
+ {0x0907,0x0806,0x0906,0x0906,0x0a06,0x0a07,0x0b07,0x0b08,0x0b08,0x0c09,0x0c09,0x0c0a,0x0d0a},
+ {0x0a08,0x0907,0x0906,0x0a07,0x0b07,0x0b07,0x0b08,0x0c08,0x0b08,0x0c09,0x0c0a,0x0d0a,0x0d0b},
+ {0x0b09,0x0907,0x0a07,0x0b07,0x0b07,0x0b08,0x0c08,0x0c09,0x0c09,0x0c09,0x0d0a,0x0d0a,0x0d0b},
+ {0x0b09,0x0a08,0x0a08,0x0b08,0x0b08,0x0c08,0x0c09,0x0d09,0x0d09,0x0d0a,0x0d0a,0x0d0b,0x0d0b},
+ {0x0b09,0x0a08,0x0a08,0x0b08,0x0b08,0x0b08,0x0c09,0x0c09,0x0d0a,0x0d0a,0x0e0a,0x0d0b,0x0e0b},
+ {0x0b0a,0x0a09,0x0b09,0x0b09,0x0c09,0x0c09,0x0c09,0x0c0a,0x0d0a,0x0d0a,0x0e0b,0x0e0b,0x0e0c},
+ {0x0c0a,0x0b09,0x0b09,0x0c09,0x0c09,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0e0b,0x0e0b,0x0e0b,0x0f0c},
+ {0x0c0b,0x0b0a,0x0c09,0x0c0a,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0d0b,0x0e0b,0x0e0b,0x0f0b,0x0f0c},
+ {0x0d0b,0x0c0a,0x0c0a,0x0c0a,0x0d0a,0x0d0a,0x0d0a,0x0d0b,0x0e0b,0x0e0c,0x0e0c,0x0e0c,0x0f0c}
+};
+
+const UWord16 huff_ltab11[17][17]=
+{
+ {0x0004,0x0005,0x0006,0x0007,0x0008,0x0008,0x0009,0x000a,0x000a,0x000a,0x000b,0x000b,0x000c,0x000b,0x000c,0x000c,0x000a},
+ {0x0005,0x0004,0x0005,0x0006,0x0007,0x0007,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000b,0x0008},
+ {0x0006,0x0005,0x0005,0x0006,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+ {0x0007,0x0006,0x0006,0x0006,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+ {0x0008,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+ {0x0008,0x0007,0x0007,0x0007,0x0007,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x0008},
+ {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x0008},
+ {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x0008},
+ {0x000a,0x0009,0x0008,0x0008,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x0008},
+ {0x000a,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x0008},
+ {0x000b,0x0009,0x0009,0x0009,0x0009,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000a,0x000b,0x000b,0x0008},
+ {0x000b,0x000a,0x0009,0x0009,0x000a,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x0008},
+ {0x000b,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009},
+ {0x000b,0x000a,0x0009,0x0009,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009},
+ {0x000b,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x0009},
+ {0x000c,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000a,0x000b,0x000b,0x000b,0x000b,0x000b,0x000b,0x000c,0x000c,0x0009},
+ {0x0009,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0008,0x0009,0x0005}
+};
+
+const UWord16 huff_ltabscf[121]=
+{
+ 0x0012,
+ 0x0012,
+ 0x0012,
+ 0x0012,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0012,
+ 0x0013,
+ 0x0012,
+ 0x0011,
+ 0x0011,
+ 0x0010,
+ 0x0011,
+ 0x0010,
+ 0x0010,
+ 0x0010,
+ 0x0010,
+ 0x000f,
+ 0x000f,
+ 0x000e,
+ 0x000e,
+ 0x000e,
+ 0x000e,
+ 0x000e,
+ 0x000e,
+ 0x000d,
+ 0x000d,
+ 0x000c,
+ 0x000c,
+ 0x000c,
+ 0x000b,
+ 0x000c,
+ 0x000b,
+ 0x000a,
+ 0x000a,
+ 0x000a,
+ 0x0009,
+ 0x0009,
+ 0x0008,
+ 0x0008,
+ 0x0008,
+ 0x0007,
+ 0x0006,
+ 0x0006,
+ 0x0005,
+ 0x0004,
+ 0x0003,
+ 0x0001,
+ 0x0004,
+ 0x0004,
+ 0x0005,
+ 0x0006,
+ 0x0006,
+ 0x0007,
+ 0x0007,
+ 0x0008,
+ 0x0008,
+ 0x0009,
+ 0x0009,
+ 0x000a,
+ 0x000a,
+ 0x000a,
+ 0x000b,
+ 0x000b,
+ 0x000b,
+ 0x000b,
+ 0x000c,
+ 0x000c,
+ 0x000d,
+ 0x000d,
+ 0x000d,
+ 0x000e,
+ 0x000e,
+ 0x0010,
+ 0x000f,
+ 0x0010,
+ 0x000f,
+ 0x0012,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013,
+ 0x0013
+};
+
+
+const UWord16 huff_ctab1[3][3][3][3]=
+{
+ {
+ {
+ {0x07f8,0x01f1,0x07fd},
+ {0x03f5,0x0068,0x03f0},
+ {0x07f7,0x01ec,0x07f5}
+ },
+ {
+ {0x03f1,0x0072,0x03f4},
+ {0x0074,0x0011,0x0076},
+ {0x01eb,0x006c,0x03f6}
+ },
+ {
+ {0x07fc,0x01e1,0x07f1},
+ {0x01f0,0x0061,0x01f6},
+ {0x07f2,0x01ea,0x07fb}
+ }
+ },
+ {
+ {
+ {0x01f2,0x0069,0x01ed},
+ {0x0077,0x0017,0x006f},
+ {0x01e6,0x0064,0x01e5}
+ },
+ {
+ {0x0067,0x0015,0x0062},
+ {0x0012,0x0000,0x0014},
+ {0x0065,0x0016,0x006d}
+ },
+ {
+ {0x01e9,0x0063,0x01e4},
+ {0x006b,0x0013,0x0071},
+ {0x01e3,0x0070,0x01f3}
+ }
+ },
+ {
+ {
+ {0x07fe,0x01e7,0x07f3},
+ {0x01ef,0x0060,0x01ee},
+ {0x07f0,0x01e2,0x07fa}
+ },
+ {
+ {0x03f3,0x006a,0x01e8},
+ {0x0075,0x0010,0x0073},
+ {0x01f4,0x006e,0x03f7}
+ },
+ {
+ {0x07f6,0x01e0,0x07f9},
+ {0x03f2,0x0066,0x01f5},
+ {0x07ff,0x01f7,0x07f4}
+ }
+ }
+};
+
+const UWord16 huff_ctab2[3][3][3][3]=
+{
+ {
+ {
+ {0x01f3,0x006f,0x01fd},
+ {0x00eb,0x0023,0x00ea},
+ {0x01f7,0x00e8,0x01fa}
+ },
+ {
+ {0x00f2,0x002d,0x0070},
+ {0x0020,0x0006,0x002b},
+ {0x006e,0x0028,0x00e9}
+ },
+ {
+ {0x01f9,0x0066,0x00f8},
+ {0x00e7,0x001b,0x00f1},
+ {0x01f4,0x006b,0x01f5}
+ }
+ },
+ {
+ {
+ {0x00ec,0x002a,0x006c},
+ {0x002c,0x000a,0x0027},
+ {0x0067,0x001a,0x00f5}
+ },
+ {
+ {0x0024,0x0008,0x001f},
+ {0x0009,0x0000,0x0007},
+ {0x001d,0x000b,0x0030}
+ },
+ {
+ {0x00ef,0x001c,0x0064},
+ {0x001e,0x000c,0x0029},
+ {0x00f3,0x002f,0x00f0}
+ }
+ },
+ {
+ {
+ {0x01fc,0x0071,0x01f2},
+ {0x00f4,0x0021,0x00e6},
+ {0x00f7,0x0068,0x01f8}
+ },
+ {
+ {0x00ee,0x0022,0x0065},
+ {0x0031,0x0002,0x0026},
+ {0x00ed,0x0025,0x006a}
+ },
+ {
+ {0x01fb,0x0072,0x01fe},
+ {0x0069,0x002e,0x00f6},
+ {0x01ff,0x006d,0x01f6}
+ }
+ }
+};
+
+const UWord16 huff_ctab3[3][3][3][3]=
+{
+ {
+ {
+ {0x0000,0x0009,0x00ef},
+ {0x000b,0x0019,0x00f0},
+ {0x01eb,0x01e6,0x03f2}
+ },
+ {
+ {0x000a,0x0035,0x01ef},
+ {0x0034,0x0037,0x01e9},
+ {0x01ed,0x01e7,0x03f3}
+ },
+ {
+ {0x01ee,0x03ed,0x1ffa},
+ {0x01ec,0x01f2,0x07f9},
+ {0x07f8,0x03f8,0x0ff8}
+ }
+ },
+ {
+ {
+ {0x0008,0x0038,0x03f6},
+ {0x0036,0x0075,0x03f1},
+ {0x03eb,0x03ec,0x0ff4}
+ },
+ {
+ {0x0018,0x0076,0x07f4},
+ {0x0039,0x0074,0x03ef},
+ {0x01f3,0x01f4,0x07f6}
+ },
+ {
+ {0x01e8,0x03ea,0x1ffc},
+ {0x00f2,0x01f1,0x0ffb},
+ {0x03f5,0x07f3,0x0ffc}
+ }
+ },
+ {
+ {
+ {0x00ee,0x03f7,0x7ffe},
+ {0x01f0,0x07f5,0x7ffd},
+ {0x1ffb,0x3ffa,0xffff}
+ },
+ {
+ {0x00f1,0x03f0,0x3ffc},
+ {0x01ea,0x03ee,0x3ffb},
+ {0x0ff6,0x0ffa,0x7ffc}
+ },
+ {
+ {0x07f2,0x0ff5,0xfffe},
+ {0x03f4,0x07f7,0x7ffb},
+ {0x0ff7,0x0ff9,0x7ffa}
+ }
+ }
+};
+
+const UWord16 huff_ctab4[3][3][3][3]=
+{
+ {
+ {
+ {0x0007,0x0016,0x00f6},
+ {0x0018,0x0008,0x00ef},
+ {0x01ef,0x00f3,0x07f8}
+ },
+ {
+ {0x0019,0x0017,0x00ed},
+ {0x0015,0x0001,0x00e2},
+ {0x00f0,0x0070,0x03f0}
+ },
+ {
+ {0x01ee,0x00f1,0x07fa},
+ {0x00ee,0x00e4,0x03f2},
+ {0x07f6,0x03ef,0x07fd}
+ }
+ },
+ {
+ {
+ {0x0005,0x0014,0x00f2},
+ {0x0009,0x0004,0x00e5},
+ {0x00f4,0x00e8,0x03f4}
+ },
+ {
+ {0x0006,0x0002,0x00e7},
+ {0x0003,0x0000,0x006b},
+ {0x00e3,0x0069,0x01f3}
+ },
+ {
+ {0x00eb,0x00e6,0x03f6},
+ {0x006e,0x006a,0x01f4},
+ {0x03ec,0x01f0,0x03f9}
+ }
+ },
+ {
+ {
+ {0x00f5,0x00ec,0x07fb},
+ {0x00ea,0x006f,0x03f7},
+ {0x07f9,0x03f3,0x0fff}
+ },
+ {
+ {0x00e9,0x006d,0x03f8},
+ {0x006c,0x0068,0x01f5},
+ {0x03ee,0x01f2,0x07f4}
+ },
+ {
+ {0x07f7,0x03f1,0x0ffe},
+ {0x03ed,0x01f1,0x07f5},
+ {0x07fe,0x03f5,0x07fc}
+ }
+ }
+};
+const UWord16 huff_ctab5[9][9]=
+{
+ {0x1fff,0x0ff7,0x07f4,0x07e8,0x03f1,0x07ee,0x07f9,0x0ff8,0x1ffd},
+ {0x0ffd,0x07f1,0x03e8,0x01e8,0x00f0,0x01ec,0x03ee,0x07f2,0x0ffa},
+ {0x0ff4,0x03ef,0x01f2,0x00e8,0x0070,0x00ec,0x01f0,0x03ea,0x07f3},
+ {0x07eb,0x01eb,0x00ea,0x001a,0x0008,0x0019,0x00ee,0x01ef,0x07ed},
+ {0x03f0,0x00f2,0x0073,0x000b,0x0000,0x000a,0x0071,0x00f3,0x07e9},
+ {0x07ef,0x01ee,0x00ef,0x0018,0x0009,0x001b,0x00eb,0x01e9,0x07ec},
+ {0x07f6,0x03eb,0x01f3,0x00ed,0x0072,0x00e9,0x01f1,0x03ed,0x07f7},
+ {0x0ff6,0x07f0,0x03e9,0x01ed,0x00f1,0x01ea,0x03ec,0x07f8,0x0ff9},
+ {0x1ffc,0x0ffc,0x0ff5,0x07ea,0x03f3,0x03f2,0x07f5,0x0ffb,0x1ffe}
+};
+
+const UWord16 huff_ctab6[9][9]=
+{
+ {0x07fe,0x03fd,0x01f1,0x01eb,0x01f4,0x01ea,0x01f0,0x03fc,0x07fd},
+ {0x03f6,0x01e5,0x00ea,0x006c,0x0071,0x0068,0x00f0,0x01e6,0x03f7},
+ {0x01f3,0x00ef,0x0032,0x0027,0x0028,0x0026,0x0031,0x00eb,0x01f7},
+ {0x01e8,0x006f,0x002e,0x0008,0x0004,0x0006,0x0029,0x006b,0x01ee},
+ {0x01ef,0x0072,0x002d,0x0002,0x0000,0x0003,0x002f,0x0073,0x01fa},
+ {0x01e7,0x006e,0x002b,0x0007,0x0001,0x0005,0x002c,0x006d,0x01ec},
+ {0x01f9,0x00ee,0x0030,0x0024,0x002a,0x0025,0x0033,0x00ec,0x01f2},
+ {0x03f8,0x01e4,0x00ed,0x006a,0x0070,0x0069,0x0074,0x00f1,0x03fa},
+ {0x07ff,0x03f9,0x01f6,0x01ed,0x01f8,0x01e9,0x01f5,0x03fb,0x07fc}
+};
+
+const UWord16 huff_ctab7[8][8]=
+{
+ {0x0000,0x0005,0x0037,0x0074,0x00f2,0x01eb,0x03ed,0x07f7},
+ {0x0004,0x000c,0x0035,0x0071,0x00ec,0x00ee,0x01ee,0x01f5},
+ {0x0036,0x0034,0x0072,0x00ea,0x00f1,0x01e9,0x01f3,0x03f5},
+ {0x0073,0x0070,0x00eb,0x00f0,0x01f1,0x01f0,0x03ec,0x03fa},
+ {0x00f3,0x00ed,0x01e8,0x01ef,0x03ef,0x03f1,0x03f9,0x07fb},
+ {0x01ed,0x00ef,0x01ea,0x01f2,0x03f3,0x03f8,0x07f9,0x07fc},
+ {0x03ee,0x01ec,0x01f4,0x03f4,0x03f7,0x07f8,0x0ffd,0x0ffe},
+ {0x07f6,0x03f0,0x03f2,0x03f6,0x07fa,0x07fd,0x0ffc,0x0fff}
+};
+
+const UWord16 huff_ctab8[8][8]=
+{
+ {0x000e,0x0005,0x0010,0x0030,0x006f,0x00f1,0x01fa,0x03fe},
+ {0x0003,0x0000,0x0004,0x0012,0x002c,0x006a,0x0075,0x00f8},
+ {0x000f,0x0002,0x0006,0x0014,0x002e,0x0069,0x0072,0x00f5},
+ {0x002f,0x0011,0x0013,0x002a,0x0032,0x006c,0x00ec,0x00fa},
+ {0x0071,0x002b,0x002d,0x0031,0x006d,0x0070,0x00f2,0x01f9},
+ {0x00ef,0x0068,0x0033,0x006b,0x006e,0x00ee,0x00f9,0x03fc},
+ {0x01f8,0x0074,0x0073,0x00ed,0x00f0,0x00f6,0x01f6,0x01fd},
+ {0x03fd,0x00f3,0x00f4,0x00f7,0x01f7,0x01fb,0x01fc,0x03ff}
+};
+
+const UWord16 huff_ctab9[13][13]=
+{
+ {0x0000,0x0005,0x0037,0x00e7,0x01de,0x03ce,0x03d9,0x07c8,0x07cd,0x0fc8,0x0fdd,0x1fe4,0x1fec},
+ {0x0004,0x000c,0x0035,0x0072,0x00ea,0x00ed,0x01e2,0x03d1,0x03d3,0x03e0,0x07d8,0x0fcf,0x0fd5},
+ {0x0036,0x0034,0x0071,0x00e8,0x00ec,0x01e1,0x03cf,0x03dd,0x03db,0x07d0,0x0fc7,0x0fd4,0x0fe4},
+ {0x00e6,0x0070,0x00e9,0x01dd,0x01e3,0x03d2,0x03dc,0x07cc,0x07ca,0x07de,0x0fd8,0x0fea,0x1fdb},
+ {0x01df,0x00eb,0x01dc,0x01e6,0x03d5,0x03de,0x07cb,0x07dd,0x07dc,0x0fcd,0x0fe2,0x0fe7,0x1fe1},
+ {0x03d0,0x01e0,0x01e4,0x03d6,0x07c5,0x07d1,0x07db,0x0fd2,0x07e0,0x0fd9,0x0feb,0x1fe3,0x1fe9},
+ {0x07c4,0x01e5,0x03d7,0x07c6,0x07cf,0x07da,0x0fcb,0x0fda,0x0fe3,0x0fe9,0x1fe6,0x1ff3,0x1ff7},
+ {0x07d3,0x03d8,0x03e1,0x07d4,0x07d9,0x0fd3,0x0fde,0x1fdd,0x1fd9,0x1fe2,0x1fea,0x1ff1,0x1ff6},
+ {0x07d2,0x03d4,0x03da,0x07c7,0x07d7,0x07e2,0x0fce,0x0fdb,0x1fd8,0x1fee,0x3ff0,0x1ff4,0x3ff2},
+ {0x07e1,0x03df,0x07c9,0x07d6,0x0fca,0x0fd0,0x0fe5,0x0fe6,0x1feb,0x1fef,0x3ff3,0x3ff4,0x3ff5},
+ {0x0fe0,0x07ce,0x07d5,0x0fc6,0x0fd1,0x0fe1,0x1fe0,0x1fe8,0x1ff0,0x3ff1,0x3ff8,0x3ff6,0x7ffc},
+ {0x0fe8,0x07df,0x0fc9,0x0fd7,0x0fdc,0x1fdc,0x1fdf,0x1fed,0x1ff5,0x3ff9,0x3ffb,0x7ffd,0x7ffe},
+ {0x1fe7,0x0fcc,0x0fd6,0x0fdf,0x1fde,0x1fda,0x1fe5,0x1ff2,0x3ffa,0x3ff7,0x3ffc,0x3ffd,0x7fff}
+};
+
+const UWord16 huff_ctab10[13][13]=
+{
+ {0x0022,0x0008,0x001d,0x0026,0x005f,0x00d3,0x01cf,0x03d0,0x03d7,0x03ed,0x07f0,0x07f6,0x0ffd},
+ {0x0007,0x0000,0x0001,0x0009,0x0020,0x0054,0x0060,0x00d5,0x00dc,0x01d4,0x03cd,0x03de,0x07e7},
+ {0x001c,0x0002,0x0006,0x000c,0x001e,0x0028,0x005b,0x00cd,0x00d9,0x01ce,0x01dc,0x03d9,0x03f1},
+ {0x0025,0x000b,0x000a,0x000d,0x0024,0x0057,0x0061,0x00cc,0x00dd,0x01cc,0x01de,0x03d3,0x03e7},
+ {0x005d,0x0021,0x001f,0x0023,0x0027,0x0059,0x0064,0x00d8,0x00df,0x01d2,0x01e2,0x03dd,0x03ee},
+ {0x00d1,0x0055,0x0029,0x0056,0x0058,0x0062,0x00ce,0x00e0,0x00e2,0x01da,0x03d4,0x03e3,0x07eb},
+ {0x01c9,0x005e,0x005a,0x005c,0x0063,0x00ca,0x00da,0x01c7,0x01ca,0x01e0,0x03db,0x03e8,0x07ec},
+ {0x01e3,0x00d2,0x00cb,0x00d0,0x00d7,0x00db,0x01c6,0x01d5,0x01d8,0x03ca,0x03da,0x07ea,0x07f1},
+ {0x01e1,0x00d4,0x00cf,0x00d6,0x00de,0x00e1,0x01d0,0x01d6,0x03d1,0x03d5,0x03f2,0x07ee,0x07fb},
+ {0x03e9,0x01cd,0x01c8,0x01cb,0x01d1,0x01d7,0x01df,0x03cf,0x03e0,0x03ef,0x07e6,0x07f8,0x0ffa},
+ {0x03eb,0x01dd,0x01d3,0x01d9,0x01db,0x03d2,0x03cc,0x03dc,0x03ea,0x07ed,0x07f3,0x07f9,0x0ff9},
+ {0x07f2,0x03ce,0x01e4,0x03cb,0x03d8,0x03d6,0x03e2,0x03e5,0x07e8,0x07f4,0x07f5,0x07f7,0x0ffb},
+ {0x07fa,0x03ec,0x03df,0x03e1,0x03e4,0x03e6,0x03f0,0x07e9,0x07ef,0x0ff8,0x0ffe,0x0ffc,0x0fff}
+};
+
+const UWord16 huff_ctab11[17][17]=
+{
+ {0x0000,0x0006,0x0019,0x003d,0x009c,0x00c6,0x01a7,0x0390,0x03c2,0x03df,0x07e6,0x07f3,0x0ffb,0x07ec,0x0ffa,0x0ffe,0x038e},
+ {0x0005,0x0001,0x0008,0x0014,0x0037,0x0042,0x0092,0x00af,0x0191,0x01a5,0x01b5,0x039e,0x03c0,0x03a2,0x03cd,0x07d6,0x00ae},
+ {0x0017,0x0007,0x0009,0x0018,0x0039,0x0040,0x008e,0x00a3,0x00b8,0x0199,0x01ac,0x01c1,0x03b1,0x0396,0x03be,0x03ca,0x009d},
+ {0x003c,0x0015,0x0016,0x001a,0x003b,0x0044,0x0091,0x00a5,0x00be,0x0196,0x01ae,0x01b9,0x03a1,0x0391,0x03a5,0x03d5,0x0094},
+ {0x009a,0x0036,0x0038,0x003a,0x0041,0x008c,0x009b,0x00b0,0x00c3,0x019e,0x01ab,0x01bc,0x039f,0x038f,0x03a9,0x03cf,0x0093},
+ {0x00bf,0x003e,0x003f,0x0043,0x0045,0x009e,0x00a7,0x00b9,0x0194,0x01a2,0x01ba,0x01c3,0x03a6,0x03a7,0x03bb,0x03d4,0x009f},
+ {0x01a0,0x008f,0x008d,0x0090,0x0098,0x00a6,0x00b6,0x00c4,0x019f,0x01af,0x01bf,0x0399,0x03bf,0x03b4,0x03c9,0x03e7,0x00a8},
+ {0x01b6,0x00ab,0x00a4,0x00aa,0x00b2,0x00c2,0x00c5,0x0198,0x01a4,0x01b8,0x038c,0x03a4,0x03c4,0x03c6,0x03dd,0x03e8,0x00ad},
+ {0x03af,0x0192,0x00bd,0x00bc,0x018e,0x0197,0x019a,0x01a3,0x01b1,0x038d,0x0398,0x03b7,0x03d3,0x03d1,0x03db,0x07dd,0x00b4},
+ {0x03de,0x01a9,0x019b,0x019c,0x01a1,0x01aa,0x01ad,0x01b3,0x038b,0x03b2,0x03b8,0x03ce,0x03e1,0x03e0,0x07d2,0x07e5,0x00b7},
+ {0x07e3,0x01bb,0x01a8,0x01a6,0x01b0,0x01b2,0x01b7,0x039b,0x039a,0x03ba,0x03b5,0x03d6,0x07d7,0x03e4,0x07d8,0x07ea,0x00ba},
+ {0x07e8,0x03a0,0x01bd,0x01b4,0x038a,0x01c4,0x0392,0x03aa,0x03b0,0x03bc,0x03d7,0x07d4,0x07dc,0x07db,0x07d5,0x07f0,0x00c1},
+ {0x07fb,0x03c8,0x03a3,0x0395,0x039d,0x03ac,0x03ae,0x03c5,0x03d8,0x03e2,0x03e6,0x07e4,0x07e7,0x07e0,0x07e9,0x07f7,0x0190},
+ {0x07f2,0x0393,0x01be,0x01c0,0x0394,0x0397,0x03ad,0x03c3,0x03c1,0x03d2,0x07da,0x07d9,0x07df,0x07eb,0x07f4,0x07fa,0x0195},
+ {0x07f8,0x03bd,0x039c,0x03ab,0x03a8,0x03b3,0x03b9,0x03d0,0x03e3,0x03e5,0x07e2,0x07de,0x07ed,0x07f1,0x07f9,0x07fc,0x0193},
+ {0x0ffd,0x03dc,0x03b6,0x03c7,0x03cc,0x03cb,0x03d9,0x03da,0x07d3,0x07e1,0x07ee,0x07ef,0x07f5,0x07f6,0x0ffc,0x0fff,0x019d},
+ {0x01c2,0x00b5,0x00a1,0x0096,0x0097,0x0095,0x0099,0x00a0,0x00a2,0x00ac,0x00a9,0x00b1,0x00b3,0x00bb,0x00c0,0x018f,0x0004}
+};
+
+const UWord32 huff_ctabscf[121]=
+{
+ 0x0003ffe8,
+ 0x0003ffe6,
+ 0x0003ffe7,
+ 0x0003ffe5,
+ 0x0007fff5,
+ 0x0007fff1,
+ 0x0007ffed,
+ 0x0007fff6,
+ 0x0007ffee,
+ 0x0007ffef,
+ 0x0007fff0,
+ 0x0007fffc,
+ 0x0007fffd,
+ 0x0007ffff,
+ 0x0007fffe,
+ 0x0007fff7,
+ 0x0007fff8,
+ 0x0007fffb,
+ 0x0007fff9,
+ 0x0003ffe4,
+ 0x0007fffa,
+ 0x0003ffe3,
+ 0x0001ffef,
+ 0x0001fff0,
+ 0x0000fff5,
+ 0x0001ffee,
+ 0x0000fff2,
+ 0x0000fff3,
+ 0x0000fff4,
+ 0x0000fff1,
+ 0x00007ff6,
+ 0x00007ff7,
+ 0x00003ff9,
+ 0x00003ff5,
+ 0x00003ff7,
+ 0x00003ff3,
+ 0x00003ff6,
+ 0x00003ff2,
+ 0x00001ff7,
+ 0x00001ff5,
+ 0x00000ff9,
+ 0x00000ff7,
+ 0x00000ff6,
+ 0x000007f9,
+ 0x00000ff4,
+ 0x000007f8,
+ 0x000003f9,
+ 0x000003f7,
+ 0x000003f5,
+ 0x000001f8,
+ 0x000001f7,
+ 0x000000fa,
+ 0x000000f8,
+ 0x000000f6,
+ 0x00000079,
+ 0x0000003a,
+ 0x00000038,
+ 0x0000001a,
+ 0x0000000b,
+ 0x00000004,
+ 0x00000000,
+ 0x0000000a,
+ 0x0000000c,
+ 0x0000001b,
+ 0x00000039,
+ 0x0000003b,
+ 0x00000078,
+ 0x0000007a,
+ 0x000000f7,
+ 0x000000f9,
+ 0x000001f6,
+ 0x000001f9,
+ 0x000003f4,
+ 0x000003f6,
+ 0x000003f8,
+ 0x000007f5,
+ 0x000007f4,
+ 0x000007f6,
+ 0x000007f7,
+ 0x00000ff5,
+ 0x00000ff8,
+ 0x00001ff4,
+ 0x00001ff6,
+ 0x00001ff8,
+ 0x00003ff8,
+ 0x00003ff4,
+ 0x0000fff0,
+ 0x00007ff4,
+ 0x0000fff6,
+ 0x00007ff5,
+ 0x0003ffe2,
+ 0x0007ffd9,
+ 0x0007ffda,
+ 0x0007ffdb,
+ 0x0007ffdc,
+ 0x0007ffdd,
+ 0x0007ffde,
+ 0x0007ffd8,
+ 0x0007ffd2,
+ 0x0007ffd3,
+ 0x0007ffd4,
+ 0x0007ffd5,
+ 0x0007ffd6,
+ 0x0007fff2,
+ 0x0007ffdf,
+ 0x0007ffe7,
+ 0x0007ffe8,
+ 0x0007ffe9,
+ 0x0007ffea,
+ 0x0007ffeb,
+ 0x0007ffe6,
+ 0x0007ffe0,
+ 0x0007ffe1,
+ 0x0007ffe2,
+ 0x0007ffe3,
+ 0x0007ffe4,
+ 0x0007ffe5,
+ 0x0007ffd7,
+ 0x0007ffec,
+ 0x0007fff4,
+ 0x0007fff3
+};
+
+const Word32 m_log2_table[INT_BITS] = {
+ 0x00000000,0x4ae00d00,0x2934f080,0x15c01a3f,
+ 0x0b31fb80,0x05aeb4e0,0x02dcf2d0,0x016fe50c,
+ 0x00b84e23,0x005c3e10,0x002e24ca,0x001713d6,
+ 0x000b8a47,0x0005c53b,0x0002e2a3,0x00017153,
+ 0x0000b8aa,0x00005c55,0x00002e2b,0x00001715,
+ 0x00000b8b,0x000005c5,0x000002e3,0x00000171,
+ 0x000000b9,0x0000005c,0x0000002e,0x00000017,
+ 0x0000000c,0x00000006,0x00000003,0x00000001
+};
+
+
+/*
+ 3 bit resolution
+*/
+const Word32 tnsCoeff3[8] =
+{
+ 0x81f1d1d4,
+ 0x9126147c,
+ 0xadb922f7,
+ 0xd438af09,
+ 0x00000000,
+ 0x37898087,
+ 0x64130dfa,
+ 0x7cca6ffb,
+};
+
+const Word32 tnsCoeff3Borders[8] =
+{
+ 0x80000000, /* -4 */
+ 0x87b826de, /* -3 */
+ 0x9df24153, /* -2 */
+ 0xbfffffe5, /* -1 */
+ 0xe9c5e578, /* 0 */
+ 0x1c7b90f0, /* 1 */
+ 0x4fce83aa, /* 2 */
+ 0x7352f2c4, /* 3 */
+};
+
+
+/*
+ 4 bit resolution
+*/
+
+const Word32 tnsCoeff4[16] =
+{
+ 0x808bc84b,
+ 0x84e2e57d,
+ 0x8d6b49fb,
+ 0x99da9207,
+ 0xa9c45707,
+ 0xbc9dde78,
+ 0xd1c2d4fc,
+ 0xe87ae539,
+ 0x00000000,
+ 0x1a9cd9c0,
+ 0x340ff23b,
+ 0x4b3c8bf7,
+ 0x5f1f5e80,
+ 0x6ed9eb84,
+ 0x79bc3880,
+ 0x7f4c7e89
+};
+
+const Word32 tnsCoeff4Borders[16]=
+{
+ 0x80000000, /* -8 */
+ 0x822defef, /* -7 */
+ 0x88a4bfe5, /* -6 */
+ 0x932c159c, /* -5 */
+ 0xa16827c1, /* -4 */
+ 0xb2dcde26, /* -3 */
+ 0xc6f20b91, /* -2 */
+ 0xdcf89c64, /* -1 */
+ 0xf4308ce1, /* 0 */
+ 0x0d613054, /* 1 */
+ 0x278dde80, /* 2 */
+ 0x4000001b, /* 3 */
+ 0x55a6127c, /* 4 */
+ 0x678dde8f, /* 5 */
+ 0x74ef0ed8, /* 6 */
+ 0x7d33f0db /* 7 */
+};
+
+
+const unsigned char bitrevTab[17 + 129] =
+{
+/* 64 */
+0x01, 0x08, 0x02, 0x04, 0x03, 0x0c, 0x05, 0x0a, 0x07, 0x0e, 0x0b, 0x0d, 0x00, 0x06, 0x09, 0x0f,
+0x00,
+
+/* 512 */
+0x01, 0x40, 0x02, 0x20, 0x03, 0x60, 0x04, 0x10, 0x05, 0x50, 0x06, 0x30, 0x07, 0x70, 0x09, 0x48,
+0x0a, 0x28, 0x0b, 0x68, 0x0c, 0x18, 0x0d, 0x58, 0x0e, 0x38, 0x0f, 0x78, 0x11, 0x44, 0x12, 0x24,
+0x13, 0x64, 0x15, 0x54, 0x16, 0x34, 0x17, 0x74, 0x19, 0x4c, 0x1a, 0x2c, 0x1b, 0x6c, 0x1d, 0x5c,
+0x1e, 0x3c, 0x1f, 0x7c, 0x21, 0x42, 0x23, 0x62, 0x25, 0x52, 0x26, 0x32, 0x27, 0x72, 0x29, 0x4a,
+0x2b, 0x6a, 0x2d, 0x5a, 0x2e, 0x3a, 0x2f, 0x7a, 0x31, 0x46, 0x33, 0x66, 0x35, 0x56, 0x37, 0x76,
+0x39, 0x4e, 0x3b, 0x6e, 0x3d, 0x5e, 0x3f, 0x7e, 0x43, 0x61, 0x45, 0x51, 0x47, 0x71, 0x4b, 0x69,
+0x4d, 0x59, 0x4f, 0x79, 0x53, 0x65, 0x57, 0x75, 0x5b, 0x6d, 0x5f, 0x7d, 0x67, 0x73, 0x6f, 0x7b,
+0x00, 0x08, 0x14, 0x1c, 0x22, 0x2a, 0x36, 0x3e, 0x41, 0x49, 0x55, 0x5d, 0x63, 0x6b, 0x77, 0x7f,
+0x00,
+}; \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc.c b/media/libstagefright/codecs/aacenc/src/aacenc.c
new file mode 100644
index 0000000..552ae41
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/aacenc.c
@@ -0,0 +1,495 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: aacenc.c
+
+ Content: aac encoder interface functions
+
+*******************************************************************************/
+
+#include "voAAC.h"
+#include "typedef.h"
+#include "aacenc_core.h"
+#include "aac_rom.h"
+#include "cmnMemory.h"
+#include "memalign.h"
+
+/**
+* Init the audio codec module and return codec handle
+* \param phCodec [OUT] Return the video codec handle
+* \param vType [IN] The codec type if the module support multi codec.
+* \param pUserData [IN] The init param. It is memory operator or alloced memory
+* \retval VO_ERR_NONE Succeeded.
+*/
+VO_U32 VO_API voAACEncInit(VO_HANDLE * phCodec,VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA *pUserData)
+{
+ AAC_ENCODER*hAacEnc;
+ AACENC_CONFIG config;
+ int error;
+
+#ifdef USE_DEAULT_MEM
+ VO_MEM_OPERATOR voMemoprator;
+#endif
+ VO_MEM_OPERATOR *pMemOP;
+ int interMem;
+
+ interMem = 0;
+ error = 0;
+
+ /* init the memory operator */
+ if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
+ {
+#ifdef USE_DEAULT_MEM
+ voMemoprator.Alloc = cmnMemAlloc;
+ voMemoprator.Copy = cmnMemCopy;
+ voMemoprator.Free = cmnMemFree;
+ voMemoprator.Set = cmnMemSet;
+ voMemoprator.Check = cmnMemCheck;
+
+ interMem = 1;
+
+ pMemOP = &voMemoprator;
+#else
+ *phCodec = NULL;
+ return VO_ERR_INVALID_ARG;
+#endif
+ }
+ else
+ {
+ pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
+ }
+
+ /* init the aac encoder handle */
+ hAacEnc = (AAC_ENCODER*)mem_malloc(pMemOP, sizeof(AAC_ENCODER), 32, VO_INDEX_ENC_AAC);
+ if(NULL == hAacEnc)
+ {
+ error = 1;
+ }
+
+ if(!error)
+ {
+ /* init the aac encoder intra memory */
+ hAacEnc->intbuf = (short *)mem_malloc(pMemOP, AACENC_BLOCKSIZE*MAX_CHANNELS*sizeof(short), 32, VO_INDEX_ENC_AAC);
+ if(NULL == hAacEnc->intbuf)
+ {
+ error = 1;
+ }
+ }
+
+ if (!error) {
+ /* init the aac encoder psychoacoustic */
+ error = (PsyNew(&hAacEnc->psyKernel, MAX_CHANNELS, pMemOP) ||
+ PsyOutNew(&hAacEnc->psyOut, pMemOP));
+ }
+
+ if (!error) {
+ /* init the aac encoder quantization elements */
+ error = QCOutNew(&hAacEnc->qcOut,MAX_CHANNELS, pMemOP);
+ }
+
+ if (!error) {
+ /* init the aac encoder quantization state */
+ error = QCNew(&hAacEnc->qcKernel, pMemOP);
+ }
+
+ /* uninit the aac encoder if error is nozero */
+ if(error)
+ {
+ AacEncClose(hAacEnc, pMemOP);
+ if(hAacEnc)
+ {
+ mem_free(pMemOP, hAacEnc, VO_INDEX_ENC_AAC);
+ hAacEnc = NULL;
+ }
+ *phCodec = NULL;
+ return VO_ERR_OUTOF_MEMORY;
+ }
+
+ /* init the aac encoder memory operator */
+#ifdef USE_DEAULT_MEM
+ if(interMem)
+ {
+ hAacEnc->voMemoprator.Alloc = cmnMemAlloc;
+ hAacEnc->voMemoprator.Copy = cmnMemCopy;
+ hAacEnc->voMemoprator.Free = cmnMemFree;
+ hAacEnc->voMemoprator.Set = cmnMemSet;
+ hAacEnc->voMemoprator.Check = cmnMemCheck;
+
+ pMemOP = &hAacEnc->voMemoprator;
+ }
+#endif
+ /* init the aac encoder default parameter */
+ if(hAacEnc->initOK == 0)
+ {
+ AACENC_CONFIG config;
+ config.adtsUsed = 1;
+ config.bitRate = 128000;
+ config.nChannelsIn = 2;
+ config.nChannelsOut = 2;
+ config.sampleRate = 44100;
+ config.bandWidth = 20000;
+
+ AacEncOpen(hAacEnc, config);
+ }
+
+ hAacEnc->voMemop = pMemOP;
+
+ *phCodec = hAacEnc;
+
+ return VO_ERR_NONE;
+}
+
+/**
+* Set input audio data.
+* \param hCodec [IN]] The Codec Handle which was created by Init function.
+* \param pInput [IN] The input buffer param.
+* \param pOutBuffer [OUT] The output buffer info.
+* \retval VO_ERR_NONE Succeeded.
+*/
+VO_U32 VO_API voAACEncSetInputData(VO_HANDLE hCodec, VO_CODECBUFFER * pInput)
+{
+ AAC_ENCODER *hAacEnc;
+ int length;
+
+ if(NULL == hCodec || NULL == pInput || NULL == pInput->Buffer)
+ {
+ return VO_ERR_INVALID_ARG;
+ }
+
+ hAacEnc = (AAC_ENCODER *)hCodec;
+
+ /* init input pcm buffer and length*/
+ hAacEnc->inbuf = (short *)pInput->Buffer;
+ hAacEnc->inlen = pInput->Length / sizeof(short);
+ hAacEnc->uselength = 0;
+
+ hAacEnc->encbuf = hAacEnc->inbuf;
+ hAacEnc->enclen = hAacEnc->inlen;
+
+ /* rebuild intra pcm buffer and length*/
+ if(hAacEnc->intlen)
+ {
+ length = min(hAacEnc->config.nChannelsIn*AACENC_BLOCKSIZE - hAacEnc->intlen, hAacEnc->inlen);
+ hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf + hAacEnc->intlen,
+ hAacEnc->inbuf, length*sizeof(short));
+
+ hAacEnc->encbuf = hAacEnc->intbuf;
+ hAacEnc->enclen = hAacEnc->intlen + length;
+
+ hAacEnc->inbuf += length;
+ hAacEnc->inlen -= length;
+ }
+
+ return VO_ERR_NONE;
+}
+
+/**
+* Get the outut audio data
+* \param hCodec [IN]] The Codec Handle which was created by Init function.
+* \param pOutBuffer [OUT] The output audio data
+* \param pOutInfo [OUT] The dec module filled audio format and used the input size.
+* pOutInfo->InputUsed is total used the input size.
+* \retval VO_ERR_NONE Succeeded.
+* VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought.
+*/
+VO_U32 VO_API voAACEncGetOutputData(VO_HANDLE hCodec, VO_CODECBUFFER * pOutput, VO_AUDIO_OUTPUTINFO * pOutInfo)
+{
+ AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
+ Word16 numAncDataBytes=0;
+ Word32 inbuflen;
+ int ret, length;
+ if(NULL == hAacEnc)
+ return VO_ERR_INVALID_ARG;
+
+ inbuflen = AACENC_BLOCKSIZE*hAacEnc->config.nChannelsIn;
+
+ /* check the input pcm buffer and length*/
+ if(NULL == hAacEnc->encbuf || hAacEnc->enclen < inbuflen)
+ {
+ length = hAacEnc->enclen;
+ if(hAacEnc->intlen == 0)
+ {
+ hAacEnc->voMemop->Copy(VO_INDEX_ENC_AAC, hAacEnc->intbuf,
+ hAacEnc->encbuf, length*sizeof(short));
+ hAacEnc->uselength += length*sizeof(short);
+ }
+ else
+ {
+ hAacEnc->uselength += (length - hAacEnc->intlen)*sizeof(short);
+ }
+
+ hAacEnc->intlen = length;
+
+ pOutput->Length = 0;
+ if(pOutInfo)
+ pOutInfo->InputUsed = hAacEnc->uselength;
+ return VO_ERR_INPUT_BUFFER_SMALL;
+ }
+
+ /* check the output aac buffer and length*/
+ if(NULL == pOutput || NULL == pOutput->Buffer || pOutput->Length < (6144/8)*hAacEnc->config.nChannelsOut/(sizeof(Word32)))
+ return VO_ERR_OUTPUT_BUFFER_SMALL;
+
+ /* aac encoder core function */
+ AacEncEncode( hAacEnc,
+ (Word16*)hAacEnc->encbuf,
+ NULL,
+ &numAncDataBytes,
+ pOutput->Buffer,
+ &pOutput->Length);
+
+ /* update the input pcm buffer and length*/
+ if(hAacEnc->intlen)
+ {
+ length = inbuflen - hAacEnc->intlen;
+ hAacEnc->encbuf = hAacEnc->inbuf;
+ hAacEnc->enclen = hAacEnc->inlen;
+ hAacEnc->uselength += length*sizeof(short);
+ hAacEnc->intlen = 0;
+ }
+ else
+ {
+ hAacEnc->encbuf = hAacEnc->encbuf + inbuflen;
+ hAacEnc->enclen = hAacEnc->enclen - inbuflen;
+ hAacEnc->uselength += inbuflen*sizeof(short);
+ }
+
+ /* update the output aac information */
+ if(pOutInfo)
+ {
+ pOutInfo->Format.Channels = hAacEnc->config.nChannelsOut;
+ pOutInfo->Format.SampleRate = hAacEnc->config.sampleRate;
+ pOutInfo->Format.SampleBits = 16;
+ pOutInfo->InputUsed = hAacEnc->uselength;
+ }
+
+ return VO_ERR_NONE;
+}
+
+/**
+* Uninit the Codec.
+* \param hCodec [IN]] The Codec Handle which was created by Init function.
+* \retval VO_ERR_NONE Succeeded.
+*/
+VO_U32 VO_API voAACEncUninit(VO_HANDLE hCodec)
+{
+ AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
+
+ if(NULL != hAacEnc)
+ {
+ /* close the aac encoder */
+ AacEncClose(hAacEnc, hAacEnc->voMemop);
+
+ /* free the aac encoder handle*/
+ mem_free(hAacEnc->voMemop, hAacEnc, VO_INDEX_ENC_AAC);
+ hAacEnc = NULL;
+ }
+
+ return VO_ERR_NONE;
+}
+
+/**
+* Set the param for special target.
+* \param hCodec [IN]] The Codec Handle which was created by Init function.
+* \param uParamID [IN] The param ID.
+* \param pData [IN] The param value depend on the ID>
+* \retval VO_ERR_NONE Succeeded.
+*/
+VO_U32 VO_API voAACEncSetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
+{
+ AACENC_CONFIG config;
+ AACENC_PARAM* pAAC_param;
+ VO_AUDIO_FORMAT *pWAV_Format;
+ AAC_ENCODER* hAacEnc = (AAC_ENCODER*)hCodec;
+ int ret, i, bitrate, tmp;
+ int SampleRateIdx;
+
+ if(NULL == hAacEnc)
+ return VO_ERR_INVALID_ARG;
+
+ switch(uParamID)
+ {
+ case VO_PID_AAC_ENCPARAM: /* init aac encoder parameter*/
+ AacInitDefaultConfig(&config);
+ if(pData == NULL)
+ return VO_ERR_INVALID_ARG;
+ pAAC_param = (AACENC_PARAM*)pData;
+ config.adtsUsed = pAAC_param->adtsUsed;
+ config.bitRate = pAAC_param->bitRate;
+ config.nChannelsIn = pAAC_param->nChannels;
+ config.nChannelsOut = pAAC_param->nChannels;
+ config.sampleRate = pAAC_param->sampleRate;
+
+ /* check the channel */
+ if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS ||
+ config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
+ return VO_ERR_AUDIO_UNSCHANNEL;
+
+ /* check the samplerate */
+ ret = -1;
+ for(i = 0; i < NUM_SAMPLE_RATES; i++)
+ {
+ if(config.sampleRate == sampRateTab[i])
+ {
+ ret = 0;
+ break;
+ }
+ }
+ if(ret < 0)
+ return VO_ERR_AUDIO_UNSSAMPLERATE;
+
+ SampleRateIdx = i;
+
+ tmp = 441;
+ if(config.sampleRate%8000 == 0)
+ tmp =480;
+ /* check the bitrate */
+ if(config.bitRate!=0 && (config.bitRate/config.nChannelsOut < 4000) ||
+ (config.bitRate/config.nChannelsOut > 160000) ||
+ (config.bitRate > config.sampleRate*6*config.nChannelsOut))
+ {
+ config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
+
+ if(config.bitRate/config.nChannelsOut < 4000)
+ config.bitRate = 4000 * config.nChannelsOut;
+ else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
+ config.bitRate = config.sampleRate*6*config.nChannelsOut;
+ else if(config.bitRate/config.nChannelsOut > 160000)
+ config.bitRate = config.nChannelsOut*160000;
+ }
+
+ /* check the bandwidth */
+ bitrate = config.bitRate / config.nChannelsOut;
+ bitrate = bitrate * tmp / config.sampleRate;
+
+ for (i = 0; rates[i]; i++)
+ {
+ if (rates[i] >= bitrate)
+ break;
+ }
+
+ config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
+
+ /* init aac encoder core */
+ ret = AacEncOpen(hAacEnc, config);
+ if(ret)
+ return VO_ERR_AUDIO_UNSFEATURE;
+ break;
+ case VO_PID_AUDIO_FORMAT: /* init pcm channel and samplerate*/
+ AacInitDefaultConfig(&config);
+ if(pData == NULL)
+ return VO_ERR_INVALID_ARG;
+ pWAV_Format = (VO_AUDIO_FORMAT*)pData;
+ config.adtsUsed = 1;
+ config.nChannelsIn = pWAV_Format->Channels;
+ config.nChannelsOut = pWAV_Format->Channels;
+ config.sampleRate = pWAV_Format->SampleRate;
+
+ /* check the channel */
+ if(config.nChannelsIn< 1 || config.nChannelsIn > MAX_CHANNELS ||
+ config.nChannelsOut < 1 || config.nChannelsOut > MAX_CHANNELS || config.nChannelsIn < config.nChannelsOut)
+ return VO_ERR_AUDIO_UNSCHANNEL;
+
+ /* check the samplebits */
+ if(pWAV_Format->SampleBits != 16)
+ {
+ return VO_ERR_AUDIO_UNSFEATURE;
+ }
+
+ /* check the samplerate */
+ ret = -1;
+ for(i = 0; i < NUM_SAMPLE_RATES; i++)
+ {
+ if(config.sampleRate == sampRateTab[i])
+ {
+ ret = 0;
+ break;
+ }
+ }
+ if(ret < 0)
+ return VO_ERR_AUDIO_UNSSAMPLERATE;
+
+ SampleRateIdx = i;
+
+ /* update the bitrates */
+ tmp = 441;
+ if(config.sampleRate%8000 == 0)
+ tmp =480;
+
+ config.bitRate = 640*config.sampleRate/tmp*config.nChannelsOut;
+
+ if(config.bitRate/config.nChannelsOut < 4000)
+ config.bitRate = 4000 * config.nChannelsOut;
+ else if(config.bitRate > config.sampleRate*6*config.nChannelsOut)
+ config.bitRate = config.sampleRate*6*config.nChannelsOut;
+ else if(config.bitRate/config.nChannelsOut > 160000)
+ config.bitRate = config.nChannelsOut*160000;
+
+ /* check the bandwidth */
+ bitrate = config.bitRate / config.nChannelsOut;
+ bitrate = bitrate * tmp / config.sampleRate;
+
+ for (i = 0; rates[i]; i++)
+ {
+ if (rates[i] >= bitrate)
+ break;
+ }
+
+ config.bandWidth = BandwithCoefTab[i][SampleRateIdx];
+
+ /* init aac encoder core */
+ ret = AacEncOpen(hAacEnc, config);
+ if(ret)
+ return VO_ERR_AUDIO_UNSFEATURE;
+ break;
+ default:
+ return VO_ERR_WRONG_PARAM_ID;
+ }
+
+ return VO_ERR_NONE;
+}
+
+/**
+* Get the param for special target.
+* \param hCodec [IN]] The Codec Handle which was created by Init function.
+* \param uParamID [IN] The param ID.
+* \param pData [IN] The param value depend on the ID>
+* \retval VO_ERR_NONE Succeeded.
+*/
+VO_U32 VO_API voAACEncGetParam(VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData)
+{
+ return VO_ERR_NONE;
+}
+
+/**
+ * Get audio codec API interface
+ * \param pEncHandle [out] Return the AAC Encoder handle.
+ * \retval VO_ERR_OK Succeeded.
+ */
+VO_S32 VO_API voGetAACEncAPI(VO_AUDIO_CODECAPI * pDecHandle)
+{
+ if(pDecHandle == NULL)
+ return VO_ERR_INVALID_ARG;
+
+ pDecHandle->Init = voAACEncInit;
+ pDecHandle->SetInputData = voAACEncSetInputData;
+ pDecHandle->GetOutputData = voAACEncGetOutputData;
+ pDecHandle->SetParam = voAACEncSetParam;
+ pDecHandle->GetParam = voAACEncGetParam;
+ pDecHandle->Uninit = voAACEncUninit;
+
+ return VO_ERR_NONE;
+} \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/aacenc_core.c b/media/libstagefright/codecs/aacenc/src/aacenc_core.c
new file mode 100644
index 0000000..616475c
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/aacenc_core.c
@@ -0,0 +1,239 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: aacenc_core.c
+
+ Content: aac encoder core functions
+
+*******************************************************************************/
+
+#include "typedef.h"
+#include "aacenc_core.h"
+#include "bitenc.h"
+
+#include "psy_configuration.h"
+#include "psy_main.h"
+#include "qc_main.h"
+#include "psy_main.h"
+#include "channel_map.h"
+#include "aac_rom.h"
+
+/********************************************************************************
+*
+* function name: AacInitDefaultConfig
+* description: gives reasonable default configuration
+*
+**********************************************************************************/
+void AacInitDefaultConfig(AACENC_CONFIG *config)
+{
+ /* default configurations */
+ config->adtsUsed = 1;
+ config->nChannelsIn = 2;
+ config->nChannelsOut = 2;
+ config->bitRate = 128000;
+ config->bandWidth = 0;
+}
+
+/********************************************************************************
+*
+* function name: AacEncOpen
+* description: allocate and initialize a new encoder instance
+* returns: 0 if success
+*
+**********************************************************************************/
+Word16 AacEncOpen( AAC_ENCODER* hAacEnc, /* pointer to an encoder handle, initialized on return */
+ const AACENC_CONFIG config /* pre-initialized config struct */
+ )
+{
+ Word32 i;
+ Word32 error = 0;
+ Word16 profile = 1;
+
+ ELEMENT_INFO *elInfo = NULL;
+
+ if (hAacEnc==0) {
+ error=1;
+ }
+
+ if (!error) {
+ hAacEnc->config = config;
+ }
+
+ if (!error) {
+ error = InitElementInfo (config.nChannelsOut,
+ &hAacEnc->elInfo);
+ }
+
+ if (!error) {
+ elInfo = &hAacEnc->elInfo;
+ }
+
+ if (!error) {
+ /* use or not tns tool for long and short block */
+ Word16 tnsMask=3;
+
+ /* init encoder psychoacoustic */
+ error = psyMainInit(&hAacEnc->psyKernel,
+ config.sampleRate,
+ config.bitRate,
+ elInfo->nChannelsInEl,
+ tnsMask,
+ hAacEnc->config.bandWidth);
+ }
+
+ /* use or not adts header */
+ if(!error) {
+ hAacEnc->qcOut.qcElement.adtsUsed = config.adtsUsed;
+ }
+
+ /* init encoder quantization */
+ if (!error) {
+ struct QC_INIT qcInit;
+
+ /*qcInit.channelMapping = &hAacEnc->channelMapping;*/
+ qcInit.elInfo = &hAacEnc->elInfo;
+
+ qcInit.maxBits = (Word16) (MAXBITS_COEF*elInfo->nChannelsInEl);
+ qcInit.bitRes = qcInit.maxBits;
+ qcInit.averageBits = (Word16) ((config.bitRate * FRAME_LEN_LONG) / config.sampleRate);
+
+ qcInit.padding.paddingRest = config.sampleRate;
+
+ qcInit.meanPe = (Word16) ((10 * FRAME_LEN_LONG * hAacEnc->config.bandWidth) /
+ (config.sampleRate>>1));
+
+ qcInit.maxBitFac = (Word16) ((100 * (MAXBITS_COEF-MINBITS_COEF)* elInfo->nChannelsInEl)/
+ (qcInit.averageBits?qcInit.averageBits:1));
+
+ qcInit.bitrate = config.bitRate;
+
+ error = QCInit(&hAacEnc->qcKernel, &qcInit);
+ }
+
+ /* init bitstream encoder */
+ if (!error) {
+ hAacEnc->bseInit.nChannels = elInfo->nChannelsInEl;
+ hAacEnc->bseInit.bitrate = config.bitRate;
+ hAacEnc->bseInit.sampleRate = config.sampleRate;
+ hAacEnc->bseInit.profile = profile;
+ }
+
+ return error;
+}
+
+/********************************************************************************
+*
+* function name: AacEncEncode
+* description: encode pcm to aac data core function
+* returns: 0 if success
+*
+**********************************************************************************/
+Word16 AacEncEncode(AAC_ENCODER *aacEnc, /*!< an encoder handle */
+ Word16 *timeSignal, /*!< BLOCKSIZE*nChannels audio samples, interleaved */
+ const UWord8 *ancBytes, /*!< pointer to ancillary data bytes */
+ Word16 *numAncBytes, /*!< number of ancillary Data Bytes */
+ UWord8 *outBytes, /*!< pointer to output buffer (must be large MINBITS_COEF/8*MAX_CHANNELS bytes) */
+ Word32 *numOutBytes /*!< number of bytes in output buffer after processing */
+ )
+{
+ ELEMENT_INFO *elInfo = &aacEnc->elInfo;
+ Word16 globUsedBits;
+ Word16 ancDataBytes, ancDataBytesLeft;
+
+ ancDataBytes = ancDataBytesLeft = *numAncBytes;
+
+ /* init output aac data buffer and length */
+ aacEnc->hBitStream = CreateBitBuffer(&aacEnc->bitStream, outBytes, *numOutBytes);
+
+ /* psychoacoustic process */
+ psyMain(aacEnc->config.nChannelsOut,
+ elInfo,
+ timeSignal,
+ &aacEnc->psyKernel.psyData[elInfo->ChannelIndex[0]],
+ &aacEnc->psyKernel.tnsData[elInfo->ChannelIndex[0]],
+ &aacEnc->psyKernel.psyConfLong,
+ &aacEnc->psyKernel.psyConfShort,
+ &aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
+ &aacEnc->psyOut.psyOutElement,
+ aacEnc->psyKernel.pScratchTns,
+ aacEnc->config.sampleRate);
+
+ /* adjust bitrate and frame length */
+ AdjustBitrate(&aacEnc->qcKernel,
+ aacEnc->config.bitRate,
+ aacEnc->config.sampleRate);
+
+ /* quantization and coding process */
+ QCMain(&aacEnc->qcKernel,
+ &aacEnc->qcKernel.elementBits,
+ &aacEnc->qcKernel.adjThr.adjThrStateElem,
+ &aacEnc->psyOut.psyOutChannel[elInfo->ChannelIndex[0]],
+ &aacEnc->psyOut.psyOutElement,
+ &aacEnc->qcOut.qcChannel[elInfo->ChannelIndex[0]],
+ &aacEnc->qcOut.qcElement,
+ elInfo->nChannelsInEl,
+ min(ancDataBytesLeft,ancDataBytes));
+
+ ancDataBytesLeft = ancDataBytesLeft - ancDataBytes;
+
+ globUsedBits = FinalizeBitConsumption(&aacEnc->qcKernel,
+ &aacEnc->qcOut);
+
+ /* write bitstream process */
+ WriteBitstream(aacEnc->hBitStream,
+ *elInfo,
+ &aacEnc->qcOut,
+ &aacEnc->psyOut,
+ &globUsedBits,
+ ancBytes,
+ aacEnc->psyKernel.sampleRateIdx);
+
+ updateBitres(&aacEnc->qcKernel,
+ &aacEnc->qcOut);
+
+ /* write out the bitstream */
+ *numOutBytes = GetBitsAvail(aacEnc->hBitStream) >> 3;
+
+ return 0;
+}
+
+
+/********************************************************************************
+*
+* function name:AacEncClose
+* description: deallocate an encoder instance
+*
+**********************************************************************************/
+void AacEncClose (AAC_ENCODER* hAacEnc, VO_MEM_OPERATOR *pMemOP)
+{
+ if (hAacEnc) {
+ QCDelete(&hAacEnc->qcKernel, pMemOP);
+
+ QCOutDelete(&hAacEnc->qcOut, pMemOP);
+
+ PsyDelete(&hAacEnc->psyKernel, pMemOP);
+
+ PsyOutDelete(&hAacEnc->psyOut, pMemOP);
+
+ DeleteBitBuffer(&hAacEnc->hBitStream);
+
+ if(hAacEnc->intbuf)
+ {
+ mem_free(pMemOP, hAacEnc->intbuf, VO_INDEX_ENC_AAC);
+ hAacEnc->intbuf = NULL;
+ }
+ }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c
new file mode 100644
index 0000000..0dbd216
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c
@@ -0,0 +1,1223 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: adj_thr.c
+
+ Content: Threshold compensation functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "adj_thr_data.h"
+#include "adj_thr.h"
+#include "qc_data.h"
+#include "line_pe.h"
+
+
+#define minSnrLimit 0x6666 /* 1 dB */
+#define PEBITS_COEF 0x170a /* 0.18*(1 << 15)*/
+
+#define HOLE_THR_LONG 0x2873 /* 0.316*(1 << 15) */
+#define HOLE_THR_SHORT 0x4000 /* 0.5 *(1 << 15) */
+
+#define MS_THRSPREAD_COEF 0x7333 /* 0.9 * (1 << 15) */
+
+#define MIN_SNR_COEF 0x651f /* 3.16* (1 << (15 - 2)) */
+
+/* values for avoid hole flag */
+enum _avoid_hole_state {
+ NO_AH =0,
+ AH_INACTIVE =1,
+ AH_ACTIVE =2
+};
+
+/********************************************************************************
+*
+* function name:bits2pe
+* description: convert from bits to pe
+* pe = 1.18*desiredBits
+*
+**********************************************************************************/
+Word16 bits2pe(const Word16 bits) {
+ return (bits + ((PEBITS_COEF * bits) >> 15));
+}
+
+/********************************************************************************
+*
+* function name:calcThreshExp
+* description: loudness calculation (threshold to the power of redExp)
+* thr(n)^0.25
+*
+**********************************************************************************/
+static void calcThreshExp(Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const Word16 nChannels)
+{
+ Word16 ch, sfb, sfbGrp;
+ Word32 *pthrExp, *psfbThre;
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup)
+ pthrExp = &(thrExp[ch][sfbGrp]);
+ psfbThre = psyOutChan->sfbThreshold + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ *pthrExp = rsqrt(rsqrt(*psfbThre,INT_BITS),INT_BITS);
+ pthrExp++; psfbThre++;
+ }
+ }
+}
+
+/********************************************************************************
+*
+* function name:adaptMinSnr
+* description: reduce minSnr requirements for bands with relative low energies
+*
+**********************************************************************************/
+static void adaptMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ MINSNR_ADAPT_PARAM *msaParam,
+ const Word16 nChannels)
+{
+ Word16 ch, sfb, sfbOffs, shift;
+ Word32 nSfb, avgEn;
+ Word16 log_avgEn = 0;
+ Word32 startRatio_x_avgEn = 0;
+
+
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL* psyOutChan = &psyOutChannel[ch];
+
+ /* calc average energy per scalefactor band */
+ avgEn = 0;
+ nSfb = 0;
+ for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfbOffs+sfb]);
+ nSfb = nSfb + 1;
+ }
+ }
+
+ if (nSfb > 0) {
+ avgEn = avgEn / nSfb;
+
+ log_avgEn = iLog4(avgEn);
+ startRatio_x_avgEn = fixmul(msaParam->startRatio, avgEn);
+ }
+
+
+ /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
+ for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup) {
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ if (psyOutChan->sfbEnergy[sfbOffs+sfb] < startRatio_x_avgEn) {
+ Word16 dbRatio, minSnrRed;
+ Word32 snrRed;
+ Word16 newMinSnr;
+
+ dbRatio = log_avgEn - logSfbEnergy[ch][sfbOffs+sfb];
+ dbRatio = dbRatio + (dbRatio << 1);
+
+ minSnrRed = 110 - ((dbRatio + (dbRatio << 1)) >> 2);
+ minSnrRed = max(minSnrRed, 20); /* 110: (0.375(redOffs)+1)*80,
+ 3: 0.00375(redRatioFac)*80
+ 20: 0.25(maxRed) * 80 */
+
+ snrRed = minSnrRed * iLog4((psyOutChan->sfbMinSnr[sfbOffs+sfb] << 16));
+ /*
+ snrRedI si now scaled by 80 (minSnrRed) and 4 (ffr_iLog4)
+ */
+
+ newMinSnr = round16(pow2_xy(snrRed,80*4));
+
+ psyOutChan->sfbMinSnr[sfbOffs+sfb] = min(newMinSnr, minSnrLimit);
+ }
+ }
+ }
+ }
+
+}
+
+
+/********************************************************************************
+*
+* function name:initAvoidHoleFlag
+* description: determine bands where avoid hole is not necessary resp. possible
+*
+**********************************************************************************/
+static void initAvoidHoleFlag(Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT* psyOutElement,
+ const Word16 nChannels,
+ AH_PARAM *ahParam)
+{
+ Word16 ch, sfb, sfbGrp, shift;
+ Word32 threshold;
+ Word32* psfbSpreadEn;
+
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+
+ if (psyOutChan->windowSequence != SHORT_WINDOW) {
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ *psfbSpreadEn = *psfbSpreadEn >> 1; /* 0.5 */
+ ++psfbSpreadEn;
+ }
+ }
+ }
+ else {
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ psfbSpreadEn = psyOutChan->sfbSpreadedEnergy + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ *psfbSpreadEn = (*psfbSpreadEn >> 1) + (*psfbSpreadEn >> 3); /* 0.63 */
+ ++psfbSpreadEn;
+ }
+ }
+ }
+ }
+
+ /* increase minSnr for local peaks, decrease it for valleys */
+ if (ahParam->modifyMinSnr) {
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+
+ if (psyOutChan->windowSequence != SHORT_WINDOW)
+ threshold = HOLE_THR_LONG;
+ else
+ threshold = HOLE_THR_SHORT;
+
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ Word16 *psfbMinSnr = psyOutChan->sfbMinSnr + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ Word32 sfbEn, sfbEnm1, sfbEnp1, avgEn;
+
+ if (sfb > 0)
+ sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp+sfb-1];
+ else
+ sfbEnm1 = psyOutChan->sfbEnergy[sfbGrp];
+
+ if (sfb < (psyOutChan->maxSfbPerGroup-1))
+ sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb+1];
+ else
+ sfbEnp1 = psyOutChan->sfbEnergy[sfbGrp+sfb];
+ avgEn = (sfbEnm1 + sfbEnp1) >> 1;
+ sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb];
+
+ if (sfbEn > avgEn && avgEn > 0) {
+ Word32 tmpMinSnr;
+ shift = norm_l(sfbEn);
+ tmpMinSnr = Div_32(L_mpy_ls(avgEn, minSnrLimit) << shift, sfbEn << shift );
+ tmpMinSnr = max(tmpMinSnr, HOLE_THR_LONG);
+ tmpMinSnr = max(tmpMinSnr, threshold);
+ *psfbMinSnr = min(*psfbMinSnr, tmpMinSnr);
+ }
+ /* valley ? */
+
+ if ((sfbEn < (avgEn >> 1)) && (sfbEn > 0)) {
+ Word32 tmpMinSnr;
+ Word32 minSnrEn = L_mpy_wx(avgEn, *psfbMinSnr);
+
+ if(minSnrEn < sfbEn) {
+ shift = norm_l(sfbEn);
+ tmpMinSnr = Div_32( minSnrEn << shift, sfbEn<<shift);
+ }
+ else {
+ tmpMinSnr = MAX_16;
+ }
+ tmpMinSnr = min(minSnrLimit, tmpMinSnr);
+
+ *psfbMinSnr =
+ (min((tmpMinSnr >> 2), mult(*psfbMinSnr, MIN_SNR_COEF)) << 2);
+ }
+ psfbMinSnr++;
+ }
+ }
+ }
+ }
+
+ /* stereo: adapt the minimum requirements sfbMinSnr of mid and
+ side channels */
+
+ if (nChannels == 2) {
+ PSY_OUT_CHANNEL *psyOutChanM = &psyOutChannel[0];
+ PSY_OUT_CHANNEL *psyOutChanS = &psyOutChannel[1];
+ for (sfb=0; sfb<psyOutChanM->sfbCnt; sfb++) {
+ if (psyOutElement->toolsInfo.msMask[sfb]) {
+ Word32 sfbEnM = psyOutChanM->sfbEnergy[sfb];
+ Word32 sfbEnS = psyOutChanS->sfbEnergy[sfb];
+ Word32 maxSfbEn = max(sfbEnM, sfbEnS);
+ Word32 maxThr = L_mpy_wx(maxSfbEn, psyOutChanM->sfbMinSnr[sfb]) >> 1;
+
+ if(maxThr >= sfbEnM) {
+ psyOutChanM->sfbMinSnr[sfb] = MAX_16;
+ }
+ else {
+ shift = norm_l(sfbEnM);
+ psyOutChanM->sfbMinSnr[sfb] = min(max(psyOutChanM->sfbMinSnr[sfb],
+ round16(Div_32(maxThr<<shift, sfbEnM << shift))), minSnrLimit);
+ }
+
+ if(maxThr >= sfbEnS) {
+ psyOutChanS->sfbMinSnr[sfb] = MAX_16;
+ }
+ else {
+ shift = norm_l(sfbEnS);
+ psyOutChanS->sfbMinSnr[sfb] = min(max(psyOutChanS->sfbMinSnr[sfb],
+ round16(Div_32(maxThr << shift, sfbEnS << shift))), minSnrLimit);
+ }
+
+
+ if (sfbEnM > psyOutChanM->sfbSpreadedEnergy[sfb])
+ psyOutChanS->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnS, MS_THRSPREAD_COEF);
+
+ if (sfbEnS > psyOutChanS->sfbSpreadedEnergy[sfb])
+ psyOutChanM->sfbSpreadedEnergy[sfb] = L_mpy_ls(sfbEnM, MS_THRSPREAD_COEF);
+ }
+ }
+ }
+
+
+ /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ Word16 *pahFlag = ahFlag[ch] + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ if ((psyOutChan->sfbSpreadedEnergy[sfbGrp+sfb] > psyOutChan->sfbEnergy[sfbGrp+sfb]) ||
+ (psyOutChan->sfbEnergy[sfbGrp+sfb] <= psyOutChan->sfbThreshold[sfbGrp+sfb]) ||
+ (psyOutChan->sfbMinSnr[sfbGrp+sfb] == MAX_16)) {
+ *pahFlag++ = NO_AH;
+ }
+ else {
+ *pahFlag++ = AH_INACTIVE;
+ }
+ }
+ for (sfb=psyOutChan->maxSfbPerGroup; sfb<psyOutChan->sfbPerGroup; sfb++) {
+ *pahFlag++ = NO_AH;
+ }
+ }
+ }
+}
+
+/********************************************************************************
+*
+* function name:calcPeNoAH
+* description: sum the pe data only for bands where avoid hole is inactive
+*
+**********************************************************************************/
+static void calcPeNoAH(Word16 *pe,
+ Word16 *constPart,
+ Word16 *nActiveLines,
+ PE_DATA *peData,
+ Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const Word16 nChannels)
+{
+ Word16 ch, sfb, sfbGrp;
+ int ipe, iconstPart, inActiveLines;
+
+ ipe = 0;
+ iconstPart = 0;
+ inActiveLines = 0;
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ if (ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) {
+ ipe = ipe + peChanData->sfbPe[sfbGrp+sfb];
+ iconstPart = iconstPart + peChanData->sfbConstPart[sfbGrp+sfb];
+ inActiveLines = inActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
+ }
+ }
+ }
+ }
+
+ *pe = saturate(ipe);
+ *constPart = saturate(iconstPart);
+ *nActiveLines = saturate(inActiveLines);
+}
+
+/********************************************************************************
+*
+* function name:reduceThresholds
+* description: apply reduction formula
+*
+**********************************************************************************/
+static void reduceThresholds(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word16 nChannels,
+ const Word32 redVal)
+{
+ Word32 sfbThrReduced;
+ Word32 *psfbEn, *psfbThr;
+ Word16 ch, sfb, sfbGrp;
+
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
+ psfbEn = psyOutChan->sfbEnergy + sfbGrp;
+ psfbThr = psyOutChan->sfbThreshold + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+
+ if (*psfbEn > *psfbThr) {
+ /* threshold reduction formula */
+ Word32 tmp = thrExp[ch][sfbGrp+sfb] + redVal;
+ tmp = fixmul(tmp, tmp);
+ sfbThrReduced = fixmul(tmp, tmp);
+ /* avoid holes */
+ tmp = L_mpy_ls(*psfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
+
+ if ((sfbThrReduced > tmp) &&
+ (ahFlag[ch][sfbGrp+sfb] != NO_AH)){
+ sfbThrReduced = max(tmp, *psfbThr);
+ ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE;
+ }
+ *psfbThr = sfbThrReduced;
+ }
+
+ psfbEn++; psfbThr++;
+ }
+ }
+ }
+}
+
+
+/********************************************************************************
+*
+* function name:correctThresh
+* description: if pe difference deltaPe between desired pe and real pe is small enough,
+* the difference can be distributed among the scale factor bands.
+*
+**********************************************************************************/
+static void correctThresh(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PE_DATA *peData,
+ Word32 thrExp[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word32 redVal,
+ const Word16 nChannels,
+ const Word32 deltaPe)
+{
+ Word16 ch, sfb, sfbGrp,shift;
+ PSY_OUT_CHANNEL *psyOutChan;
+ PE_CHANNEL_DATA *peChanData;
+ Word32 deltaSfbPe;
+ Word32 normFactor;
+ Word32 *psfbPeFactors;
+ Word16 *psfbNActiveLines, *pahFlag;
+ Word32 sfbEn, sfbThr;
+ Word32 sfbThrReduced;
+
+ /* for each sfb calc relative factors for pe changes */
+ normFactor = 1;
+ for(ch=0; ch<nChannels; ch++) {
+ psyOutChan = &psyOutChannel[ch];
+ peChanData = &peData->peChannelData[ch];
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;
+ psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;
+ pahFlag = ahFlag[ch] + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal;
+
+ if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) ) {
+
+ *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp);
+ normFactor = L_add(normFactor, *psfbPeFactors);
+ }
+ else {
+ *psfbPeFactors = 0;
+ }
+ psfbPeFactors++;
+ pahFlag++; psfbNActiveLines++;
+ }
+ }
+ }
+
+
+ /* calculate new thresholds */
+ for(ch=0; ch<nChannels; ch++) {
+ psyOutChan = &psyOutChannel[ch];
+ peChanData = &peData->peChannelData[ch];
+ for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
+ psfbPeFactors = peData->sfbPeFactors[ch] + sfbGrp;
+ psfbNActiveLines = peChanData->sfbNActiveLines + sfbGrp;
+ pahFlag = ahFlag[ch] + sfbGrp;
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ /* pe difference for this sfb */
+ deltaSfbPe = *psfbPeFactors * deltaPe;
+
+ /* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */
+ if (*psfbNActiveLines > 0) {
+ /* new threshold */
+ Word32 thrFactor;
+ sfbEn = psyOutChan->sfbEnergy[sfbGrp+sfb];
+ sfbThr = psyOutChan->sfbThreshold[sfbGrp+sfb];
+
+ if(deltaSfbPe >= 0){
+ /*
+ reduce threshold
+ */
+ thrFactor = pow2_xy(L_negate(deltaSfbPe), (normFactor* (*psfbNActiveLines)));
+
+ sfbThrReduced = L_mpy_ls(sfbThr, round16(thrFactor));
+ }
+ else {
+ /*
+ increase threshold
+ */
+ thrFactor = pow2_xy(deltaSfbPe, (normFactor * (*psfbNActiveLines)));
+
+
+ if(thrFactor > sfbThr) {
+ shift = norm_l(thrFactor);
+ sfbThrReduced = Div_32( sfbThr << shift, thrFactor<<shift );
+ }
+ else {
+ sfbThrReduced = MAX_32;
+ }
+
+ }
+
+ /* avoid hole */
+ sfbEn = L_mpy_ls(sfbEn, psyOutChan->sfbMinSnr[sfbGrp+sfb]);
+
+ if ((sfbThrReduced > sfbEn) &&
+ (*pahFlag == AH_INACTIVE)) {
+ sfbThrReduced = max(sfbEn, sfbThr);
+ *pahFlag = AH_ACTIVE;
+ }
+
+ psyOutChan->sfbThreshold[sfbGrp+sfb] = sfbThrReduced;
+ }
+
+ pahFlag++; psfbNActiveLines++; psfbPeFactors++;
+ }
+ }
+ }
+}
+
+
+/********************************************************************************
+*
+* function name:reduceMinSnr
+* description: if the desired pe can not be reached, reduce pe by reducing minSnr
+*
+**********************************************************************************/
+static void reduceMinSnr(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PE_DATA *peData,
+ Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word16 nChannels,
+ const Word16 desiredPe)
+{
+ Word16 ch, sfb, sfbSubWin;
+ Word16 deltaPe;
+
+ /* start at highest freq down to 0 */
+ sfbSubWin = psyOutChannel[0].maxSfbPerGroup;
+ while (peData->pe > desiredPe && sfbSubWin > 0) {
+
+ sfbSubWin = sfbSubWin - 1;
+ /* loop over all subwindows */
+ for (sfb=sfbSubWin; sfb<psyOutChannel[0].sfbCnt;
+ sfb+=psyOutChannel[0].sfbPerGroup) {
+ /* loop over all channels */
+ PE_CHANNEL_DATA* peChan = peData->peChannelData;
+ PSY_OUT_CHANNEL* psyOutCh = psyOutChannel;
+ for (ch=0; ch<nChannels; ch++) {
+ if (ahFlag[ch][sfb] != NO_AH &&
+ psyOutCh->sfbMinSnr[sfb] < minSnrLimit) {
+ psyOutCh->sfbMinSnr[sfb] = minSnrLimit;
+ psyOutCh->sfbThreshold[sfb] =
+ L_mpy_ls(psyOutCh->sfbEnergy[sfb], psyOutCh->sfbMinSnr[sfb]);
+
+ /* calc new pe */
+ deltaPe = ((peChan->sfbNLines4[sfb] + (peChan->sfbNLines4[sfb] >> 1)) >> 2) -
+ peChan->sfbPe[sfb];
+ peData->pe = peData->pe + deltaPe;
+ peChan->pe = peChan->pe + deltaPe;
+ }
+ peChan += 1; psyOutCh += 1;
+ }
+ /* stop if enough has been saved */
+
+ if (peData->pe <= desiredPe)
+ break;
+ }
+ }
+}
+
+/********************************************************************************
+*
+* function name:allowMoreHoles
+* description: if the desired pe can not be reached, some more scalefactor bands
+* have to be quantized to zero
+*
+**********************************************************************************/
+static void allowMoreHoles(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ PE_DATA *peData,
+ Word16 ahFlag[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const AH_PARAM *ahParam,
+ const Word16 nChannels,
+ const Word16 desiredPe)
+{
+ Word16 ch, sfb;
+ Word16 actPe, shift;
+
+ actPe = peData->pe;
+
+ /* for MS allow hole in the channel with less energy */
+
+ if (nChannels==2 &&
+ psyOutChannel[0].windowSequence==psyOutChannel[1].windowSequence) {
+ PSY_OUT_CHANNEL *psyOutChanL = &psyOutChannel[0];
+ PSY_OUT_CHANNEL *psyOutChanR = &psyOutChannel[1];
+ for (sfb=0; sfb<psyOutChanL->sfbCnt; sfb++) {
+ Word32 minEn;
+
+ if (psyOutElement->toolsInfo.msMask[sfb]) {
+ /* allow hole in side channel ? */
+ minEn = L_mpy_ls(psyOutChanL->sfbEnergy[sfb], (minSnrLimit * psyOutChanL->sfbMinSnr[sfb]) >> 16);
+
+ if (ahFlag[1][sfb] != NO_AH &&
+ minEn > psyOutChanR->sfbEnergy[sfb]) {
+ ahFlag[1][sfb] = NO_AH;
+ psyOutChanR->sfbThreshold[sfb] = L_add(psyOutChanR->sfbEnergy[sfb], psyOutChanR->sfbEnergy[sfb]);
+ actPe = actPe - peData->peChannelData[1].sfbPe[sfb];
+ }
+ /* allow hole in mid channel ? */
+ else {
+ minEn = L_mpy_ls(psyOutChanR->sfbEnergy[sfb], (minSnrLimit * psyOutChanR->sfbMinSnr[sfb]) >> 16);
+
+ if (ahFlag[0][sfb]!= NO_AH &&
+ minEn > psyOutChanL->sfbEnergy[sfb]) {
+ ahFlag[0][sfb] = NO_AH;
+ psyOutChanL->sfbThreshold[sfb] = L_add(psyOutChanL->sfbEnergy[sfb], psyOutChanL->sfbEnergy[sfb]);
+ actPe = actPe - peData->peChannelData[0].sfbPe[sfb];
+ }
+ }
+
+ if (actPe < desiredPe)
+ break;
+ }
+ }
+ }
+
+ /* subsequently erase bands */
+ if (actPe > desiredPe) {
+ Word16 startSfb[2];
+ Word32 avgEn, minEn;
+ Word16 ahCnt;
+ Word16 enIdx;
+ Word16 enDiff;
+ Word32 en[4];
+ Word16 minSfb, maxSfb;
+ Flag done;
+
+ /* do not go below startSfb */
+ for (ch=0; ch<nChannels; ch++) {
+
+ if (psyOutChannel[ch].windowSequence != SHORT_WINDOW)
+ startSfb[ch] = ahParam->startSfbL;
+ else
+ startSfb[ch] = ahParam->startSfbS;
+ }
+
+ avgEn = 0;
+ minEn = MAX_32;
+ ahCnt = 0;
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ for (sfb=startSfb[ch]; sfb<psyOutChan->sfbCnt; sfb++) {
+
+ if ((ahFlag[ch][sfb] != NO_AH) &&
+ (psyOutChan->sfbEnergy[sfb] > psyOutChan->sfbThreshold[sfb])) {
+ minEn = min(minEn, psyOutChan->sfbEnergy[sfb]);
+ avgEn = L_add(avgEn, psyOutChan->sfbEnergy[sfb]);
+ ahCnt++;
+ }
+ }
+ }
+
+ if(ahCnt) {
+ Word32 iahCnt;
+ shift = norm_l(ahCnt);
+ iahCnt = Div_32( 1 << shift, ahCnt << shift );
+ avgEn = fixmul(avgEn, iahCnt);
+ }
+
+ enDiff = iLog4(avgEn) - iLog4(minEn);
+ /* calc some energy borders between minEn and avgEn */
+ for (enIdx=0; enIdx<4; enIdx++) {
+ Word32 enFac;
+ enFac = ((6-(enIdx << 1)) * enDiff);
+ en[enIdx] = fixmul(avgEn, pow2_xy(L_negate(enFac),7*4));
+ }
+
+ /* start with lowest energy border at highest sfb */
+ maxSfb = psyOutChannel[0].sfbCnt - 1;
+ minSfb = startSfb[0];
+
+ if (nChannels == 2) {
+ maxSfb = max(maxSfb, (psyOutChannel[1].sfbCnt - 1));
+ minSfb = min(minSfb, startSfb[1]);
+ }
+
+ sfb = maxSfb;
+ enIdx = 0;
+ done = 0;
+ while (!done) {
+
+ for (ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+
+ if (sfb>=startSfb[ch] && sfb<psyOutChan->sfbCnt) {
+ /* sfb energy below border ? */
+
+ if (ahFlag[ch][sfb] != NO_AH && psyOutChan->sfbEnergy[sfb] < en[enIdx]){
+ /* allow hole */
+ ahFlag[ch][sfb] = NO_AH;
+ psyOutChan->sfbThreshold[sfb] = L_add(psyOutChan->sfbEnergy[sfb], psyOutChan->sfbEnergy[sfb]);
+ actPe = actPe - peData->peChannelData[ch].sfbPe[sfb];
+ }
+
+ if (actPe < desiredPe) {
+ done = 1;
+ break;
+ }
+ }
+ }
+ sfb = sfb - 1;
+
+ if (sfb < minSfb) {
+ /* restart with next energy border */
+ sfb = maxSfb;
+ enIdx = enIdx + 1;
+
+ if (enIdx - 4 >= 0)
+ done = 1;
+ }
+ }
+ }
+}
+
+/********************************************************************************
+*
+* function name:adaptThresholdsToPe
+* description: two guesses for the reduction value and one final correction of the
+* thresholds
+*
+**********************************************************************************/
+static void adaptThresholdsToPe(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PE_DATA *peData,
+ const Word16 nChannels,
+ const Word16 desiredPe,
+ AH_PARAM *ahParam,
+ MINSNR_ADAPT_PARAM *msaParam)
+{
+ Word16 noRedPe, redPe, redPeNoAH;
+ Word16 constPart, constPartNoAH;
+ Word16 nActiveLines, nActiveLinesNoAH;
+ Word16 desiredPeNoAH;
+ Word32 redVal, avgThrExp;
+ Word32 iter;
+
+ calcThreshExp(peData->thrExp, psyOutChannel, nChannels);
+
+ adaptMinSnr(psyOutChannel, logSfbEnergy, msaParam, nChannels);
+
+ initAvoidHoleFlag(peData->ahFlag, psyOutChannel, psyOutElement, nChannels, ahParam);
+
+ noRedPe = peData->pe;
+ constPart = peData->constPart;
+ nActiveLines = peData->nActiveLines;
+
+ /* first guess of reduction value t^0.25 = 2^((a-pen)/4*b) */
+ avgThrExp = pow2_xy((constPart - noRedPe), (nActiveLines << 2));
+
+ /* r1 = 2^((a-per)/4*b) - t^0.25 */
+ redVal = pow2_xy((constPart - desiredPe), (nActiveLines << 2)) - avgThrExp;
+
+ /* reduce thresholds */
+ reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
+
+ /* pe after first guess */
+ calcSfbPe(peData, psyOutChannel, nChannels);
+ redPe = peData->pe;
+
+ iter = 0;
+ do {
+ /* pe for bands where avoid hole is inactive */
+ calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH,
+ peData, peData->ahFlag, psyOutChannel, nChannels);
+
+ desiredPeNoAH = desiredPe -(redPe - redPeNoAH);
+
+ if (desiredPeNoAH < 0) {
+ desiredPeNoAH = 0;
+ }
+
+ /* second guess */
+
+ if (nActiveLinesNoAH > 0) {
+
+ avgThrExp = pow2_xy((constPartNoAH - redPeNoAH), (nActiveLinesNoAH << 2));
+
+ redVal = (redVal + pow2_xy((constPartNoAH - desiredPeNoAH), (nActiveLinesNoAH << 2))) - avgThrExp;
+
+ /* reduce thresholds */
+ reduceThresholds(psyOutChannel, peData->ahFlag, peData->thrExp, nChannels, redVal);
+ }
+
+ calcSfbPe(peData, psyOutChannel, nChannels);
+ redPe = peData->pe;
+
+ iter = iter+1;
+
+ } while ((20 * abs_s(redPe - desiredPe) > desiredPe) && (iter < 2));
+
+
+ if ((100 * redPe < 115 * desiredPe)) {
+ correctThresh(psyOutChannel, peData->ahFlag, peData, peData->thrExp, redVal,
+ nChannels, desiredPe - redPe);
+ }
+ else {
+ Word16 desiredPe105 = (105 * desiredPe) / 100;
+ reduceMinSnr(psyOutChannel, peData, peData->ahFlag,
+ nChannels, desiredPe105);
+ allowMoreHoles(psyOutChannel, psyOutElement, peData, peData->ahFlag,
+ ahParam, nChannels, desiredPe105);
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: calcBitSave
+* description: Calculates percentage of bit save, see figure below
+* returns:
+* input: parameters and bitres-fullness
+* output: percentage of bit save
+*
+*****************************************************************************/
+static Word16 calcBitSave(Word16 fillLevel,
+ const Word16 clipLow,
+ const Word16 clipHigh,
+ const Word16 minBitSave,
+ const Word16 maxBitSave)
+{
+ Word16 bitsave = 0;
+
+ fillLevel = max(fillLevel, clipLow);
+ fillLevel = min(fillLevel, clipHigh);
+
+ if(clipHigh-clipLow)
+ bitsave = (maxBitSave - (((maxBitSave-minBitSave)*(fillLevel-clipLow))/
+ (clipHigh-clipLow)));
+
+ return (bitsave);
+}
+
+
+
+/*****************************************************************************
+*
+* function name: calcBitSpend
+* description: Calculates percentage of bit spend, see figure below
+* returns:
+* input: parameters and bitres-fullness
+* output: percentage of bit spend
+*
+*****************************************************************************/
+static Word16 calcBitSpend(Word16 fillLevel,
+ const Word16 clipLow,
+ const Word16 clipHigh,
+ const Word16 minBitSpend,
+ const Word16 maxBitSpend)
+{
+ Word16 bitspend = 1;
+
+ fillLevel = max(fillLevel, clipLow);
+ fillLevel = min(fillLevel, clipHigh);
+
+ if(clipHigh-clipLow)
+ bitspend = (minBitSpend + ((maxBitSpend - minBitSpend)*(fillLevel - clipLow) /
+ (clipHigh-clipLow)));
+
+ return (bitspend);
+}
+
+
+/*****************************************************************************
+*
+* function name: adjustPeMinMax()
+* description: adjusts peMin and peMax parameters over time
+* returns:
+* input: current pe, peMin, peMax
+* output: adjusted peMin/peMax
+*
+*****************************************************************************/
+static void adjustPeMinMax(const Word16 currPe,
+ Word16 *peMin,
+ Word16 *peMax)
+{
+ Word16 minFacHi, maxFacHi, minFacLo, maxFacLo;
+ Word16 diff;
+ Word16 minDiff = extract_l(currPe / 6);
+ minFacHi = 30;
+ maxFacHi = 100;
+ minFacLo = 14;
+ maxFacLo = 7;
+
+ diff = currPe - *peMax ;
+
+ if (diff > 0) {
+ *peMin = *peMin + ((diff * minFacHi) / 100);
+ *peMax = *peMax + ((diff * maxFacHi) / 100);
+ } else {
+ diff = *peMin - currPe;
+
+ if (diff > 0) {
+ *peMin = *peMin - ((diff * minFacLo) / 100);
+ *peMax = *peMax - ((diff * maxFacLo) / 100);
+ } else {
+ *peMin = *peMin + ((currPe - *peMin) * minFacHi / 100);
+ *peMax = *peMax - ((*peMax - currPe) * maxFacLo / 100);
+ }
+ }
+
+
+ if ((*peMax - *peMin) < minDiff) {
+ Word16 partLo, partHi;
+
+ partLo = max(0, (currPe - *peMin));
+ partHi = max(0, (*peMax - currPe));
+
+ *peMax = currPe + ((partHi * minDiff) / (partLo + partHi));
+ *peMin = currPe - ((partLo * minDiff) / (partLo + partHi));
+ *peMin = max(0, *peMin);
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: BitresCalcBitFac
+* description: calculates factor of spending bits for one frame
+* 1.0 : take all frame dynpart bits
+* >1.0 : take all frame dynpart bits + bitres
+* <1.0 : put bits in bitreservoir
+* returns: BitFac*100
+* input: bitres-fullness, pe, blockType, parameter-settings
+* output:
+*
+*****************************************************************************/
+static Word16 bitresCalcBitFac( const Word16 bitresBits,
+ const Word16 maxBitresBits,
+ const Word16 pe,
+ const Word16 windowSequence,
+ const Word16 avgBits,
+ const Word16 maxBitFac,
+ ADJ_THR_STATE *AdjThr,
+ ATS_ELEMENT *adjThrChan)
+{
+ BRES_PARAM *bresParam;
+ Word16 pex;
+ Word16 fillLevel;
+ Word16 bitSave, bitSpend, bitresFac;
+
+ fillLevel = extract_l((100* bitresBits) / maxBitresBits);
+
+ if (windowSequence != SHORT_WINDOW)
+ bresParam = &(AdjThr->bresParamLong);
+ else
+ bresParam = &(AdjThr->bresParamShort);
+
+ pex = max(pe, adjThrChan->peMin);
+ pex = min(pex,adjThrChan->peMax);
+
+ bitSave = calcBitSave(fillLevel,
+ bresParam->clipSaveLow, bresParam->clipSaveHigh,
+ bresParam->minBitSave, bresParam->maxBitSave);
+
+ bitSpend = calcBitSpend(fillLevel,
+ bresParam->clipSpendLow, bresParam->clipSpendHigh,
+ bresParam->minBitSpend, bresParam->maxBitSpend);
+
+ if(adjThrChan->peMax != adjThrChan->peMin)
+ bitresFac = (100 - bitSave) + extract_l(((bitSpend + bitSave) * (pex - adjThrChan->peMin)) /
+ (adjThrChan->peMax - adjThrChan->peMin));
+ else
+ bitresFac = 0x7fff;
+
+ bitresFac = min(bitresFac,
+ (100-30 + extract_l((100 * bitresBits) / avgBits)));
+
+ bitresFac = min(bitresFac, maxBitFac);
+
+ adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
+
+ return bitresFac;
+}
+
+/*****************************************************************************
+*
+* function name: AdjThrInit
+* description: init thresholds parameter
+*
+*****************************************************************************/
+void AdjThrInit(ADJ_THR_STATE *hAdjThr,
+ const Word32 meanPe,
+ Word32 chBitrate)
+{
+ ATS_ELEMENT* atsElem = &hAdjThr->adjThrStateElem;
+ MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
+
+ /* common for all elements: */
+ /* parameters for bitres control */
+ hAdjThr->bresParamLong.clipSaveLow = 20;
+ hAdjThr->bresParamLong.clipSaveHigh = 95;
+ hAdjThr->bresParamLong.minBitSave = -5;
+ hAdjThr->bresParamLong.maxBitSave = 30;
+ hAdjThr->bresParamLong.clipSpendLow = 20;
+ hAdjThr->bresParamLong.clipSpendHigh = 95;
+ hAdjThr->bresParamLong.minBitSpend = -10;
+ hAdjThr->bresParamLong.maxBitSpend = 40;
+
+ hAdjThr->bresParamShort.clipSaveLow = 20;
+ hAdjThr->bresParamShort.clipSaveHigh = 75;
+ hAdjThr->bresParamShort.minBitSave = 0;
+ hAdjThr->bresParamShort.maxBitSave = 20;
+ hAdjThr->bresParamShort.clipSpendLow = 20;
+ hAdjThr->bresParamShort.clipSpendHigh = 75;
+ hAdjThr->bresParamShort.minBitSpend = -5;
+ hAdjThr->bresParamShort.maxBitSpend = 50;
+
+ /* specific for each element: */
+
+ /* parameters for bitres control */
+ atsElem->peMin = extract_l(((80*meanPe) / 100));
+ atsElem->peMax = extract_l(((120*meanPe) / 100));
+
+ /* additional pe offset to correct pe2bits for low bitrates */
+ atsElem->peOffset = 0;
+ if (chBitrate < 32000) {
+ atsElem->peOffset = max(50, (100 - extract_l((100 * chBitrate) / 32000)));
+ }
+
+ /* avoid hole parameters */
+ if (chBitrate > 20000) {
+ atsElem->ahParam.modifyMinSnr = TRUE;
+ atsElem->ahParam.startSfbL = 15;
+ atsElem->ahParam.startSfbS = 3;
+ }
+ else {
+ atsElem->ahParam.modifyMinSnr = FALSE;
+ atsElem->ahParam.startSfbL = 0;
+ atsElem->ahParam.startSfbS = 0;
+ }
+
+ /* minSnr adaptation */
+ /* maximum reduction of minSnr goes down to minSnr^maxRed */
+ msaParam->maxRed = 0x20000000; /* *0.25f /
+ /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
+ msaParam->startRatio = 0x0ccccccd; /* 10 */
+ /* maximum minSnr reduction to minSnr^maxRed is reached for
+ avgEn/sfbEn >= maxRatio */
+ msaParam->maxRatio = 0x0020c49c; /* 1000 */
+ /* helper variables to interpolate minSnr reduction for
+ avgEn/sfbEn between startRatio and maxRatio */
+
+ msaParam->redRatioFac = 0xfb333333; /* -0.75/20 */
+
+ msaParam->redOffs = 0x30000000; /* msaParam->redRatioFac * 10*log10(msaParam->startRatio) */
+
+
+ /* pe correction */
+ atsElem->peLast = 0;
+ atsElem->dynBitsLast = 0;
+ atsElem->peCorrectionFactor = 100; /* 1.0 */
+
+}
+
+/*****************************************************************************
+*
+* function name: calcPeCorrection
+* description: calculates the desired perceptual entropy factor
+* It is between 0.85 and 1.15
+*
+*****************************************************************************/
+static void calcPeCorrection(Word16 *correctionFac,
+ const Word16 peAct,
+ const Word16 peLast,
+ const Word16 bitsLast)
+{
+ Word32 peAct100 = 100 * peAct;
+ Word32 peLast100 = 100 * peLast;
+ Word16 peBitsLast = bits2pe(bitsLast);
+
+ if ((bitsLast > 0) &&
+ (peAct100 < (150 * peLast)) && (peAct100 > (70 * peLast)) &&
+ ((120 * peBitsLast) > peLast100 ) && (( 65 * peBitsLast) < peLast100))
+ {
+ Word16 newFac = (100 * peLast) / peBitsLast;
+ /* dead zone */
+
+ if (newFac < 100) {
+ newFac = min(((110 * newFac) / 100), 100);
+ newFac = max(newFac, 85);
+ }
+ else {
+ newFac = max(((90 * newFac) / 100), 100);
+ newFac = min(newFac, 115);
+ }
+
+ if ((newFac > 100 && *correctionFac < 100) ||
+ (newFac < 100 && *correctionFac > 100)) {
+ *correctionFac = 100;
+ }
+ /* faster adaptation towards 1.0, slower in the other direction */
+
+ if ((*correctionFac < 100 && newFac < *correctionFac) ||
+ (*correctionFac > 100 && newFac > *correctionFac))
+ *correctionFac = (85 * *correctionFac + 15 * newFac) / 100;
+ else
+ *correctionFac = (70 * *correctionFac + 30 * newFac) / 100;
+ *correctionFac = min(*correctionFac, 115);
+ *correctionFac = max(*correctionFac, 85);
+ }
+ else {
+ *correctionFac = 100;
+ }
+}
+
+/********************************************************************************
+*
+* function name: AdjustThresholds
+* description: Adjust thresholds to the desired bitrate
+*
+**********************************************************************************/
+void AdjustThresholds(ADJ_THR_STATE *adjThrState,
+ ATS_ELEMENT *AdjThrStateElement,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word16 *chBitDistribution,
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ QC_OUT_ELEMENT *qcOE,
+ ELEMENT_BITS *elBits,
+ const Word16 nChannels,
+ const Word16 maxBitFac)
+{
+ PE_DATA peData;
+ Word16 noRedPe, grantedPe, grantedPeCorr;
+ Word16 curWindowSequence;
+ Word16 bitFactor;
+ Word16 avgBits = (elBits->averageBits - (qcOE->staticBitsUsed + qcOE->ancBitsUsed));
+ Word16 bitresBits = elBits->bitResLevel;
+ Word16 maxBitresBits = elBits->maxBits;
+ Word16 sideInfoBits = (qcOE->staticBitsUsed + qcOE->ancBitsUsed);
+ Word16 ch;
+
+ prepareSfbPe(&peData, psyOutChannel, logSfbEnergy, sfbNRelevantLines, nChannels, AdjThrStateElement->peOffset);
+
+ /* pe without reduction */
+ calcSfbPe(&peData, psyOutChannel, nChannels);
+ noRedPe = peData.pe;
+
+
+ curWindowSequence = LONG_WINDOW;
+
+ if (nChannels == 2) {
+
+ if ((psyOutChannel[0].windowSequence == SHORT_WINDOW) ||
+ (psyOutChannel[1].windowSequence == SHORT_WINDOW)) {
+ curWindowSequence = SHORT_WINDOW;
+ }
+ }
+ else {
+ curWindowSequence = psyOutChannel[0].windowSequence;
+ }
+
+
+ /* bit factor */
+ bitFactor = bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe+5*sideInfoBits,
+ curWindowSequence, avgBits, maxBitFac,
+ adjThrState,
+ AdjThrStateElement);
+
+ /* desired pe */
+ grantedPe = ((bitFactor * bits2pe(avgBits)) / 100);
+
+ /* correction of pe value */
+ calcPeCorrection(&(AdjThrStateElement->peCorrectionFactor),
+ min(grantedPe, noRedPe),
+ AdjThrStateElement->peLast,
+ AdjThrStateElement->dynBitsLast);
+ grantedPeCorr = (grantedPe * AdjThrStateElement->peCorrectionFactor) / 100;
+
+
+ if (grantedPeCorr < noRedPe && noRedPe > peData.offset) {
+ /* calc threshold necessary for desired pe */
+ adaptThresholdsToPe(psyOutChannel,
+ psyOutElement,
+ logSfbEnergy,
+ &peData,
+ nChannels,
+ grantedPeCorr,
+ &AdjThrStateElement->ahParam,
+ &AdjThrStateElement->minSnrAdaptParam);
+ }
+
+ /* calculate relative distribution */
+ for (ch=0; ch<nChannels; ch++) {
+ Word16 peOffsDiff = peData.pe - peData.offset;
+ chBitDistribution[ch] = 200;
+
+ if (peOffsDiff > 0) {
+ Word32 temp = 1000 - (nChannels * 200);
+ chBitDistribution[ch] = chBitDistribution[ch] +
+ (temp * peData.peChannelData[ch].pe) / peOffsDiff;
+ }
+ }
+
+ /* store pe */
+ qcOE->pe = noRedPe;
+
+ /* update last pe */
+ AdjThrStateElement->peLast = grantedPe;
+}
+
+/********************************************************************************
+*
+* function name: AdjThrUpdate
+* description: save dynBitsUsed for correction of bits2pe relation
+*
+**********************************************************************************/
+void AdjThrUpdate(ATS_ELEMENT *AdjThrStateElement,
+ const Word16 dynBitsUsed)
+{
+ AdjThrStateElement->dynBitsLast = dynBitsUsed;
+}
+
+
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s
new file mode 100644
index 0000000..48edd4f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/AutoCorrelation_v5.s
@@ -0,0 +1,167 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: AutoCorrelation_v5.s
+@
+@ Content: AutoCorrelation function armv5 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+
+ .section .text
+ .global AutoCorrelation
+
+AutoCorrelation:
+ stmdb sp!, {r4 - r11, lr}
+
+ sub r13, r13, #20
+
+ mov r5, r0
+ mov r7, r1
+ mov r9, r3
+ mov r2, r2, lsl #16
+ mov r0, #0
+ mov r4, r2, asr #16
+ mov r8, #0
+ cmp r4, #0
+ ble L136
+
+ cmp r4, #8
+ mov r2, #0
+ blt L133
+
+ sub r12, r4, #8
+L132:
+ ldr r6, [r5, r2]
+ add r2, r2, #4
+ smulbb r3, r6, r6
+ ldr r1, [r5, r2]
+ smultt r10, r6, r6
+ mov r3, r3, asr #9
+ smulbb r6, r1, r1
+ mov r10, r10, asr #9
+ qadd r0, r0, r3
+ smultt r11, r1, r1
+ add r2, r2, #4
+ qadd r0, r0, r10
+ mov r6, r6, asr #9
+ mov r11, r11, asr #9
+ ldr r1, [r5, r2]
+ qadd r0, r0, r6
+ smulbb r10, r1, r1
+ smultt r6, r1, r1
+ qadd r0, r0, r11
+ mov r10, r10, asr #9
+ mov r6, r6, asr #9
+ qadd r0, r0, r10
+ add r2, r2, #4
+ add r8, r8, #6
+
+ qadd r0, r0, r6
+ cmp r8, r12
+ blt L132
+L133:
+ ldrsh r6, [r5, r2]
+ mul r10, r6, r6
+ add r2, r2, #2
+ mov r1, r10, asr #9
+ qadd r0, r0, r1
+L134:
+ add r8, r8, #1
+ cmp r8, r4
+ blt L133
+L135:
+L136:
+ str r0, [r7, #0]
+ cmp r0, #0
+ beq L1320
+L137:
+ mov r2, r9, lsl #16
+ mov r8, #1
+ mov r2, r2, asr #16
+ cmp r2, #1
+ ble L1319
+L138:
+L139:
+ sub r4, r4, #1
+ mov r14, #0
+ mov r3, #0
+ cmp r4, #0
+ ble L1317
+L1310:
+ cmp r4, #6
+ addlt r6, r5, r8, lsl #1
+ blt L1314
+L1311:
+ add r6, r5, r8, lsl #1
+ sub r12, r4, #6
+ str r8, [r13, #8]
+ str r7, [r13, #4]
+L1312:
+ mov r1, r3, lsl #1
+ ldrsh r7, [r6, r1]
+ ldrsh r10, [r5, r1]
+ add r8, r1, r6
+ add r9, r5, r1
+ mul r7, r10, r7
+ ldrsh r1, [r8, #2]
+ ldrsh r10, [r8, #4]
+ add r7, r14, r7, asr #9
+ ldrsh r0, [r9, #2]
+ ldrsh r11, [r9, #4]
+ mul r1, r0, r1
+ ldrsh r14, [r8, #6]
+ mul r10, r11, r10
+ add r7, r7, r1, asr #9
+ ldrsh r8, [r8, #8]
+ add r3, r3, #5
+ ldrsh r11, [r9, #6]
+ ldrsh r1, [r9, #8]
+ mul r14, r11, r14
+ add r7, r7, r10, asr #9
+ mul r1, r1, r8
+ add r14, r7, r14, asr #9
+ cmp r3, r12
+ add r14, r14, r1, asr #9
+ ble L1312
+L1313:
+ ldr r8, [r13, #8]
+ ldr r7, [r13, #4]
+L1314:
+L1315:
+ mov r12, r3, lsl #1
+ ldrsh r9, [r6, r12]
+ ldrsh r12, [r5, r12]
+ add r3, r3, #1
+ cmp r3, r4
+ mul r12, r12, r9
+ add r14, r14, r12, asr #9
+ blt L1315
+L1316:
+L1317:
+ str r14, [r7, +r8, lsl #2]
+ add r8, r8, #1
+ cmp r8, r2
+ blt L139
+
+L1319:
+L1320:
+ add r13, r13, #20
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |AutoCorrelation|
+ .end
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s
new file mode 100644
index 0000000..7997e98
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/CalcWindowEnergy_v5.s
@@ -0,0 +1,112 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: CalcWindowEnergy_v5.s
+@
+@ Content: CalcWindowEnergy function armv5 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+
+ .global CalcWindowEnergy
+
+CalcWindowEnergy:
+ stmdb sp!, {r4 - r11, lr}
+ sub r13, r13, #20
+
+ mov r3, r3, lsl #16
+ ldr r10, [r0, #168] @ states0 = blockSwitchingControl->iirStates[0];
+ mov r3, r3, asr #16
+ ldr r11, [r0, #172] @ states1 = blockSwitchingControl->iirStates[1];
+
+ mov r2, r2, lsl #16
+ ldr r12, hiPassCoeff @ Coeff0 = hiPassCoeff[0];
+ mov r2, r2, asr #16
+ ldr r14, hiPassCoeff + 4 @ Coeff1 = hiPassCoeff[1];
+
+ mov r8, #0 @ w=0
+ mov r5, #0 @ wOffset = 0;
+
+BLOCK_BEGIN:
+ mov r6, #0 @ accuUE = 0;
+ mov r7, #0 @ accuFE = 0;
+ mov r4, #0 @ i=0
+
+ str r8, [r13, #4]
+ str r0, [r13, #8]
+ str r3, [r13, #12]
+
+ENERGY_BEG:
+ mov r9, r5, lsl #1
+ ldrsh r9, [r1, r9] @ tempUnfiltered = timeSignal[tidx];
+
+ add r5, r5, r2 @ tidx = tidx + chIncrement;
+
+ smulwb r3, r14, r9 @ accu1 = L_mpy_ls(Coeff1, tempUnfiltered);
+ smull r0, r8, r12, r11 @ accu2 = fixmul( Coeff0, states1 );
+
+ mov r3, r3, lsl #1
+ mov r8, r8, lsl #1
+
+ sub r0, r3, r10 @ accu3 = accu1 - states0;
+ sub r8, r0, r8 @ out = accu3 - accu2;
+
+ mov r10, r3 @ states0 = accu1;
+ mov r11, r8 @ states1 = out;
+
+ mul r3, r9, r9
+ mov r8, r8, asr #16
+
+ add r4, r4, #1
+ add r6, r6, r3, asr #7
+
+ mul r9, r8, r8
+ ldr r3, [r13, #12]
+
+ add r7, r7, r9, asr #7
+
+ cmp r4, r3
+ blt ENERGY_BEG
+
+ ldr r0, [r13, #8]
+ ldr r8, [r13, #4]
+
+ENERGY_END:
+ add r4, r0, r8, lsl #2
+
+ str r6, [r4, #72]
+ add r8, r8, #1
+ str r7, [r4, #136]
+
+ cmp r8, #8
+ blt BLOCK_BEGIN
+
+BLOCK_END:
+ str r10, [r0, #168]
+ str r11, [r0, #172]
+ mov r0, #1
+
+ add r13, r13, #20
+ ldmia sp!, {r4 - r11, pc}
+
+hiPassCoeff:
+ .word 0xbec8b439
+ .word 0x609d4952
+
+ @ENDP
+ .end
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s
new file mode 100644
index 0000000..d4d3edb
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/PrePostMDCT_v5.s
@@ -0,0 +1,131 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: PrePostMDCT_v5.s
+@
+@ Content: premdct and postmdct function armv5 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global PreMDCT
+
+PreMDCT:
+ stmdb sp!, {r4 - r11, lr}
+
+ add r9, r0, r1, lsl #2
+ sub r3, r9, #8
+
+ movs r1, r1, asr #2
+ beq PreMDCT_END
+
+PreMDCT_LOOP:
+ ldr r8, [r2], #4
+ ldr r9, [r2], #4
+
+ ldrd r4, [r0]
+ ldrd r6, [r3]
+
+ smull r14, r11, r4, r8 @ MULHIGH(tr1, cosa)
+ smull r10, r12, r7, r8 @ MULHIGH(ti1, cosa)
+
+ smull r14, r8, r7, r9 @ MULHIGH(ti1, sina)
+ smull r7, r10, r4, r9 @ MULHIGH(tr1, sina)
+
+ add r11, r11, r8 @ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
+ sub r7, r12, r10 @ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)
+
+ ldr r8, [r2], #4
+ ldr r9, [r2], #4
+
+ smull r14, r4, r6, r8 @ MULHIGH(tr2, cosa)
+ smull r10, r12, r5, r8 @ MULHIGH(ti2, cosa)
+
+ smull r14, r8, r5, r9 @ MULHIGH(ti2, sina)
+ smull r5, r10, r6, r9 @ MULHIGH(tr2, sina)
+
+ add r8, r8, r4
+ sub r9, r12, r10
+
+ mov r6, r11
+
+ strd r6, [r0]
+ strd r8, [r3]
+
+ subs r1, r1, #1
+ sub r3, r3, #8
+ add r0, r0, #8
+ bne PreMDCT_LOOP
+
+PreMDCT_END:
+ ldmia sp!, {r4 - r11, pc}
+ @ENDP @ |PreMDCT|
+
+ .section .text
+ .global PostMDCT
+
+PostMDCT:
+ stmdb sp!, {r4 - r11, lr}
+
+ add r9, r0, r1, lsl #2
+ sub r3, r9, #8
+
+ movs r1, r1, asr #2
+ beq PostMDCT_END
+
+PostMDCT_LOOP:
+ ldr r8, [r2], #4
+ ldr r9, [r2], #4
+
+ ldrd r4, [r0]
+ ldrd r6, [r3]
+
+ smull r14, r11, r4, r8 @ MULHIGH(tr1, cosa)
+ smull r10, r12, r5, r8 @ MULHIGH(ti1, cosa)
+
+ smull r14, r8, r5, r9 @ MULHIGH(ti1, sina)
+ smull r5, r10, r4, r9 @ MULHIGH(tr1, sina)
+
+ add r4, r11, r8 @ MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
+ sub r11, r10, r12 @ MULHIGH(ti1, cosa) - MULHIGH(tr1, sina)@
+
+ ldr r8, [r2], #4 @
+ ldr r9, [r2], #4
+
+ smull r14, r5, r6, r8 @ MULHIGH(tr2, cosa)
+ smull r10, r12, r7, r8 @ MULHIGH(ti2, cosa)
+
+ smull r14, r8, r7, r9 @ MULHIGH(ti2, sina)
+ smull r7, r10, r6, r9 @ MULHIGH(tr2, sina)
+
+ add r6, r8, r5 @ MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2)@
+ sub r5, r10, r12 @ MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2)@
+
+ mov r7, r11
+
+ strd r4, [r0]
+ strd r6, [r3]
+
+ subs r1, r1, #1
+ sub r3, r3, #8
+ add r0, r0, #8
+ bne PostMDCT_LOOP
+
+PostMDCT_END:
+ ldmia sp!, {r4 - r11, pc}
+ @ENDP @ |PostMDCT|
+ .end \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s
new file mode 100644
index 0000000..370daf4
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/R4R8First_v5.s
@@ -0,0 +1,252 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: R4R8First_v5.s
+@
+@ Content: Radix8First and Radix4First function armv5 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global Radix4First
+
+Radix4First:
+ stmdb sp!, {r4 - r11, lr}
+
+ movs r10, r1
+ mov r11, r0
+ beq Radix4First_END
+
+Radix4First_LOOP:
+ ldrd r0, [r11]
+ ldrd r2, [r11, #8]
+ ldrd r4, [r11, #16]
+ ldrd r6, [r11, #24]
+
+ add r8, r0, r2
+ add r9, r1, r3
+
+ sub r0, r0, r2
+ sub r1, r1, r3
+
+ add r2, r4, r6
+ add r3, r5, r7
+
+ sub r4, r4, r6
+ sub r5, r5, r7
+
+ add r6, r8, r2
+ add r7, r9, r3
+
+ sub r8, r8, r2
+ sub r9, r9, r3
+
+ add r2, r0, r5
+ sub r3, r1, r4
+
+ sub r0, r0, r5
+ add r1, r1, r4
+
+ strd r6, [r11]
+ strd r2, [r11, #8]
+ strd r8, [r11, #16]
+ strd r0, [r11, #24]
+
+ subs r10, r10, #1
+ add r11, r11, #32
+ bne Radix4First_LOOP
+
+Radix4First_END:
+ ldmia sp!, {r4 - r11, pc}
+ @ENDP @ |Radix4First|
+
+ .section .text
+ .global Radix8First
+
+Radix8First:
+ stmdb sp!, {r4 - r11, lr}
+ sub sp, sp, #0x24
+
+ mov r12, r1
+ mov r14, r0
+ cmp r12, #0
+ beq Radix8First_END
+
+Radix8First_LOOP:
+ ldrd r0, [r14]
+ ldrd r2, [r14, #8]
+ ldrd r4, [r14, #16]
+ ldrd r6, [r14, #24]
+
+ add r8, r0, r2 @ r0 = buf[0] + buf[2]@
+ add r9, r1, r3 @ i0 = buf[1] + buf[3]@
+
+ sub r0, r0, r2 @ r1 = buf[0] - buf[2]@
+ sub r1, r1, r3 @ i1 = buf[1] - buf[3]@
+
+ add r2, r4, r6 @ r2 = buf[4] + buf[6]@
+ add r3, r5, r7 @ i2 = buf[5] + buf[7]@
+
+ sub r4, r4, r6 @ r3 = buf[4] - buf[6]@
+ sub r5, r5, r7 @ i3 = buf[5] - buf[7]@
+
+ add r6, r8, r2 @ r4 = (r0 + r2) >> 1@
+ add r7, r9, r3 @ i4 = (i0 + i2) >> 1@
+
+ sub r8, r8, r2 @ r5 = (r0 - r2) >> 1@
+ sub r9, r9, r3 @ i5 = (i0 - i2) >> 1@
+
+ sub r2, r0, r5 @ r6 = (r1 - i3) >> 1@
+ add r3, r1, r4 @ i6 = (i1 + r3) >> 1@
+
+ add r0, r0, r5 @ r7 = (r1 + i3) >> 1@
+ sub r1, r1, r4 @ i7 = (i1 - r3) >> 1@
+
+ mov r6, r6, asr #1 @
+ mov r7, r7, asr #1 @
+
+ mov r8, r8, asr #1
+ mov r9, r9, asr #1
+
+ mov r2, r2, asr #1
+ mov r3, r3, asr #1
+
+ mov r0, r0, asr #1
+ mov r1, r1, asr #1
+
+ str r6, [sp]
+ str r7, [sp, #4]
+
+ str r8, [sp, #8]
+ str r9, [sp, #12]
+
+ str r2, [sp, #16]
+ str r3, [sp, #20]
+
+ str r0, [sp, #24]
+ str r1, [sp, #28]
+
+ ldrd r2, [r14, #32]
+ ldrd r4, [r14, #40]
+ ldrd r6, [r14, #48]
+ ldrd r8, [r14, #56]
+
+ add r0, r2, r4 @ r0 = buf[ 8] + buf[10]@
+ add r1, r3, r5 @ i0 = buf[ 9] + buf[11]@
+
+ sub r2, r2, r4 @ r1 = buf[ 8] - buf[10]@
+ sub r3, r3, r5 @ i1 = buf[ 9] - buf[11]@
+
+ add r4, r6, r8 @ r2 = buf[12] + buf[14]@
+ add r5, r7, r9 @ i2 = buf[13] + buf[15]@
+
+ sub r6, r6, r8 @ r3 = buf[12] - buf[14]@
+ sub r7, r7, r9 @ i3 = buf[13] - buf[15]@
+
+ add r8, r0, r4 @ t0 = (r0 + r2)
+ add r9, r1, r5 @ t1 = (i0 + i2)
+
+ sub r0, r0, r4 @ t2 = (r0 - r2)
+ sub r1, r1, r5 @ t3 = (i0 - i2)
+
+ mov r8, r8, asr #1
+ ldr r4, [sp]
+
+ mov r9, r9, asr #1
+ ldr r5, [sp, #4]
+
+ mov r0, r0, asr #1
+ mov r1, r1, asr #1
+
+ add r10, r4, r8 @ buf[ 0] = r4 + t0@
+ add r11, r5, r9 @ buf[ 1] = i4 + t1@
+
+ sub r4, r4, r8 @ buf[ 8] = r4 - t0@
+ sub r5, r5, r9 @ buf[ 9] = i4 - t1@
+
+ strd r10, [r14]
+ strd r4, [r14, #32]
+
+ ldr r10, [sp, #8]
+ ldr r11, [sp, #12]
+
+ add r4, r10, r1 @ buf[ 4] = r5 + t3@
+ sub r5, r11, r0 @ buf[ 5] = i5 - t2@
+
+ sub r10, r10, r1 @ buf[12] = r5 - t3@
+ add r11, r11, r0 @ buf[13] = i5 + t2@
+
+ strd r4, [r14, #16]
+ strd r10, [r14, #48]
+
+ sub r0, r2, r7 @ r0 = r1 - i3@
+ add r1, r3, r6 @ i0 = i1 + r3@
+
+ ldr r11, DATATab
+
+ add r2, r2, r7 @ r2 = r1 + i3@
+ sub r3, r3, r6 @ i2 = i1 - r3@
+
+ sub r4, r0, r1 @ r0 - i0
+ add r5, r0, r1 @ r0 + i0
+
+ sub r0, r2, r3 @ r2 - i2
+ add r1, r2, r3 @ r2 + i2
+
+ smull r8, r6, r4, r11
+ smull r9, r7, r5, r11
+
+ ldr r2, [sp, #16]
+ ldr r3, [sp, #20]
+
+ smull r8, r4, r0, r11
+ smull r9, r5, r1, r11
+
+ ldr r10, [sp, #24]
+ ldr r11, [sp, #28]
+
+ sub r8, r2, r6
+ sub r9, r3, r7
+
+ add r2, r2, r6
+ add r3, r3, r7
+
+ add r6, r10, r5
+ sub r7, r11, r4
+
+ sub r0, r10, r5
+ add r1, r11, r4
+
+ strd r6, [r14, #8]
+ strd r8, [r14, #24]
+ strd r0, [r14, #40]
+ strd r2, [r14, #56]
+
+ subs r12, r12, #1
+ add r14, r14, #64
+
+ bne Radix8First_LOOP
+
+Radix8First_END:
+ add sp, sp, #0x24
+ ldmia sp!, {r4 - r11, pc}
+
+DATATab:
+ .word 0x5a82799a
+
+ @ENDP @ |Radix8First|
+ .end \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s
new file mode 100644
index 0000000..db8e5d8
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/Radix4FFT_v5.s
@@ -0,0 +1,169 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: Radix4FFT_v5.s
+@
+@ Content: Radix4FFT armv5 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+ .section .text
+ .global Radix4FFT
+
+Radix4FFT:
+ stmdb sp!, {r4 - r11, lr}
+ sub sp, sp, #32
+
+ mov r1, r1, asr #2
+ cmp r1, #0
+ beq Radix4FFT_END
+
+Radix4FFT_LOOP1:
+ mov r14, r0 @ xptr = buf@
+ mov r10, r1 @ i = num@
+ mov r9, r2, lsl #3 @ step = 2*bgn@
+ cmp r10, #0
+ str r0, [sp]
+ str r1, [sp, #4]
+ str r2, [sp, #8]
+ str r3, [sp, #12]
+ beq Radix4FFT_LOOP1_END
+
+Radix4FFT_LOOP2:
+ mov r12, r3 @ csptr = twidTab@
+ mov r11, r2 @ j = bgn
+ cmp r11, #0
+ str r10, [sp, #16]
+ beq Radix4FFT_LOOP2_END
+
+Radix4FFT_LOOP3:
+ str r11, [sp, #20]
+
+ ldrd r0, [r14, #0] @ r0 = xptr[0]@ r1 = xptr[1]@
+ add r14, r14, r9 @ xptr += step@
+
+ ldrd r10, [r14, #0] @ r2 = xptr[0]@ r3 = xptr[1]@
+ ldr r8, [r12], #4 @ cosxsinx = csptr[0]@
+
+ smulwt r4, r10, r8 @ L_mpy_wx(cosx, t0)
+ smulwt r3, r11, r8 @ L_mpy_wx(cosx, t1)
+
+ smlawb r2, r11, r8, r4 @ r2 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@
+ smulwb r5, r10, r8 @ L_mpy_wx(sinx, t0)
+
+ mov r10, r0, asr #2 @ t0 = r0 >> 2@
+ mov r11, r1, asr #2 @ t1 = r1 >> 2@
+
+ sub r3, r3, r5 @ r3 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@
+ add r14, r14, r9 @ xptr += step@
+
+ sub r0, r10, r2 @ r0 = t0 - r2@
+ sub r1, r11, r3 @ r1 = t1 - r3@
+
+ add r2, r10, r2 @ r2 = t0 + r2@
+ add r3, r11, r3 @ r3 = t1 + r3@
+
+ str r2, [sp, #24]
+ str r3, [sp, #28]
+
+ ldrd r10, [r14, #0] @ r4 = xptr[0]@ r5 = xptr[1]@
+ ldr r8, [r12], #4 @ cosxsinx = csptr[1]@
+
+ smulwt r6, r10, r8 @ L_mpy_wx(cosx, t0)
+ smulwt r5, r11, r8 @ L_mpy_wx(cosx, t1)
+
+ smlawb r4, r11, r8, r6 @ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@
+ smulwb r7, r10, r8 @ L_mpy_wx(sinx, t0)
+
+ add r14, r14, r9 @ xptr += step@
+ sub r5, r5, r7 @ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@
+
+ ldrd r10, [r14] @ r6 = xptr[0]@ r7 = xptr[1]@
+ ldr r8, [r12], #4 @ cosxsinx = csptr[1]@
+
+ smulwt r2, r10, r8 @ L_mpy_wx(cosx, t0)
+ smulwt r7, r11, r8 @ L_mpy_wx(cosx, t1)
+
+ smlawb r6, r11, r8, r2 @ r4 = L_mpy_wx(cosx, t0) + L_mpy_wx(sinx, t1)@
+ smulwb r3, r10, r8 @ L_mpy_wx(sinx, t0)
+
+ mov r10, r4 @ t0 = r4@
+ mov r11, r5 @ t1 = r5@
+
+ sub r7, r7, r3 @ r5 = L_mpy_wx(cosx, t1) - L_mpy_wx(sinx, t0)@
+
+
+ add r4, r10, r6 @ r4 = t0 + r6@
+ sub r5, r7, r11 @ r5 = r7 - t1@
+
+ sub r6, r10, r6 @ r6 = t0 - r6@
+ add r7, r7, r11 @ r7 = r7 + t1@
+
+ ldr r2, [sp, #24]
+ ldr r3, [sp, #28]
+
+ add r10, r0, r5 @ xptr[0] = r0 + r5@
+ add r11, r1, r6 @ xptr[0] = r1 + r6
+
+ strd r10, [r14]
+ sub r14, r14, r9 @ xptr -= step@
+
+ sub r10, r2, r4 @ xptr[0] = r2 - r4@
+ sub r11, r3, r7 @ xptr[1] = r3 - r7@
+
+ strd r10, [r14]
+ sub r14, r14, r9 @ xptr -= step@
+
+ sub r10, r0, r5 @ xptr[0] = r0 - r5@
+ sub r11, r1, r6 @ xptr[0] = r1 - r6
+
+ strd r10, [r14]
+ sub r14, r14, r9 @ xptr -= step@
+
+ add r10, r2, r4 @ xptr[0] = r2 - r4@
+ add r11, r3, r7 @ xptr[1] = r3 - r7@
+
+ strd r10, [r14]
+ add r14, r14, #8 @ xptr += 2@
+
+ ldr r11, [sp, #20]
+ subs r11, r11, #1
+ bne Radix4FFT_LOOP3
+
+Radix4FFT_LOOP2_END:
+ ldr r10, [sp, #16]
+ ldr r3, [sp, #12]
+ ldr r2, [sp, #8]
+ rsb r8, r9, r9, lsl #2
+ sub r10, r10, #1
+ add r14, r14, r8
+ cmp r10, #0
+ bhi Radix4FFT_LOOP2
+
+Radix4FFT_LOOP1_END:
+ ldr r0, [sp]
+ ldr r1, [sp, #4]
+ add r3, r3, r8, asr #1
+ mov r2, r2, lsl #2
+ movs r1, r1, asr #2
+ bne Radix4FFT_LOOP1
+
+Radix4FFT_END:
+ add sp, sp, #32
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |Radix4FFT|
+ .end \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s
new file mode 100644
index 0000000..a463dfd
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV5E/band_nrg_v5.s
@@ -0,0 +1,204 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: band_nrg_v5.s
+@
+@ Content: CalcBandEnergy and CalcBandEnergyMS function armv5 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+
+ .global CalcBandEnergy
+
+CalcBandEnergy:
+ stmdb sp!, {r4 - r11, lr}
+
+ mov r2, r2, lsl #16
+ ldr r12, [r13, #36]
+ mov r9, #0
+ mov r5, r2, asr #16
+ mov r4, #0
+ cmp r5, #0
+ ble L212
+
+L22:
+ mov r2, r4, lsl #1
+ ldrsh r10, [r1, r2]
+ add r11, r1, r2
+ ldrsh r2, [r11, #2]
+ mov r14, #0
+ cmp r10, r2
+ bge L28
+
+L23:
+ ldr r11, [r0, +r10, lsl #2]
+ add r10, r10, #1
+ ldr r6, [r0, +r10, lsl #2]
+ smull r11, r7, r11, r11
+ add r10, r10, #1
+ smull r6, r8, r6, r6
+ ldr r11, [r0, +r10, lsl #2]
+ qadd r14, r14, r7
+ add r10, r10, #1
+ smull r11, r7, r11, r11
+ ldr r6, [r0, +r10, lsl #2]
+ qadd r14, r14, r8
+ smull r6, r8, r6, r6
+ add r10, r10, #1
+ qadd r14, r14, r7
+ cmp r10, r2
+ qadd r14, r14, r8
+ blt L23
+
+L28:
+ qadd r14, r14, r14
+ str r14, [r3, +r4, lsl #2]
+ add r4, r4, #1
+ qadd r9, r9, r14
+ cmp r4, r5
+
+ blt L22
+
+L212:
+ str r9, [r12, #0]
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP ; |CalcBandEnergy|
+
+ .global CalcBandEnergyMS
+
+CalcBandEnergyMS:
+ stmdb sp!, {r4 - r11, lr}
+ sub r13, r13, #24
+
+ mov r12, #0
+ mov r3, r3, lsl #16
+ mov r14, #0
+ mov r3, r3, asr #16
+ cmp r3, #0
+ mov r4, #0
+ ble L315
+
+L32:
+ mov r5, r4, lsl #1
+ mov r6, #0
+ ldrsh r10, [r2, r5]
+ add r5, r2, r5
+ mov r7, #0
+ ldrsh r11, [r5, #2]
+ cmp r10, r11
+ bge L39
+
+ str r3, [r13, #4]
+ str r4, [r13, #8]
+ str r12, [r13, #12]
+ str r14, [r13, #16]
+
+L33:
+ ldr r8, [r0, +r10, lsl #2]
+ ldr r9, [r1, +r10, lsl #2]
+ mov r8, r8, asr #1
+ add r10, r10, #1
+ mov r9, r9, asr #1
+
+ ldr r12, [r0, +r10, lsl #2]
+ add r5, r8, r9
+ ldr r14, [r1, +r10, lsl #2]
+ sub r8, r8, r9
+
+ smull r5, r3, r5, r5
+ mov r12, r12, asr #1
+ smull r8, r4, r8, r8
+ mov r14, r14, asr #1
+
+ qadd r6, r6, r3
+ add r5, r12, r14
+ qadd r7, r7, r4
+ sub r8, r12, r14
+
+ smull r5, r3, r5, r5
+ add r10, r10, #1
+ smull r8, r4, r8, r8
+
+ qadd r6, r6, r3
+ qadd r7, r7, r4
+
+ ldr r8, [r0, +r10, lsl #2]
+ ldr r9, [r1, +r10, lsl #2]
+ mov r8, r8, asr #1
+ add r10, r10, #1
+ mov r9, r9, asr #1
+
+ ldr r12, [r0, +r10, lsl #2]
+ add r5, r8, r9
+ ldr r14, [r1, +r10, lsl #2]
+ sub r8, r8, r9
+
+ smull r5, r3, r5, r5
+ mov r12, r12, asr #1
+ smull r8, r4, r8, r8
+ mov r14, r14, asr #1
+
+ qadd r6, r6, r3
+ add r5, r12, r14
+ qadd r7, r7, r4
+ sub r8, r12, r14
+
+ smull r5, r3, r5, r5
+ add r10, r10, #1
+ smull r8, r4, r8, r8
+
+ qadd r6, r6, r3
+ qadd r7, r7, r4
+
+ cmp r10, r11
+
+ blt L33
+
+ ldr r3, [r13, #4]
+ ldr r4, [r13, #8]
+ ldr r12, [r13, #12]
+ ldr r14, [r13, #16]
+L39:
+ qadd r6, r6, r6
+ qadd r7, r7, r7
+
+ ldr r8, [r13, #60]
+ ldr r9, [r13, #68]
+
+ qadd r12, r12, r6
+ qadd r14, r14, r7
+
+ str r6, [r8, +r4, lsl #2]
+ str r7, [r9, +r4, lsl #2]
+
+ add r4, r4, #1
+ cmp r4, r3
+ blt L32
+
+L315:
+ ldr r8, [r13, #64]
+ ldr r9, [r13, #72]
+ str r12, [r8, #0]
+ str r14, [r9, #0]
+
+ add r13, r13, #24
+ ldmia sp!, {r4 - r11, pc}
+ @ENDP ; |CalcBandEnergyMS|
+
+ .end
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s
new file mode 100644
index 0000000..bf7dcba
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/PrePostMDCT_v7.s
@@ -0,0 +1,135 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: PrePostMDCT_v7.s
+@
+@ Content: premdct and postmdct function armv7 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global PreMDCT
+
+PreMDCT:
+ stmdb sp!, {r4 - r11, lr}
+
+ add r9, r0, r1, lsl #2
+ sub r3, r9, #32
+
+ movs r1, r1, asr #2
+ beq PreMDCT_END
+
+PreMDCT_LOOP:
+ VLD4.I32 {d0, d2, d4, d6}, [r2]! @ cosa = *csptr++@ sina = *csptr++@
+ VLD4.I32 {d1, d3, d5, d7}, [r2]! @ cosb = *csptr++@ sinb = *csptr++@
+ VLD2.I32 {d8, d9, d10, d11}, [r0] @ tr1 = *(buf0 + 0)@ ti2 = *(buf0 + 1)@
+ VLD2.I32 {d13, d15}, [r3]! @ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@
+ VLD2.I32 {d12, d14}, [r3]! @ tr2 = *(buf1 - 1)@ ti1 = *(buf1 + 0)@
+
+ VREV64.32 Q8, Q7
+ VREV64.32 Q9, Q6
+
+
+ VQDMULH.S32 Q10, Q0, Q4 @ MULHIGH(cosa, tr1)
+ VQDMULH.S32 Q11, Q1, Q8 @ MULHIGH(sina, ti1)
+ VQDMULH.S32 Q12, Q0, Q8 @ MULHIGH(cosa, ti1)
+ VQDMULH.S32 Q13, Q1, Q4 @ MULHIGH(sina, tr1)
+
+ VADD.S32 Q0, Q10, Q11 @ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
+ VSUB.S32 Q1, Q12, Q13 @ *buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1)@
+
+ VST2.I32 {d0, d1, d2, d3}, [r0]!
+ sub r3, r3, #32
+
+ VQDMULH.S32 Q10, Q2, Q9 @ MULHIGH(cosb, tr2)
+ VQDMULH.S32 Q11, Q3, Q5 @ MULHIGH(sinb, ti2)
+ VQDMULH.S32 Q12, Q2, Q5 @ MULHIGH(cosb, ti2)
+ VQDMULH.S32 Q13, Q3, Q9 @ MULHIGH(sinb, tr2)
+
+ VADD.S32 Q0, Q10, Q11 @ MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@
+ VSUB.S32 Q1, Q12, Q13 @ MULHIGH(cosa, ti2) - MULHIGH(sina, tr2)@
+
+ VREV64.32 Q3, Q1
+ VREV64.32 Q2, Q0
+
+ VST2.I32 {d5, d7}, [r3]!
+ VST2.I32 {d4, d6}, [r3]!
+
+ subs r1, r1, #4
+ sub r3, r3, #64
+ bne PreMDCT_LOOP
+
+PreMDCT_END:
+ ldmia sp!, {r4 - r11, pc}
+ @ENDP @ |PreMDCT|
+
+ .section .text
+ .global PostMDCT
+
+PostMDCT:
+ stmdb sp!, {r4 - r11, lr}
+
+ add r9, r0, r1, lsl #2
+ sub r3, r9, #32
+
+ movs r1, r1, asr #2
+ beq PostMDCT_END
+
+PostMDCT_LOOP:
+ VLD4.I32 {d0, d2, d4, d6}, [r2]! @ cosa = *csptr++@ sina = *csptr++@
+ VLD4.I32 {d1, d3, d5, d7}, [r2]! @ cosb = *csptr++@ sinb = *csptr++@
+ VLD2.I32 {d8, d9, d10, d11}, [r0] @ tr1 = *(zbuf1 + 0)@ ti1 = *(zbuf1 + 1)@
+ VLD2.I32 {d13, d15}, [r3]! @ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@
+ VLD2.I32 {d12, d14}, [r3]! @ tr2 = *(zbuf2 - 1)@ ti2 = *(zbuf2 + 0)@
+
+ VREV64.32 Q8, Q6
+ VREV64.32 Q9, Q7
+
+ VQDMULH.S32 Q10, Q0, Q4 @ MULHIGH(cosa, tr1)
+ VQDMULH.S32 Q11, Q1, Q5 @ MULHIGH(sina, ti1)
+ VQDMULH.S32 Q12, Q0, Q5 @ MULHIGH(cosa, ti1)
+ VQDMULH.S32 Q13, Q1, Q4 @ MULHIGH(sina, tr1)
+
+ VADD.S32 Q0, Q10, Q11 @ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1)@
+ VSUB.S32 Q5, Q13, Q12 @ *buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1)@
+
+ VQDMULH.S32 Q10, Q2, Q8 @ MULHIGH(cosb, tr2)
+ VQDMULH.S32 Q11, Q3, Q9 @ MULHIGH(sinb, ti2)
+ VQDMULH.S32 Q12, Q2, Q9 @ MULHIGH(cosb, ti2)
+ VQDMULH.S32 Q13, Q3, Q8 @ MULHIGH(sinb, tr2)
+
+ VADD.S32 Q4, Q10, Q11 @ *buf1-- = MULHIGH(cosa, tr2) + MULHIGH(sina, ti2)@
+ VSUB.S32 Q1, Q13, Q12 @ *buf0++ = MULHIGH(sina, tr2) - MULHIGH(cosa, ti2)@
+
+ VREV64.32 Q2, Q4
+ VREV64.32 Q3, Q5
+
+ sub r3, r3, #32
+ VST2.I32 {d0, d1, d2, d3}, [r0]!
+
+ VST2.I32 {d5, d7}, [r3]!
+ VST2.I32 {d4, d6}, [r3]!
+
+ subs r1, r1, #4
+ sub r3, r3, #64
+ bne PostMDCT_LOOP
+
+PostMDCT_END:
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |PostMDCT|
+ .end \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s
new file mode 100644
index 0000000..99ee68b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/R4R8First_v7.s
@@ -0,0 +1,146 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: R4R8First_v7.s
+@
+@ Content: Radix8First and Radix4First function armv7 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global Radix8First
+
+Radix8First:
+ stmdb sp!, {r4 - r11, lr}
+
+ ldr r3, SQRT1_2
+ cmp r1, #0
+
+ VDUP.I32 Q15, r3
+ beq Radix8First_END
+
+Radix8First_LOOP:
+ VLD1.I32 {d0, d1, d2, d3}, [r0]!
+ VLD1.I32 {d8, d9, d10, d11}, [r0]!
+
+ VADD.S32 d4, d0, d1 @ r0 = buf[0] + buf[2]@i0 = buf[1] + buf[3]@
+ VSUB.S32 d5, d0, d1 @ r1 = buf[0] - buf[2]@i1 = buf[1] - buf[3]@
+ VSUB.S32 d7, d2, d3 @ r2 = buf[4] - buf[6]@i2 = buf[5] - buf[7]@
+ VADD.S32 d6, d2, d3 @ r3 = buf[4] + buf[6]@i3 = buf[5] + buf[7]@
+ VREV64.I32 d7, d7
+
+ VADD.S32 Q0, Q2, Q3 @ r4 = (r0 + r2)@i4 = (i0 + i2)@i6 = (i1 + r3)@r7 = (r1 + i3)
+ VSUB.S32 Q1, Q2, Q3 @ r5 = (r0 - r2)@i5 = (i0 - i2)@r6 = (r1 - i3)@i7 = (i1 - r3)@
+
+ VREV64.I32 d3, d3
+
+ VADD.S32 d4, d8, d9 @ r0 = buf[ 8] + buf[10]@i0 = buf[ 9] + buf[11]@
+ VSUB.S32 d7, d10, d11 @ r1 = buf[12] - buf[14]@i1 = buf[13] - buf[15]@
+ VADD.S32 d6, d10, d11 @ r2 = buf[12] + buf[14]@i2 = buf[13] + buf[15]@
+ VREV64.I32 d7, d7
+ VSUB.S32 d5, d8, d9 @ r3 = buf[ 8] - buf[10]@i3 = buf[ 9] - buf[11]@
+
+ VTRN.32 d1, d3
+
+ VADD.S32 Q4, Q2, Q3 @ t0 = (r0 + r2) >> 1@t1 = (i0 + i2) >> 1@i0 = i1 + r3@r2 = r1 + i3@
+ VSUB.S32 Q5, Q2, Q3 @ t2 = (r0 - r2) >> 1@t3 = (i0 - i2) >> 1@r0 = r1 - i3@i2 = i1 - r3@
+
+ VREV64.I32 d3, d3
+
+ VSHR.S32 d8, d8, #1
+ VSHR.S32 Q0, Q0, #1
+ VREV64.I32 d10, d10
+ VTRN.32 d11, d9
+ VSHR.S32 Q1, Q1, #1
+ VSHR.S32 d10, d10, #1
+ VREV64.I32 d9, d9
+
+ sub r0, r0, #0x40
+
+ VADD.S32 d12, d0, d8
+ VSUB.S32 d16, d0, d8
+ VADD.S32 d14, d2, d10
+ VSUB.S32 d18, d2, d10
+
+ VSUB.S32 d4, d11, d9
+ VADD.S32 d5, d11, d9
+
+ VREV64.I32 d18, d18
+
+ VQDMULH.S32 Q3, Q2, Q15
+ VTRN.32 d14, d18
+ VTRN.32 d6, d7
+ VREV64.I32 d18, d18
+
+ VSUB.S32 d15, d3, d6
+ VREV64.I32 d7, d7
+ VADD.S32 d19, d3, d6
+ VADD.S32 d13, d1, d7
+ VSUB.S32 d17, d1, d7
+
+ VREV64.I32 d17, d17
+ VTRN.32 d13, d17
+ VREV64.I32 d17, d17
+
+ subs r1, r1, #1
+
+ VST1.I32 {d12, d13, d14, d15}, [r0]!
+ VST1.I32 {d16, d17, d18, d19}, [r0]!
+ bne Radix8First_LOOP
+
+Radix8First_END:
+ ldmia sp!, {r4 - r11, pc}
+SQRT1_2:
+ .word 0x2d413ccd
+
+ @ENDP @ |Radix8First|
+
+ .section .text
+ .global Radix4First
+
+Radix4First:
+ stmdb sp!, {r4 - r11, lr}
+
+ cmp r1, #0
+ beq Radix4First_END
+
+Radix4First_LOOP:
+ VLD1.I32 {d0, d1, d2, d3}, [r0]
+
+ VADD.S32 d4, d0, d1 @ r0 = buf[0] + buf[2]@ r1 = buf[1] + buf[3]@
+ VSUB.S32 d5, d0, d1 @ r2 = buf[0] - buf[2]@ r3 = buf[1] - buf[3]@
+ VSUB.S32 d7, d2, d3 @ r4 = buf[4] + buf[6]@ r5 = buf[5] + buf[7]@
+ VADD.S32 d6, d2, d3 @ r6 = buf[4] - buf[6]@ r7 = buf[5] - buf[7]@
+
+ VREV64.I32 d7, d7 @
+
+ VADD.S32 Q4, Q2, Q3
+ VSUB.S32 Q5, Q2, Q3
+
+ VREV64.I32 d11, d11
+ VTRN.32 d9, d11
+ subs r1, r1, #1
+ VREV64.I32 d11, d11
+ VST1.I32 {d8, d9, d10, d11}, [r0]!
+
+ bne Radix4First_LOOP
+
+Radix4First_END:
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |Radix4First|
+ .end \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s
new file mode 100644
index 0000000..e1a8438
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/asm/ARMV7/Radix4FFT_v7.s
@@ -0,0 +1,143 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT 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: Radix4FFT_v7.s
+@
+@ Content: Radix4FFT armv7 assemble
+@
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+
+ .section .text
+ .global Radix4FFT
+
+Radix4FFT:
+ stmdb sp!, {r4 - r11, lr}
+
+ mov r1, r1, asr #2
+ cmp r1, #0
+ beq Radix4FFT_END
+
+Radix4FFT_LOOP1:
+ mov r5, r2, lsl #1
+ mov r8, r0
+ mov r7, r1
+ mov r5, r5, lsl #2
+ cmp r1, #0
+ rsbeq r12, r5, r5, lsl #2
+ beq Radix4FFT_LOOP1_END
+
+ rsb r12, r5, r5, lsl #2
+
+Radix4FFT_LOOP2:
+ mov r6, r3
+ mov r4, r2
+ cmp r2, #0
+ beq Radix4FFT_LOOP2_END
+
+Radix4FFT_LOOP3:
+ @r0 = xptr[0]@
+ @r1 = xptr[1]@
+ VLD2.I32 {D0, D1, D2, D3}, [r8]
+ VLD2.I32 {D28, D29, D30, D31}, [r6]! @ cosx = csptr[0]@ sinx = csptr[1]@
+
+ add r8, r8, r5 @ xptr += step@
+ VLD2.I32 {D4, D5, D6,D7}, [r8] @ r2 = xptr[0]@ r3 = xptr[1]@
+
+ VQDMULH.S32 Q10, Q2, Q14 @ MULHIGH(cosx, t0)
+ VQDMULH.S32 Q11, Q3, Q15 @ MULHIGH(sinx, t1)
+ VQDMULH.S32 Q12, Q3, Q14 @ MULHIGH(cosx, t1)
+ VQDMULH.S32 Q13, Q2, Q15 @ MULHIGH(sinx, t0)
+
+ VADD.S32 Q2, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)
+ VSUB.S32 Q3, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)
+
+ add r8, r8, r5 @ xptr += step@
+ VSHR.S32 Q10, Q0, #2 @ t0 = r0 >> 2@
+ VSHR.S32 Q11, Q1, #2 @ t1 = r1 >> 2@
+
+ VSUB.S32 Q0, Q10, Q2 @ r0 = t0 - r2@
+ VSUB.S32 Q1, Q11, Q3 @ r1 = t1 - r3@
+ VADD.S32 Q2, Q10, Q2 @ r2 = t0 + r2@
+ VADD.S32 Q3, Q11, Q3 @ r3 = t1 + r3@
+
+ VLD2.I32 {D8, D9, D10, D11}, [r8]
+ VLD2.I32 {D28, D29, D30, D31}, [r6]!
+ add r8, r8, r5
+
+ VQDMULH.S32 Q10, Q4, Q14 @ MULHIGH(cosx, t0)
+ VQDMULH.S32 Q11, Q5, Q15 @ MULHIGH(sinx, t1)
+ VQDMULH.S32 Q12, Q5, Q14 @ MULHIGH(cosx, t1)
+ VQDMULH.S32 Q13, Q4, Q15 @ MULHIGH(sinx, t0)
+
+ VADD.S32 Q8, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)
+ VSUB.S32 Q9, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)
+
+ VLD2.I32 {D12, D13, D14, D15}, [r8]
+ VLD2.I32 {D28, D29, D30, D31}, [r6]!
+
+ VQDMULH.S32 Q10, Q6, Q14 @ MULHIGH(cosx, t0)
+ VQDMULH.S32 Q11, Q7, Q15 @ MULHIGH(sinx, t1)
+ VQDMULH.S32 Q12, Q7, Q14 @ MULHIGH(cosx, t1)
+ VQDMULH.S32 Q13, Q6, Q15 @ MULHIGH(sinx, t0)
+
+ VADD.S32 Q6, Q10, Q11 @ MULHIGH(cosx, t0) + MULHIGH(sinx, t1)
+ VSUB.S32 Q7, Q12, Q13 @ MULHIGH(cosx, t1) - MULHIGH(sinx, t0)
+
+ VADD.S32 Q4, Q8, Q6 @ r4 = t0 + r6@
+ VSUB.S32 Q5, Q7, Q9 @ r5 = r7 - t1@
+ VSUB.S32 Q6, Q8, Q6 @ r6 = t0 - r6@
+ VADD.S32 Q7, Q7, Q9 @ r7 = r7 + t1@
+
+ VADD.S32 Q8, Q0, Q5 @ xptr[0] = r0 + r5@
+ VADD.S32 Q9, Q1, Q6 @ xptr[1] = r1 + r6@
+ VST2.I32 {D16, D17, D18, D19}, [r8]
+
+ VSUB.S32 Q10, Q2, Q4 @ xptr[0] = r2 - r4@
+ sub r8, r8, r5 @ xptr -= step@
+ VSUB.S32 Q11, Q3, Q7 @ xptr[1] = r3 - r7@
+ VST2.I32 {D20, D21, D22, D23}, [r8]
+
+ VSUB.S32 Q8, Q0, Q5 @ xptr[0] = r0 - r5@
+ sub r8, r8, r5 @ xptr -= step@
+ VSUB.S32 Q9, Q1, Q6 @ xptr[1] = r1 - r6@
+ VST2.I32 {D16, D17, D18, D19}, [r8]
+
+ VADD.S32 Q10, Q2, Q4 @ xptr[0] = r2 + r4@
+ sub r8, r8, r5 @ xptr -= step@
+ VADD.S32 Q11, Q3, Q7 @ xptr[1] = r3 + r7@
+ VST2.I32 {D20, D21, D22, D23}, [r8]!
+
+ subs r4, r4, #4
+ bne Radix4FFT_LOOP3
+
+Radix4FFT_LOOP2_END:
+ add r8, r8, r12
+ sub r7, r7, #1
+ cmp r7, #0
+ bhi Radix4FFT_LOOP2
+
+Radix4FFT_LOOP1_END:
+ add r3, r12, r3
+ mov r2, r2, lsl #2
+ movs r1, r1, asr #2
+ bne Radix4FFT_LOOP1
+
+Radix4FFT_END:
+ ldmia sp!, {r4 - r11, pc}
+
+ @ENDP @ |Radix4FFT|
+ .end \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/band_nrg.c b/media/libstagefright/codecs/aacenc/src/band_nrg.c
new file mode 100644
index 0000000..666c4ca
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/band_nrg.c
@@ -0,0 +1,102 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: band_nrg.c
+
+ Content: Band/Line energy calculations functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "band_nrg.h"
+
+#ifndef ARMV5E
+/********************************************************************************
+*
+* function name: CalcBandEnergy
+* description: Calc sfb-bandwise mdct-energies for left and right channel
+*
+**********************************************************************************/
+void CalcBandEnergy(const Word32 *mdctSpectrum,
+ const Word16 *bandOffset,
+ const Word16 numBands,
+ Word32 *bandEnergy,
+ Word32 *bandEnergySum)
+{
+ Word32 i, j;
+ Word32 accuSum = 0;
+
+ for (i=0; i<numBands; i++) {
+ Word32 accu = 0;
+ for (j=bandOffset[i]; j<bandOffset[i+1]; j++)
+ accu = L_add(accu, MULHIGH(mdctSpectrum[j], mdctSpectrum[j]));
+
+ accu = L_add(accu, accu);
+ accuSum = L_add(accuSum, accu);
+ bandEnergy[i] = accu;
+ }
+ *bandEnergySum = accuSum;
+}
+
+/********************************************************************************
+*
+* function name: CalcBandEnergyMS
+* description: Calc sfb-bandwise mdct-energies for left add or minus right channel
+*
+**********************************************************************************/
+void CalcBandEnergyMS(const Word32 *mdctSpectrumLeft,
+ const Word32 *mdctSpectrumRight,
+ const Word16 *bandOffset,
+ const Word16 numBands,
+ Word32 *bandEnergyMid,
+ Word32 *bandEnergyMidSum,
+ Word32 *bandEnergySide,
+ Word32 *bandEnergySideSum)
+{
+
+ Word32 i, j;
+ Word32 accuMidSum = 0;
+ Word32 accuSideSum = 0;
+
+
+ for(i=0; i<numBands; i++) {
+ Word32 accuMid = 0;
+ Word32 accuSide = 0;
+ for (j=bandOffset[i]; j<bandOffset[i+1]; j++) {
+ Word32 specm, specs;
+ Word32 l, r;
+
+ l = mdctSpectrumLeft[j] >> 1;
+ r = mdctSpectrumRight[j] >> 1;
+ specm = l + r;
+ specs = l - r;
+ accuMid = L_add(accuMid, MULHIGH(specm, specm));
+ accuSide = L_add(accuSide, MULHIGH(specs, specs));
+ }
+
+ accuMid = L_add(accuMid, accuMid);
+ accuSide = L_add(accuSide, accuSide);
+ bandEnergyMid[i] = accuMid;
+ accuMidSum = L_add(accuMidSum, accuMid);
+ bandEnergySide[i] = accuSide;
+ accuSideSum = L_add(accuSideSum, accuSide);
+
+ }
+ *bandEnergyMidSum = accuMidSum;
+ *bandEnergySideSum = accuSideSum;
+}
+
+#endif \ No newline at end of file
diff --git a/media/libstagefright/codecs/aacenc/src/bit_cnt.c b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
new file mode 100644
index 0000000..24837e8
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bit_cnt.c
@@ -0,0 +1,885 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bit_cnt.c
+
+ Content: Huffman Bitcounter & coder functions
+
+*******************************************************************************/
+
+#include "bit_cnt.h"
+#include "aac_rom.h"
+
+#define HI_LTAB(a) (a>>8)
+#define LO_LTAB(a) (a & 0xff)
+
+#define EXPAND(a) ((((Word32)(a&0xff00)) << 8)|(Word32)(a&0xff))
+
+
+/*****************************************************************************
+*
+* function name: count1_2_3_4_5_6_7_8_9_10_11
+* description: counts tables 1-11
+* returns:
+* input: quantized spectrum
+* output: bitCount for tables 1-11
+*
+*****************************************************************************/
+
+static void count1_2_3_4_5_6_7_8_9_10_11(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+ Word32 t0,t1,t2,t3,i;
+ Word32 bc1_2,bc3_4,bc5_6,bc7_8,bc9_10;
+ Word16 bc11,sc;
+
+ bc1_2=0;
+ bc3_4=0;
+ bc5_6=0;
+ bc7_8=0;
+ bc9_10=0;
+ bc11=0;
+ sc=0;
+
+ for(i=0;i<width;i+=4){
+
+ t0= values[i+0];
+ t1= values[i+1];
+ t2= values[i+2];
+ t3= values[i+3];
+
+ /* 1,2 */
+
+ bc1_2 = bc1_2 + EXPAND(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);
+
+ /* 5,6 */
+ bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);
+ bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t2+4][t3+4]);
+
+ t0=ABS(t0);
+ t1=ABS(t1);
+ t2=ABS(t2);
+ t3=ABS(t3);
+
+
+ bc3_4 = bc3_4 + EXPAND(huff_ltab3_4[t0][t1][t2][t3]);
+
+ bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
+ bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t2][t3]);
+
+ bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
+ bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t2][t3]);
+
+ bc11 = bc11 + huff_ltab11[t0][t1];
+ bc11 = bc11 + huff_ltab11[t2][t3];
+
+
+ sc = sc + (t0>0) + (t1>0) + (t2>0) + (t3>0);
+ }
+
+ bitCount[1]=extract_h(bc1_2);
+ bitCount[2]=extract_l(bc1_2);
+ bitCount[3]=extract_h(bc3_4) + sc;
+ bitCount[4]=extract_l(bc3_4) + sc;
+ bitCount[5]=extract_h(bc5_6);
+ bitCount[6]=extract_l(bc5_6);
+ bitCount[7]=extract_h(bc7_8) + sc;
+ bitCount[8]=extract_l(bc7_8) + sc;
+ bitCount[9]=extract_h(bc9_10) + sc;
+ bitCount[10]=extract_l(bc9_10) + sc;
+ bitCount[11]=bc11 + sc;
+}
+
+
+/*****************************************************************************
+*
+* function name: count3_4_5_6_7_8_9_10_11
+* description: counts tables 3-11
+* returns:
+* input: quantized spectrum
+* output: bitCount for tables 3-11
+*
+*****************************************************************************/
+
+static void count3_4_5_6_7_8_9_10_11(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+ Word32 t0,t1,t2,t3, i;
+ Word32 bc3_4,bc5_6,bc7_8,bc9_10;
+ Word16 bc11,sc;
+
+ bc3_4=0;
+ bc5_6=0;
+ bc7_8=0;
+ bc9_10=0;
+ bc11=0;
+ sc=0;
+
+ for(i=0;i<width;i+=4){
+
+ t0= values[i+0];
+ t1= values[i+1];
+ t2= values[i+2];
+ t3= values[i+3];
+
+ /*
+ 5,6
+ */
+ bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);
+ bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t2+4][t3+4]);
+
+ t0=ABS(t0);
+ t1=ABS(t1);
+ t2=ABS(t2);
+ t3=ABS(t3);
+
+
+ bc3_4 = bc3_4 + EXPAND(huff_ltab3_4[t0][t1][t2][t3]);
+
+ bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
+ bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t2][t3]);
+
+ bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
+ bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t2][t3]);
+
+ bc11 = bc11 + huff_ltab11[t0][t1];
+ bc11 = bc11 + huff_ltab11[t2][t3];
+
+
+ sc = sc + (t0>0) + (t1>0) + (t2>0) + (t3>0);
+ }
+
+ bitCount[1]=INVALID_BITCOUNT;
+ bitCount[2]=INVALID_BITCOUNT;
+ bitCount[3]=extract_h(bc3_4) + sc;
+ bitCount[4]=extract_l(bc3_4) + sc;
+ bitCount[5]=extract_h(bc5_6);
+ bitCount[6]=extract_l(bc5_6);
+ bitCount[7]=extract_h(bc7_8) + sc;
+ bitCount[8]=extract_l(bc7_8) + sc;
+ bitCount[9]=extract_h(bc9_10) + sc;
+ bitCount[10]=extract_l(bc9_10) + sc;
+ bitCount[11]=bc11 + sc;
+
+}
+
+
+
+/*****************************************************************************
+*
+* function name: count5_6_7_8_9_10_11
+* description: counts tables 5-11
+* returns:
+* input: quantized spectrum
+* output: bitCount for tables 5-11
+*
+*****************************************************************************/
+static void count5_6_7_8_9_10_11(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+
+ Word32 t0,t1,i;
+ Word32 bc5_6,bc7_8,bc9_10;
+ Word16 bc11,sc;
+
+ bc5_6=0;
+ bc7_8=0;
+ bc9_10=0;
+ bc11=0;
+ sc=0;
+
+ for(i=0;i<width;i+=2){
+
+ t0 = values[i+0];
+ t1 = values[i+1];
+
+ bc5_6 = bc5_6 + EXPAND(huff_ltab5_6[t0+4][t1+4]);
+
+ t0=ABS(t0);
+ t1=ABS(t1);
+
+ bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
+ bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
+ bc11 = bc11 + huff_ltab11[t0][t1];
+
+
+ sc = sc + (t0>0) + (t1>0);
+ }
+ bitCount[1]=INVALID_BITCOUNT;
+ bitCount[2]=INVALID_BITCOUNT;
+ bitCount[3]=INVALID_BITCOUNT;
+ bitCount[4]=INVALID_BITCOUNT;
+ bitCount[5]=extract_h(bc5_6);
+ bitCount[6]=extract_l(bc5_6);
+ bitCount[7]=extract_h(bc7_8) + sc;
+ bitCount[8]=extract_l(bc7_8) + sc;
+ bitCount[9]=extract_h(bc9_10) + sc;
+ bitCount[10]=extract_l(bc9_10) + sc;
+ bitCount[11]=bc11 + sc;
+
+}
+
+
+/*****************************************************************************
+*
+* function name: count7_8_9_10_11
+* description: counts tables 7-11
+* returns:
+* input: quantized spectrum
+* output: bitCount for tables 7-11
+*
+*****************************************************************************/
+
+static void count7_8_9_10_11(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+ Word32 t0,t1, i;
+ Word32 bc7_8,bc9_10;
+ Word16 bc11,sc;
+
+ bc7_8=0;
+ bc9_10=0;
+ bc11=0;
+ sc=0;
+
+ for(i=0;i<width;i+=2){
+
+ t0=ABS(values[i+0]);
+ t1=ABS(values[i+1]);
+
+ bc7_8 = bc7_8 + EXPAND(huff_ltab7_8[t0][t1]);
+ bc9_10 = bc9_10 + EXPAND(huff_ltab9_10[t0][t1]);
+ bc11 = bc11 + huff_ltab11[t0][t1];
+
+
+ sc = sc + (t0>0) + (t1>0);
+ }
+ bitCount[1]=INVALID_BITCOUNT;
+ bitCount[2]=INVALID_BITCOUNT;
+ bitCount[3]=INVALID_BITCOUNT;
+ bitCount[4]=INVALID_BITCOUNT;
+ bitCount[5]=INVALID_BITCOUNT;
+ bitCount[6]=INVALID_BITCOUNT;
+ bitCount[7]=extract_h(bc7_8) + sc;
+ bitCount[8]=extract_l(bc7_8) + sc;
+ bitCount[9]=extract_h(bc9_10) + sc;
+ bitCount[10]=extract_l(bc9_10) + sc;
+ bitCount[11]=bc11 + sc;
+
+}
+
+/*****************************************************************************
+*
+* function name: count9_10_11
+* description: counts tables 9-11
+* returns:
+* input: quantized spectrum
+* output: bitCount for tables 9-11
+*
+*****************************************************************************/
+static void count9_10_11(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+
+ Word32 t0,t1,i;
+ Word32 bc9_10;
+ Word16 bc11,sc;
+
+ bc9_10=0;
+ bc11=0;
+ sc=0;
+
+ for(i=0;i<width;i+=2){
+
+ t0=ABS(values[i+0]);
+ t1=ABS(values[i+1]);
+
+
+ bc9_10 += EXPAND(huff_ltab9_10[t0][t1]);
+ bc11 = bc11 + huff_ltab11[t0][t1];
+
+
+ sc = sc + (t0>0) + (t1>0);
+ }
+ bitCount[1]=INVALID_BITCOUNT;
+ bitCount[2]=INVALID_BITCOUNT;
+ bitCount[3]=INVALID_BITCOUNT;
+ bitCount[4]=INVALID_BITCOUNT;
+ bitCount[5]=INVALID_BITCOUNT;
+ bitCount[6]=INVALID_BITCOUNT;
+ bitCount[7]=INVALID_BITCOUNT;
+ bitCount[8]=INVALID_BITCOUNT;
+ bitCount[9]=extract_h(bc9_10) + sc;
+ bitCount[10]=extract_l(bc9_10) + sc;
+ bitCount[11]=bc11 + sc;
+
+}
+
+/*****************************************************************************
+*
+* function name: count11
+* description: counts table 11
+* returns:
+* input: quantized spectrum
+* output: bitCount for table 11
+*
+*****************************************************************************/
+ static void count11(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+ Word32 t0,t1,i;
+ Word16 bc11,sc;
+
+ bc11=0;
+ sc=0;
+ for(i=0;i<width;i+=2){
+ t0=ABS(values[i+0]);
+ t1=ABS(values[i+1]);
+ bc11 = bc11 + huff_ltab11[t0][t1];
+
+
+ sc = sc + (t0>0) + (t1>0);
+ }
+
+ bitCount[1]=INVALID_BITCOUNT;
+ bitCount[2]=INVALID_BITCOUNT;
+ bitCount[3]=INVALID_BITCOUNT;
+ bitCount[4]=INVALID_BITCOUNT;
+ bitCount[5]=INVALID_BITCOUNT;
+ bitCount[6]=INVALID_BITCOUNT;
+ bitCount[7]=INVALID_BITCOUNT;
+ bitCount[8]=INVALID_BITCOUNT;
+ bitCount[9]=INVALID_BITCOUNT;
+ bitCount[10]=INVALID_BITCOUNT;
+ bitCount[11]=bc11 + sc;
+}
+
+/*****************************************************************************
+*
+* function name: countEsc
+* description: counts table 11 (with Esc)
+* returns:
+* input: quantized spectrum
+* output: bitCount for tables 11 (with Esc)
+*
+*****************************************************************************/
+
+static void countEsc(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount)
+{
+ Word32 t0,t1,t00,t01,i;
+ Word16 bc11,ec,sc;
+
+ bc11=0;
+ sc=0;
+ ec=0;
+ for(i=0;i<width;i+=2){
+ t0=ABS(values[i+0]);
+ t1=ABS(values[i+1]);
+
+
+ sc = sc + (t0>0) + (t1>0);
+
+ t00 = min(t0,16);
+ t01 = min(t1,16);
+ bc11 = bc11 + huff_ltab11[t00][t01];
+
+
+ if(t0 >= 16){
+ ec = ec + 5;
+ while(sub(t0=(t0 >> 1), 16) >= 0) {
+ ec = ec + 2;
+ }
+ }
+
+
+ if(t1 >= 16){
+ ec = ec + 5;
+ while(sub(t1=(t1 >> 1), 16) >= 0) {
+ ec = ec + 2;
+ }
+ }
+ }
+ bitCount[1]=INVALID_BITCOUNT;
+ bitCount[2]=INVALID_BITCOUNT;
+ bitCount[3]=INVALID_BITCOUNT;
+ bitCount[4]=INVALID_BITCOUNT;
+ bitCount[5]=INVALID_BITCOUNT;
+ bitCount[6]=INVALID_BITCOUNT;
+ bitCount[7]=INVALID_BITCOUNT;
+ bitCount[8]=INVALID_BITCOUNT;
+ bitCount[9]=INVALID_BITCOUNT;
+ bitCount[10]=INVALID_BITCOUNT;
+ bitCount[11]=bc11 + sc + ec;
+}
+
+
+typedef void (*COUNT_FUNCTION)(const Word16 *values,
+ const Word16 width,
+ Word16 *bitCount);
+
+static COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV+1] =
+ {
+
+ count1_2_3_4_5_6_7_8_9_10_11, /* 0 */
+ count1_2_3_4_5_6_7_8_9_10_11, /* 1 */
+ count3_4_5_6_7_8_9_10_11, /* 2 */
+ count5_6_7_8_9_10_11, /* 3 */
+ count5_6_7_8_9_10_11, /* 4 */
+ count7_8_9_10_11, /* 5 */
+ count7_8_9_10_11, /* 6 */
+ count7_8_9_10_11, /* 7 */
+ count9_10_11, /* 8 */
+ count9_10_11, /* 9 */
+ count9_10_11, /* 10 */
+ count9_10_11, /* 11 */
+ count9_10_11, /* 12 */
+ count11, /* 13 */
+ count11, /* 14 */
+ count11, /* 15 */
+ countEsc /* 16 */
+ };
+
+/*****************************************************************************
+*
+* function name: bitCount
+* description: count bits
+*
+*****************************************************************************/
+Word16 bitCount(const Word16 *values,
+ const Word16 width,
+ Word16 maxVal,
+ Word16 *bitCount)
+{
+ /*
+ check if we can use codebook 0
+ */
+
+ if(maxVal == 0)
+ bitCount[0] = 0;
+ else
+ bitCount[0] = INVALID_BITCOUNT;
+
+ maxVal = min(maxVal, CODE_BOOK_ESC_LAV);
+ countFuncTable[maxVal](values,width,bitCount);
+
+ return(0);
+}
+
+/*****************************************************************************
+*
+* function name: codeValues
+* description: write huffum bits
+*
+*****************************************************************************/
+Word16 codeValues(Word16 *values, Word16 width, Word16 codeBook, HANDLE_BIT_BUF hBitstream)
+{
+
+ Word32 i, t0, t1, t2, t3, t00, t01;
+ Word16 codeWord, codeLength;
+ Word16 sign, signLength;
+
+
+ switch (codeBook) {
+ case CODE_BOOK_ZERO_NO:
+ break;
+
+ case CODE_BOOK_1_NO:
+ for(i=0; i<width; i+=4) {
+ t0 = values[i+0];
+ t1 = values[i+1];
+ t2 = values[i+2];
+ t3 = values[i+3];
+ codeWord = huff_ctab1[t0+1][t1+1][t2+1][t3+1];
+ codeLength = HI_LTAB(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);
+ WriteBits(hBitstream, codeWord, codeLength);
+ }
+ break;
+
+ case CODE_BOOK_2_NO:
+ for(i=0; i<width; i+=4) {
+ t0 = values[i+0];
+ t1 = values[i+1];
+ t2 = values[i+2];
+ t3 = values[i+3];
+ codeWord = huff_ctab2[t0+1][t1+1][t2+1][t3+1];
+ codeLength = LO_LTAB(huff_ltab1_2[t0+1][t1+1][t2+1][t3+1]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ }
+ break;
+
+ case CODE_BOOK_3_NO:
+ for(i=0; i<width; i+=4) {
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ t2 = values[i+2];
+
+ if(t2 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t2 < 0){
+ sign|=1;
+ t2=-t2;
+ }
+ }
+ t3 = values[i+3];
+ if(t3 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t3 < 0){
+ sign|=1;
+ t3=-t3;
+ }
+ }
+
+ codeWord = huff_ctab3[t0][t1][t2][t3];
+ codeLength = HI_LTAB(huff_ltab3_4[t0][t1][t2][t3]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+ }
+ break;
+
+ case CODE_BOOK_4_NO:
+ for(i=0; i<width; i+=4) {
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ t2 = values[i+2];
+
+ if(t2 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t2 < 0){
+ sign|=1;
+ t2=-t2;
+ }
+ }
+ t3 = values[i+3];
+
+ if(t3 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t3 < 0){
+ sign|=1;
+ t3=-t3;
+ }
+ }
+ codeWord = huff_ctab4[t0][t1][t2][t3];
+ codeLength = LO_LTAB(huff_ltab3_4[t0][t1][t2][t3]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+ }
+ break;
+
+ case CODE_BOOK_5_NO:
+ for(i=0; i<width; i+=2) {
+ t0 = values[i+0];
+ t1 = values[i+1];
+ codeWord = huff_ctab5[t0+4][t1+4];
+ codeLength = HI_LTAB(huff_ltab5_6[t0+4][t1+4]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ }
+ break;
+
+ case CODE_BOOK_6_NO:
+ for(i=0; i<width; i+=2) {
+ t0 = values[i+0];
+ t1 = values[i+1];
+ codeWord = huff_ctab6[t0+4][t1+4];
+ codeLength = LO_LTAB(huff_ltab5_6[t0+4][t1+4]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ }
+ break;
+
+ case CODE_BOOK_7_NO:
+ for(i=0; i<width; i+=2){
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ codeWord = huff_ctab7[t0][t1];
+ codeLength = HI_LTAB(huff_ltab7_8[t0][t1]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+ }
+ break;
+
+ case CODE_BOOK_8_NO:
+ for(i=0; i<width; i+=2) {
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ codeWord = huff_ctab8[t0][t1];
+ codeLength = LO_LTAB(huff_ltab7_8[t0][t1]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+ }
+ break;
+
+ case CODE_BOOK_9_NO:
+ for(i=0; i<width; i+=2) {
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ codeWord = huff_ctab9[t0][t1];
+ codeLength = HI_LTAB(huff_ltab9_10[t0][t1]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+ }
+ break;
+
+ case CODE_BOOK_10_NO:
+ for(i=0; i<width; i+=2) {
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ codeWord = huff_ctab10[t0][t1];
+ codeLength = LO_LTAB(huff_ltab9_10[t0][t1]);
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+ }
+ break;
+
+ case CODE_BOOK_ESC_NO:
+ for(i=0; i<width; i+=2) {
+ sign=0;
+ signLength=0;
+ t0 = values[i+0];
+
+ if(t0 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t0 < 0){
+ sign|=1;
+ t0=-t0;
+ }
+ }
+
+ t1 = values[i+1];
+
+ if(t1 != 0){
+ signLength = signLength + 1;
+ sign = sign << 1;
+
+ if(t1 < 0){
+ sign|=1;
+ t1=-t1;
+ }
+ }
+ t00 = min(t0,16);
+ t01 = min(t1,16);
+
+ codeWord = huff_ctab11[t00][t01];
+ codeLength = huff_ltab11[t00][t01];
+ WriteBits(hBitstream,codeWord,codeLength);
+ WriteBits(hBitstream,sign,signLength);
+
+ if(t0 >= 16){
+ Word16 n, p;
+ n=0;
+ p=t0;
+ while(sub(p=(p >> 1), 16) >= 0){
+
+ WriteBits(hBitstream,1,1);
+ n = n + 1;
+ }
+ WriteBits(hBitstream,0,1);
+ n = n + 4;
+ WriteBits(hBitstream,(t0 - (1 << n)),n);
+ }
+
+ if(t1 >= 16){
+ Word16 n, p;
+ n=0;
+ p=t1;
+ while(sub(p=(p >> 1), 16) >= 0){
+
+ WriteBits(hBitstream,1,1);
+ n = n + 1;
+ }
+ WriteBits(hBitstream,0,1);
+ n = n + 4;
+ WriteBits(hBitstream,(t1 - (1 << n)),n);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ return(0);
+}
+
+Word16 bitCountScalefactorDelta(Word16 delta)
+{
+ return(huff_ltabscf[delta+CODE_BOOK_SCF_LAV]);
+}
+
+Word16 codeScalefactorDelta(Word16 delta, HANDLE_BIT_BUF hBitstream)
+{
+ Word32 codeWord;
+ Word16 codeLength;
+
+
+ if(delta > CODE_BOOK_SCF_LAV || delta < -CODE_BOOK_SCF_LAV)
+ return(1);
+
+ codeWord = huff_ctabscf[delta + CODE_BOOK_SCF_LAV];
+ codeLength = huff_ltabscf[delta + CODE_BOOK_SCF_LAV];
+ WriteBits(hBitstream,codeWord,codeLength);
+ return(0);
+}
diff --git a/media/libstagefright/codecs/aacenc/src/bitbuffer.c b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
new file mode 100644
index 0000000..3248f0b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bitbuffer.c
@@ -0,0 +1,172 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bitbuffer.c
+
+ Content: Bit Buffer Management functions
+
+*******************************************************************************/
+
+#include "bitbuffer.h"
+
+/*****************************************************************************
+*
+* function name: updateBitBufWordPtr
+* description: update Bit Buffer pointer
+*
+*****************************************************************************/
+static void updateBitBufWordPtr(HANDLE_BIT_BUF hBitBuf,
+ UWord8 **pBitBufWord,
+ Word16 cnt)
+{
+ *pBitBufWord += cnt;
+
+
+ if(*pBitBufWord > hBitBuf->pBitBufEnd) {
+ *pBitBufWord -= (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
+ }
+
+ if(*pBitBufWord < hBitBuf->pBitBufBase) {
+ *pBitBufWord += (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: CreateBitBuffer
+* description: create and init Bit Buffer Management
+*
+*****************************************************************************/
+HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
+ UWord8 *pBitBufBase,
+ Word16 bitBufSize)
+{
+ assert(bitBufSize*8 <= 32768);
+
+ hBitBuf->pBitBufBase = pBitBufBase;
+ hBitBuf->pBitBufEnd = pBitBufBase + bitBufSize - 1;
+
+ hBitBuf->pWriteNext = pBitBufBase;
+
+ hBitBuf->cache = 0;
+
+ hBitBuf->wBitPos = 0;
+ hBitBuf->cntBits = 0;
+
+ hBitBuf->size = (bitBufSize << 3);
+ hBitBuf->isValid = 1;
+
+ return hBitBuf;
+}
+
+/*****************************************************************************
+*
+* function name: DeleteBitBuffer
+* description: uninit Bit Buffer Management
+*
+*****************************************************************************/
+void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf)
+{
+ if(*hBitBuf)
+ (*hBitBuf)->isValid = 0;
+ *hBitBuf = NULL;
+}
+
+/*****************************************************************************
+*
+* function name: ResetBitBuf
+* description: reset Bit Buffer Management
+*
+*****************************************************************************/
+void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
+ UWord8 *pBitBufBase,
+ Word16 bitBufSize)
+{
+ hBitBuf->pBitBufBase = pBitBufBase;
+ hBitBuf->pBitBufEnd = pBitBufBase + bitBufSize - 1;
+
+
+ hBitBuf->pWriteNext = pBitBufBase;
+
+ hBitBuf->wBitPos = 0;
+ hBitBuf->cntBits = 0;
+
+ hBitBuf->cache = 0;
+}
+
+/*****************************************************************************
+*
+* function name: CopyBitBuf
+* description: copy Bit Buffer Management
+*
+*****************************************************************************/
+void CopyBitBuf(HANDLE_BIT_BUF hBitBufSrc,
+ HANDLE_BIT_BUF hBitBufDst)
+{
+ *hBitBufDst = *hBitBufSrc;
+}
+
+/*****************************************************************************
+*
+* function name: GetBitsAvail
+* description: get available bits
+*
+*****************************************************************************/
+Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf)
+{
+ return hBitBuf->cntBits;
+}
+
+/*****************************************************************************
+*
+* function name: WriteBits
+* description: write bits to the buffer
+*
+*****************************************************************************/
+Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
+ Word32 writeValue,
+ Word16 noBitsToWrite)
+{
+ Word16 wBitPos;
+
+ assert(noBitsToWrite <= (Word16)sizeof(Word32)*8);
+
+ if(noBitsToWrite == 0)
+ return noBitsToWrite;
+
+ hBitBuf->cntBits += noBitsToWrite;
+
+ wBitPos = hBitBuf->wBitPos;
+ wBitPos += noBitsToWrite;
+ writeValue <<= 32 - wBitPos;
+ writeValue |= hBitBuf->cache;
+
+ while (wBitPos >= 8)
+ {
+ UWord8 tmp;
+ tmp = (UWord8)((writeValue >> 24) & 0xFF);
+
+ *hBitBuf->pWriteNext++ = tmp;
+ writeValue <<= 8;
+ wBitPos -= 8;
+ }
+
+ hBitBuf->wBitPos = wBitPos;
+ hBitBuf->cache = writeValue;
+
+ return noBitsToWrite;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/bitenc.c b/media/libstagefright/codecs/aacenc/src/bitenc.c
new file mode 100644
index 0000000..588c2da
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/bitenc.c
@@ -0,0 +1,690 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bitenc.c
+
+ Content: Bitstream encoder functions
+
+*******************************************************************************/
+
+#include "bitenc.h"
+#include "bit_cnt.h"
+#include "dyn_bits.h"
+#include "qc_data.h"
+#include "interface.h"
+
+
+static const Word16 globalGainOffset = 100;
+static const Word16 icsReservedBit = 0;
+
+
+/*****************************************************************************
+*
+* function name: encodeSpectralData
+* description: encode spectral data
+* returns: spectral bits used
+*
+*****************************************************************************/
+static Word32 encodeSpectralData(Word16 *sfbOffset,
+ SECTION_DATA *sectionData,
+ Word16 *quantSpectrum,
+ HANDLE_BIT_BUF hBitStream)
+{
+ Word16 i,sfb;
+ Word16 dbgVal;
+ SECTION_INFO* psectioninfo;
+ dbgVal = GetBitsAvail(hBitStream);
+
+ for(i=0; i<sectionData->noOfSections; i++) {
+ psectioninfo = &(sectionData->sectionInfo[i]);
+ /*
+ huffencode spectral data for this section
+ */
+ for(sfb=psectioninfo->sfbStart;
+ sfb<psectioninfo->sfbStart+psectioninfo->sfbCnt;
+ sfb++) {
+ codeValues(quantSpectrum+sfbOffset[sfb],
+ sfbOffset[sfb+1] - sfbOffset[sfb],
+ psectioninfo->codeBook,
+ hBitStream);
+ }
+ }
+
+ return(GetBitsAvail(hBitStream)-dbgVal);
+}
+
+/*****************************************************************************
+*
+* function name:encodeGlobalGain
+* description: encodes Global Gain (common scale factor)
+* returns: none
+*
+*****************************************************************************/
+static void encodeGlobalGain(Word16 globalGain,
+ Word16 logNorm,
+ Word16 scalefac,
+ HANDLE_BIT_BUF hBitStream)
+{
+ WriteBits(hBitStream, ((globalGain - scalefac) + globalGainOffset-(logNorm << 2)), 8);
+}
+
+
+/*****************************************************************************
+*
+* function name:encodeIcsInfo
+* description: encodes Ics Info
+* returns: none
+*
+*****************************************************************************/
+
+static void encodeIcsInfo(Word16 blockType,
+ Word16 windowShape,
+ Word16 groupingMask,
+ SECTION_DATA *sectionData,
+ HANDLE_BIT_BUF hBitStream)
+{
+ WriteBits(hBitStream,icsReservedBit,1);
+ WriteBits(hBitStream,blockType,2);
+ WriteBits(hBitStream,windowShape,1);
+
+
+ switch(blockType){
+ case LONG_WINDOW:
+ case START_WINDOW:
+ case STOP_WINDOW:
+ WriteBits(hBitStream,sectionData->maxSfbPerGroup,6);
+
+ /* No predictor data present */
+ WriteBits(hBitStream, 0, 1);
+ break;
+
+ case SHORT_WINDOW:
+ WriteBits(hBitStream,sectionData->maxSfbPerGroup,4);
+
+ /*
+ Write grouping bits
+ */
+ WriteBits(hBitStream,groupingMask,TRANS_FAC-1);
+ break;
+ }
+}
+
+/*****************************************************************************
+*
+* function name: encodeSectionData
+* description: encode section data (common Huffman codebooks for adjacent
+* SFB's)
+* returns: none
+*
+*****************************************************************************/
+static Word32 encodeSectionData(SECTION_DATA *sectionData,
+ HANDLE_BIT_BUF hBitStream)
+{
+ Word16 sectEscapeVal=0,sectLenBits=0;
+ Word16 sectLen;
+ Word16 i;
+ Word16 dbgVal=GetBitsAvail(hBitStream);
+
+
+
+ switch(sectionData->blockType)
+ {
+ case LONG_WINDOW:
+ case START_WINDOW:
+ case STOP_WINDOW:
+ sectEscapeVal = SECT_ESC_VAL_LONG;
+ sectLenBits = SECT_BITS_LONG;
+ break;
+
+ case SHORT_WINDOW:
+ sectEscapeVal = SECT_ESC_VAL_SHORT;
+ sectLenBits = SECT_BITS_SHORT;
+ break;
+ }
+
+ for(i=0;i<sectionData->noOfSections;i++) {
+ WriteBits(hBitStream,sectionData->sectionInfo[i].codeBook,4);
+ sectLen = sectionData->sectionInfo[i].sfbCnt;
+
+ while(sectLen >= sectEscapeVal) {
+
+ WriteBits(hBitStream,sectEscapeVal,sectLenBits);
+ sectLen = sectLen - sectEscapeVal;
+ }
+ WriteBits(hBitStream,sectLen,sectLenBits);
+ }
+ return(GetBitsAvail(hBitStream)-dbgVal);
+}
+
+/*****************************************************************************
+*
+* function name: encodeScaleFactorData
+* description: encode DPCM coded scale factors
+* returns: none
+*
+*****************************************************************************/
+static Word32 encodeScaleFactorData(UWord16 *maxValueInSfb,
+ SECTION_DATA *sectionData,
+ Word16 *scalefac,
+ HANDLE_BIT_BUF hBitStream)
+{
+ Word16 i,j,lastValScf,deltaScf;
+ Word16 dbgVal = GetBitsAvail(hBitStream);
+ SECTION_INFO* psectioninfo;
+
+ lastValScf=scalefac[sectionData->firstScf];
+
+ for(i=0;i<sectionData->noOfSections;i++){
+ psectioninfo = &(sectionData->sectionInfo[i]);
+ if (psectioninfo->codeBook != CODE_BOOK_ZERO_NO){
+ for (j=psectioninfo->sfbStart;
+ j<psectioninfo->sfbStart+psectioninfo->sfbCnt; j++){
+
+ if(maxValueInSfb[j] == 0) {
+ deltaScf = 0;
+ }
+ else {
+ deltaScf = lastValScf - scalefac[j];
+ lastValScf = scalefac[j];
+ }
+
+ if(codeScalefactorDelta(deltaScf,hBitStream)){
+ return(1);
+ }
+ }
+ }
+
+ }
+ return(GetBitsAvail(hBitStream)-dbgVal);
+}
+
+/*****************************************************************************
+*
+* function name:encodeMsInfo
+* description: encodes MS-Stereo Info
+* returns: none
+*
+*****************************************************************************/
+static void encodeMSInfo(Word16 sfbCnt,
+ Word16 grpSfb,
+ Word16 maxSfb,
+ Word16 msDigest,
+ Word16 *jsFlags,
+ HANDLE_BIT_BUF hBitStream)
+{
+ Word16 sfb, sfbOff;
+
+
+ switch(msDigest)
+ {
+ case MS_NONE:
+ WriteBits(hBitStream,SI_MS_MASK_NONE,2);
+ break;
+
+ case MS_ALL:
+ WriteBits(hBitStream,SI_MS_MASK_ALL,2);
+ break;
+
+ case MS_SOME:
+ WriteBits(hBitStream,SI_MS_MASK_SOME,2);
+ for(sfbOff = 0; sfbOff < sfbCnt; sfbOff+=grpSfb) {
+ for(sfb=0; sfb<maxSfb; sfb++) {
+
+ if(jsFlags[sfbOff+sfb] & MS_ON) {
+ WriteBits(hBitStream,1,1);
+ }
+ else{
+ WriteBits(hBitStream,0,1);
+ }
+ }
+ }
+ break;
+ }
+
+}
+
+/*****************************************************************************
+*
+* function name: encodeTnsData
+* description: encode TNS data (filter order, coeffs, ..)
+* returns: none
+*
+*****************************************************************************/
+static void encodeTnsData(TNS_INFO tnsInfo,
+ Word16 blockType,
+ HANDLE_BIT_BUF hBitStream) {
+ Word16 i,k;
+ Flag tnsPresent;
+ Word16 numOfWindows;
+ Word16 coefBits;
+ Flag isShort;
+
+
+ if (blockType==2) {
+ isShort = 1;
+ numOfWindows = TRANS_FAC;
+ }
+ else {
+ isShort = 0;
+ numOfWindows = 1;
+ }
+
+ tnsPresent=0;
+ for (i=0; i<numOfWindows; i++) {
+
+ if (tnsInfo.tnsActive[i]) {
+ tnsPresent=1;
+ }
+ }
+
+ if (tnsPresent==0) {
+ WriteBits(hBitStream,0,1);
+ }
+ else{ /* there is data to be written*/
+ WriteBits(hBitStream,1,1); /*data_present */
+ for (i=0; i<numOfWindows; i++) {
+
+ WriteBits(hBitStream,tnsInfo.tnsActive[i],(isShort?1:2));
+
+ if (tnsInfo.tnsActive[i]) {
+
+ WriteBits(hBitStream,((tnsInfo.coefRes[i] - 4)==0?1:0),1);
+
+ WriteBits(hBitStream,tnsInfo.length[i],(isShort?4:6));
+
+ WriteBits(hBitStream,tnsInfo.order[i],(isShort?3:5));
+
+ if (tnsInfo.order[i]){
+ WriteBits(hBitStream, FILTER_DIRECTION, 1);
+
+ if(tnsInfo.coefRes[i] == 4) {
+ coefBits = 3;
+ for(k=0; k<tnsInfo.order[i]; k++) {
+
+ if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 3 ||
+ tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -4) {
+ coefBits = 4;
+ break;
+ }
+ }
+ }
+ else {
+ coefBits = 2;
+ for(k=0; k<tnsInfo.order[i]; k++) {
+
+ if (tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] > 1 ||
+ tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] < -2) {
+ coefBits = 3;
+ break;
+ }
+ }
+ }
+ WriteBits(hBitStream, tnsInfo.coefRes[i] - coefBits, 1); /*coef_compres*/
+ for (k=0; k<tnsInfo.order[i]; k++ ) {
+ static const Word16 rmask[] = {0,1,3,7,15};
+
+ WriteBits(hBitStream,tnsInfo.coef[i*TNS_MAX_ORDER_SHORT+k] & rmask[coefBits],coefBits);
+ }
+ }
+ }
+ }
+ }
+
+}
+
+/*****************************************************************************
+*
+* function name: encodeGainControlData
+* description: unsupported
+* returns: none
+*
+*****************************************************************************/
+static void encodeGainControlData(HANDLE_BIT_BUF hBitStream)
+{
+ WriteBits(hBitStream,0,1);
+}
+
+/*****************************************************************************
+*
+* function name: encodePulseData
+* description: not supported yet (dummy)
+* returns: none
+*
+*****************************************************************************/
+static void encodePulseData(HANDLE_BIT_BUF hBitStream)
+{
+ WriteBits(hBitStream,0,1);
+}
+
+
+/*****************************************************************************
+*
+* function name: WriteIndividualChannelStream
+* description: management of write process of individual channel stream
+* returns: none
+*
+*****************************************************************************/
+static void
+writeIndividualChannelStream(Flag commonWindow,
+ Word16 mdctScale,
+ Word16 windowShape,
+ Word16 groupingMask,
+ Word16 *sfbOffset,
+ Word16 scf[],
+ UWord16 *maxValueInSfb,
+ Word16 globalGain,
+ Word16 quantSpec[],
+ SECTION_DATA *sectionData,
+ HANDLE_BIT_BUF hBitStream,
+ TNS_INFO tnsInfo)
+{
+ Word16 logNorm;
+
+ logNorm = LOG_NORM_PCM - (mdctScale + 1);
+
+ encodeGlobalGain(globalGain, logNorm,scf[sectionData->firstScf], hBitStream);
+
+
+ if(!commonWindow) {
+ encodeIcsInfo(sectionData->blockType, windowShape, groupingMask, sectionData, hBitStream);
+ }
+
+ encodeSectionData(sectionData, hBitStream);
+
+ encodeScaleFactorData(maxValueInSfb,
+ sectionData,
+ scf,
+ hBitStream);
+
+ encodePulseData(hBitStream);
+
+ encodeTnsData(tnsInfo, sectionData->blockType, hBitStream);
+
+ encodeGainControlData(hBitStream);
+
+ encodeSpectralData(sfbOffset,
+ sectionData,
+ quantSpec,
+ hBitStream);
+
+}
+
+/*****************************************************************************
+*
+* function name: writeSingleChannelElement
+* description: write single channel element to bitstream
+* returns: none
+*
+*****************************************************************************/
+static Word16 writeSingleChannelElement(Word16 instanceTag,
+ Word16 *sfbOffset,
+ QC_OUT_CHANNEL* qcOutChannel,
+ HANDLE_BIT_BUF hBitStream,
+ TNS_INFO tnsInfo)
+{
+ WriteBits(hBitStream,ID_SCE,3);
+ WriteBits(hBitStream,instanceTag,4);
+ writeIndividualChannelStream(0,
+ qcOutChannel->mdctScale,
+ qcOutChannel->windowShape,
+ qcOutChannel->groupingMask,
+ sfbOffset,
+ qcOutChannel->scf,
+ qcOutChannel->maxValueInSfb,
+ qcOutChannel->globalGain,
+ qcOutChannel->quantSpec,
+ &(qcOutChannel->sectionData),
+ hBitStream,
+ tnsInfo
+ );
+ return(0);
+}
+
+
+
+/*****************************************************************************
+*
+* function name: writeChannelPairElement
+* description:
+* returns: none
+*
+*****************************************************************************/
+static Word16 writeChannelPairElement(Word16 instanceTag,
+ Word16 msDigest,
+ Word16 msFlags[MAX_GROUPED_SFB],
+ Word16 *sfbOffset[2],
+ QC_OUT_CHANNEL qcOutChannel[2],
+ HANDLE_BIT_BUF hBitStream,
+ TNS_INFO tnsInfo[2])
+{
+ WriteBits(hBitStream,ID_CPE,3);
+ WriteBits(hBitStream,instanceTag,4);
+ WriteBits(hBitStream,1,1); /* common window */
+
+ encodeIcsInfo(qcOutChannel[0].sectionData.blockType,
+ qcOutChannel[0].windowShape,
+ qcOutChannel[0].groupingMask,
+ &(qcOutChannel[0].sectionData),
+ hBitStream);
+
+ encodeMSInfo(qcOutChannel[0].sectionData.sfbCnt,
+ qcOutChannel[0].sectionData.sfbPerGroup,
+ qcOutChannel[0].sectionData.maxSfbPerGroup,
+ msDigest,
+ msFlags,
+ hBitStream);
+
+ writeIndividualChannelStream(1,
+ qcOutChannel[0].mdctScale,
+ qcOutChannel[0].windowShape,
+ qcOutChannel[0].groupingMask,
+ sfbOffset[0],
+ qcOutChannel[0].scf,
+ qcOutChannel[0].maxValueInSfb,
+ qcOutChannel[0].globalGain,
+ qcOutChannel[0].quantSpec,
+ &(qcOutChannel[0].sectionData),
+ hBitStream,
+ tnsInfo[0]);
+
+ writeIndividualChannelStream(1,
+ qcOutChannel[1].mdctScale,
+ qcOutChannel[1].windowShape,
+ qcOutChannel[1].groupingMask,
+ sfbOffset[1],
+ qcOutChannel[1].scf,
+ qcOutChannel[1].maxValueInSfb,
+ qcOutChannel[1].globalGain,
+ qcOutChannel[1].quantSpec,
+ &(qcOutChannel[1].sectionData),
+ hBitStream,
+ tnsInfo[1]);
+
+ return(0);
+}
+
+
+
+/*****************************************************************************
+*
+* function name: writeFillElement
+* description: write fill elements to bitstream
+* returns: none
+*
+*****************************************************************************/
+static void writeFillElement( const UWord8 *ancBytes,
+ Word16 totFillBits,
+ HANDLE_BIT_BUF hBitStream)
+{
+ Word16 i;
+ Word16 cnt,esc_count;
+
+ /*
+ Write fill Element(s):
+ amount of a fill element can be 7+X*8 Bits, X element of [0..270]
+ */
+
+ while(totFillBits >= (3+4)) {
+ cnt = min(((totFillBits - (3+4)) >> 3), ((1<<4)-1));
+
+ WriteBits(hBitStream,ID_FIL,3);
+ WriteBits(hBitStream,cnt,4);
+
+ totFillBits = totFillBits - (3+4);
+
+
+ if ((cnt == (1<<4)-1)) {
+
+ esc_count = min( ((totFillBits >> 3) - ((1<<4)-1)), (1<<8)-1);
+ WriteBits(hBitStream,esc_count,8);
+ totFillBits = (totFillBits - 8);
+ cnt = cnt + (esc_count - 1);
+ }
+
+ for(i=0;i<cnt;i++) {
+
+ if(ancBytes)
+ WriteBits(hBitStream, *ancBytes++,8);
+ else
+ WriteBits(hBitStream,0,8);
+ totFillBits = totFillBits - 8;
+ }
+ }
+}
+
+/*****************************************************************************
+*
+* function name: WriteBitStream
+* description: main function of write bitsteam process
+* returns: 0 if success
+*
+*****************************************************************************/
+Word16 WriteBitstream (HANDLE_BIT_BUF hBitStream,
+ ELEMENT_INFO elInfo,
+ QC_OUT *qcOut,
+ PSY_OUT *psyOut,
+ Word16 *globUsedBits,
+ const UWord8 *ancBytes,
+ Word16 sampindex
+ ) /* returns error code */
+{
+ Word16 bitMarkUp;
+ Word16 elementUsedBits;
+ Word16 frameBits=0;
+
+ /* struct bitbuffer bsWriteCopy; */
+ bitMarkUp = GetBitsAvail(hBitStream);
+ if(qcOut->qcElement.adtsUsed) /* write adts header*/
+ {
+ WriteBits(hBitStream, 0xFFF, 12); /* 12 bit Syncword */
+ WriteBits(hBitStream, 1, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */
+ WriteBits(hBitStream, 0, 2); /* layer == 0 */
+ WriteBits(hBitStream, 1, 1); /* protection absent */
+ WriteBits(hBitStream, 1, 2); /* profile */
+ WriteBits(hBitStream, sampindex, 4); /* sampling rate */
+ WriteBits(hBitStream, 0, 1); /* private bit */
+ WriteBits(hBitStream, elInfo.nChannelsInEl, 3); /* ch. config (must be > 0) */
+ /* simply using numChannels only works for
+ 6 channels or less, else a channel
+ configuration should be written */
+ WriteBits(hBitStream, 0, 1); /* original/copy */
+ WriteBits(hBitStream, 0, 1); /* home */
+
+ /* Variable ADTS header */
+ WriteBits(hBitStream, 0, 1); /* copyr. id. bit */
+ WriteBits(hBitStream, 0, 1); /* copyr. id. start */
+ WriteBits(hBitStream, *globUsedBits >> 3, 13);
+ WriteBits(hBitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */
+ WriteBits(hBitStream, 0, 2); /* raw data blocks (0+1=1) */
+ }
+
+ *globUsedBits=0;
+
+ {
+
+ Word16 *sfbOffset[2];
+ TNS_INFO tnsInfo[2];
+ elementUsedBits = 0;
+
+ switch (elInfo.elType) {
+
+ case ID_SCE: /* single channel */
+ sfbOffset[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
+ tnsInfo[0] = psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
+
+ writeSingleChannelElement(elInfo.instanceTag,
+ sfbOffset[0],
+ &qcOut->qcChannel[elInfo.ChannelIndex[0]],
+ hBitStream,
+ tnsInfo[0]);
+ break;
+
+ case ID_CPE: /* channel pair */
+ {
+ Word16 msDigest;
+ Word16 *msFlags = psyOut->psyOutElement.toolsInfo.msMask;
+ msDigest = psyOut->psyOutElement.toolsInfo.msDigest;
+ sfbOffset[0] =
+ psyOut->psyOutChannel[elInfo.ChannelIndex[0]].sfbOffsets;
+ sfbOffset[1] =
+ psyOut->psyOutChannel[elInfo.ChannelIndex[1]].sfbOffsets;
+
+ tnsInfo[0]=
+ psyOut->psyOutChannel[elInfo.ChannelIndex[0]].tnsInfo;
+ tnsInfo[1]=
+ psyOut->psyOutChannel[elInfo.ChannelIndex[1]].tnsInfo;
+ writeChannelPairElement(elInfo.instanceTag,
+ msDigest,
+ msFlags,
+ sfbOffset,
+ &qcOut->qcChannel[elInfo.ChannelIndex[0]],
+ hBitStream,
+ tnsInfo);
+ }
+ break;
+
+ default:
+ return(1);
+
+ } /* switch */
+
+ elementUsedBits = elementUsedBits - bitMarkUp;
+ bitMarkUp = GetBitsAvail(hBitStream);
+ frameBits = frameBits + elementUsedBits + bitMarkUp;
+
+ }
+
+ writeFillElement(NULL,
+ qcOut->totFillBits,
+ hBitStream);
+
+ WriteBits(hBitStream,ID_END,3);
+
+ /* byte alignement */
+ WriteBits(hBitStream,0, (8 - (hBitStream->cntBits & 7)) & 7);
+
+ *globUsedBits = *globUsedBits- bitMarkUp;
+ bitMarkUp = GetBitsAvail(hBitStream);
+ *globUsedBits = *globUsedBits + bitMarkUp;
+ frameBits = frameBits + *globUsedBits;
+
+
+ if (frameBits != (qcOut->totStaticBitsUsed+qcOut->totDynBitsUsed + qcOut->totAncBitsUsed +
+ qcOut->totFillBits + qcOut->alignBits)) {
+ return(-1);
+ }
+ return(0);
+}
diff --git a/media/libstagefright/codecs/aacenc/src/block_switch.c b/media/libstagefright/codecs/aacenc/src/block_switch.c
new file mode 100644
index 0000000..c0054f7
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/block_switch.c
@@ -0,0 +1,431 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: block_switch.c
+
+ Content: Block switching functions
+
+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "psy_const.h"
+#include "block_switch.h"
+
+
+#define ENERGY_SHIFT (8 - 1)
+
+/**************** internal function prototypes ***********/
+static Word16
+IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[]);
+
+static Word32
+SrchMaxWithIndex(const Word32 *in, Word16 *index, Word16 n);
+
+
+Word32
+CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+ Word16 *timeSignal,
+ Word16 chIncrement,
+ Word16 windowLen);
+
+
+
+/****************** Constants *****************************/
+
+
+/*
+ IIR high pass coeffs
+*/
+Word32 hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = {
+ 0xbec8b439, 0x609d4952 /* -0.5095f, 0.7548f */
+};
+
+static const Word32 accWindowNrgFac = 0x26666666; /* factor for accumulating filtered window energies 0.3 */
+static const Word32 oneMinusAccWindowNrgFac = 0x5999999a; /* 0.7 */
+static const Word32 invAttackRatioHighBr = 0x0ccccccd; /* inverted lower ratio limit for attacks 0.1*/
+static const Word32 invAttackRatioLowBr = 0x072b020c; /* 0.056 */
+static const Word32 minAttackNrg = 0x00001e84; /* minimum energy for attacks 1e+6 */
+
+
+/****************** Routines ****************************/
+
+
+/*****************************************************************************
+*
+* function name: InitBlockSwitching
+* description: init Block Switching parameter.
+* returns: TRUE if success
+*
+**********************************************************************************/
+Word16 InitBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+ const Word32 bitRate, const Word16 nChannels)
+{
+ /* select attackRatio */
+
+ if ((sub(nChannels,1)==0 && L_sub(bitRate, 24000) > 0) ||
+ (sub(nChannels,1)>0 && bitRate > (nChannels * 16000))) {
+ blockSwitchingControl->invAttackRatio = invAttackRatioHighBr;
+ }
+ else {
+ blockSwitchingControl->invAttackRatio = invAttackRatioLowBr;
+ }
+
+ return(TRUE);
+}
+
+static Word16 suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = {
+ /* Attack in Window 0 */ {1, 3, 3, 1},
+ /* Attack in Window 1 */ {1, 1, 3, 3},
+ /* Attack in Window 2 */ {2, 1, 3, 2},
+ /* Attack in Window 3 */ {3, 1, 3, 1},
+ /* Attack in Window 4 */ {3, 1, 1, 3},
+ /* Attack in Window 5 */ {3, 2, 1, 2},
+ /* Attack in Window 6 */ {3, 3, 1, 1},
+ /* Attack in Window 7 */ {3, 3, 1, 1}
+};
+
+/*****************************************************************************
+*
+* function name: BlockSwitching
+* description: detect this frame whether there is an attack
+* returns: TRUE if success
+*
+**********************************************************************************/
+Word16 BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+ Word16 *timeSignal,
+ Word32 sampleRate,
+ Word16 chIncrement)
+{
+ Word32 i, w;
+ Word32 enM1, enMax;
+
+ /* Reset grouping info */
+ for (i=0; i<TRANS_FAC; i++) {
+ blockSwitchingControl->groupLen[i] = 0;
+ }
+
+
+ /* Search for position and amplitude of attack in last frame (1 windows delay) */
+ blockSwitchingControl->maxWindowNrg = SrchMaxWithIndex( &blockSwitchingControl->windowNrg[0][BLOCK_SWITCH_WINDOWS-1],
+ &blockSwitchingControl->attackIndex,
+ BLOCK_SWITCH_WINDOWS);
+
+ blockSwitchingControl->attackIndex = blockSwitchingControl->lastAttackIndex;
+
+ /* Set grouping info */
+ blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS;
+
+ for (i=0; i<MAX_NO_OF_GROUPS; i++) {
+ blockSwitchingControl->groupLen[i] = suggestedGroupingTable[blockSwitchingControl->attackIndex][i];
+ }
+
+ /* if the samplerate is less than 16000, it should be all the short block, avoid pre&post echo */
+ if(sampleRate >= 16000) {
+ /* Save current window energy as last window energy */
+ for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
+ blockSwitchingControl->windowNrg[0][w] = blockSwitchingControl->windowNrg[1][w];
+ blockSwitchingControl->windowNrgF[0][w] = blockSwitchingControl->windowNrgF[1][w];
+ }
+
+
+ /* Calculate unfiltered and filtered energies in subwindows and combine to segments */
+ CalcWindowEnergy(blockSwitchingControl, timeSignal, chIncrement, BLOCK_SWITCH_WINDOW_LEN);
+
+ /* reset attack */
+ blockSwitchingControl->attack = FALSE;
+
+ enMax = 0;
+ enM1 = blockSwitchingControl->windowNrgF[0][BLOCK_SWITCH_WINDOWS-1];
+
+ for (w=0; w<BLOCK_SWITCH_WINDOWS; w++) {
+ Word32 enM1_Tmp, accWindowNrg_Tmp, windowNrgF_Tmp;
+ Word16 enM1_Shf, accWindowNrg_Shf, windowNrgF_Shf;
+
+ accWindowNrg_Shf = norm_l(blockSwitchingControl->accWindowNrg);
+ enM1_Shf = norm_l(enM1);
+ windowNrgF_Shf = norm_l(blockSwitchingControl->windowNrgF[1][w]);
+
+ accWindowNrg_Tmp = blockSwitchingControl->accWindowNrg << accWindowNrg_Shf;
+ enM1_Tmp = enM1 << enM1_Shf;
+ windowNrgF_Tmp = blockSwitchingControl->windowNrgF[1][w] << windowNrgF_Shf;
+
+ /* a sliding average of the previous energies */
+ blockSwitchingControl->accWindowNrg = (fixmul(oneMinusAccWindowNrgFac, accWindowNrg_Tmp) >> accWindowNrg_Shf) +
+ (fixmul(accWindowNrgFac, enM1_Tmp) >> enM1_Shf);
+
+
+ /* if the energy with the ratio is bigger than the average, and the attack and short block */
+ if ((fixmul(windowNrgF_Tmp, blockSwitchingControl->invAttackRatio) >> windowNrgF_Shf) >
+ blockSwitchingControl->accWindowNrg ) {
+ blockSwitchingControl->attack = TRUE;
+ blockSwitchingControl->lastAttackIndex = w;
+ }
+ enM1 = blockSwitchingControl->windowNrgF[1][w];
+ enMax = max(enMax, enM1);
+ }
+
+ if (enMax < minAttackNrg) {
+ blockSwitchingControl->attack = FALSE;
+ }
+ }
+ else
+ {
+ blockSwitchingControl->attack = TRUE;
+ }
+
+ /* Check if attack spreads over frame border */
+ if ((!blockSwitchingControl->attack) && (blockSwitchingControl->lastattack)) {
+
+ if (blockSwitchingControl->attackIndex == TRANS_FAC-1) {
+ blockSwitchingControl->attack = TRUE;
+ }
+
+ blockSwitchingControl->lastattack = FALSE;
+ }
+ else {
+ blockSwitchingControl->lastattack = blockSwitchingControl->attack;
+ }
+
+ blockSwitchingControl->windowSequence = blockSwitchingControl->nextwindowSequence;
+
+
+ if (blockSwitchingControl->attack) {
+ blockSwitchingControl->nextwindowSequence = SHORT_WINDOW;
+ }
+ else {
+ blockSwitchingControl->nextwindowSequence = LONG_WINDOW;
+ }
+
+ /* update short block group */
+ if (blockSwitchingControl->nextwindowSequence == SHORT_WINDOW) {
+
+ if (blockSwitchingControl->windowSequence== LONG_WINDOW) {
+ blockSwitchingControl->windowSequence = START_WINDOW;
+ }
+
+ if (blockSwitchingControl->windowSequence == STOP_WINDOW) {
+ blockSwitchingControl->windowSequence = SHORT_WINDOW;
+ blockSwitchingControl->noOfGroups = 3;
+ blockSwitchingControl->groupLen[0] = 3;
+ blockSwitchingControl->groupLen[1] = 3;
+ blockSwitchingControl->groupLen[2] = 2;
+ }
+ }
+
+ /* update block type */
+ if (blockSwitchingControl->nextwindowSequence == LONG_WINDOW) {
+
+ if (blockSwitchingControl->windowSequence == SHORT_WINDOW) {
+ blockSwitchingControl->nextwindowSequence = STOP_WINDOW;
+ }
+ }
+
+ return(TRUE);
+}
+
+
+/*****************************************************************************
+*
+* function name: SrchMaxWithIndex
+* description: search for the biggest value in an array
+* returns: the max value
+*
+**********************************************************************************/
+static Word32 SrchMaxWithIndex(const Word32 in[], Word16 *index, Word16 n)
+{
+ Word32 max;
+ Word32 i, idx;
+
+ /* Search maximum value in array and return index and value */
+ max = 0;
+ idx = 0;
+
+ for (i = 0; i < n; i++) {
+
+ if (in[i+1] > max) {
+ max = in[i+1];
+ idx = i;
+ }
+ }
+ *index = idx;
+
+ return(max);
+}
+
+/*****************************************************************************
+*
+* function name: CalcWindowEnergy
+* description: calculate the energy before iir-filter and after irr-filter
+* returns: TRUE if success
+*
+**********************************************************************************/
+#ifndef ARMV5E
+Word32 CalcWindowEnergy(BLOCK_SWITCHING_CONTROL *blockSwitchingControl,
+ Word16 *timeSignal,
+ Word16 chIncrement,
+ Word16 windowLen)
+{
+ Word32 w, i, wOffset, tidx, ch;
+ Word32 accuUE, accuFE;
+ Word32 tempUnfiltered;
+ Word32 tempFiltered;
+ Word32 states0, states1;
+ Word32 Coeff0, Coeff1;
+
+
+ states0 = blockSwitchingControl->iirStates[0];
+ states1 = blockSwitchingControl->iirStates[1];
+ Coeff0 = hiPassCoeff[0];
+ Coeff1 = hiPassCoeff[1];
+ tidx = 0;
+ for (w=0; w < BLOCK_SWITCH_WINDOWS; w++) {
+
+ accuUE = 0;
+ accuFE = 0;
+
+ for(i=0; i<windowLen; i++) {
+ Word32 accu1, accu2, accu3;
+ Word32 out;
+ tempUnfiltered = timeSignal[tidx];
+ tidx = tidx + chIncrement;
+
+ accu1 = L_mpy_ls(Coeff1, tempUnfiltered);
+ accu2 = fixmul( Coeff0, states1 );
+ accu3 = accu1 - states0;
+ out = accu3 - accu2;
+
+ states0 = accu1;
+ states1 = out;
+
+ tempFiltered = extract_h(out);
+ accuUE += (tempUnfiltered * tempUnfiltered) >> ENERGY_SHIFT;
+ accuFE += (tempFiltered * tempFiltered) >> ENERGY_SHIFT;
+ }
+
+ blockSwitchingControl->windowNrg[1][w] = accuUE;
+ blockSwitchingControl->windowNrgF[1][w] = accuFE;
+
+ }
+
+ blockSwitchingControl->iirStates[0] = states0;
+ blockSwitchingControl->iirStates[1] = states1;
+
+ return(TRUE);
+}
+#endif
+
+/*****************************************************************************
+*
+* function name: IIRFilter
+* description: calculate the iir-filter for an array
+* returns: the result after iir-filter
+*
+**********************************************************************************/
+static Word16 IIRFilter(const Word16 in, const Word32 coeff[], Word32 states[])
+{
+ Word32 accu1, accu2, accu3;
+ Word32 out;
+
+ accu1 = L_mpy_ls(coeff[1], in);
+ accu3 = accu1 - states[0];
+ accu2 = fixmul( coeff[0], states[1] );
+ out = accu3 - accu2;
+
+ states[0] = accu1;
+ states[1] = out;
+
+ return round16(out);
+}
+
+
+static Word16 synchronizedBlockTypeTable[4][4] = {
+ /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW */
+ /* LONG_WINDOW */{LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW},
+ /* START_WINDOW */{START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
+ /* SHORT_WINDOW */{SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW},
+ /* STOP_WINDOW */{STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW}
+};
+
+
+/*****************************************************************************
+*
+* function name: SyncBlockSwitching
+* description: update block type and group value
+* returns: TRUE if success
+*
+**********************************************************************************/
+Word16 SyncBlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft,
+ BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight,
+ const Word16 nChannels)
+{
+ Word16 i;
+ Word16 patchType = LONG_WINDOW;
+
+
+ if (nChannels == 1) { /* Mono */
+ if (blockSwitchingControlLeft->windowSequence != SHORT_WINDOW) {
+ blockSwitchingControlLeft->noOfGroups = 1;
+ blockSwitchingControlLeft->groupLen[0] = 1;
+
+ for (i=1; i<TRANS_FAC; i++) {
+ blockSwitchingControlLeft->groupLen[i] = 0;
+ }
+ }
+ }
+ else { /* Stereo common Window */
+ patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft->windowSequence];
+ patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight->windowSequence];
+
+ /* Set synchronized Blocktype */
+ blockSwitchingControlLeft->windowSequence = patchType;
+ blockSwitchingControlRight->windowSequence = patchType;
+
+ /* Synchronize grouping info */
+ if(patchType != SHORT_WINDOW) { /* Long Blocks */
+ /* Set grouping info */
+ blockSwitchingControlLeft->noOfGroups = 1;
+ blockSwitchingControlRight->noOfGroups = 1;
+ blockSwitchingControlLeft->groupLen[0] = 1;
+ blockSwitchingControlRight->groupLen[0] = 1;
+
+ for (i=1; i<TRANS_FAC; i++) {
+ blockSwitchingControlLeft->groupLen[i] = 0;
+ blockSwitchingControlRight->groupLen[i] = 0;
+ }
+ }
+ else {
+
+ if (blockSwitchingControlLeft->maxWindowNrg > blockSwitchingControlRight->maxWindowNrg) {
+ /* Left Channel wins */
+ blockSwitchingControlRight->noOfGroups = blockSwitchingControlLeft->noOfGroups;
+ for (i=0; i<TRANS_FAC; i++) {
+ blockSwitchingControlRight->groupLen[i] = blockSwitchingControlLeft->groupLen[i];
+ }
+ }
+ else {
+ /* Right Channel wins */
+ blockSwitchingControlLeft->noOfGroups = blockSwitchingControlRight->noOfGroups;
+ for (i=0; i<TRANS_FAC; i++) {
+ blockSwitchingControlLeft->groupLen[i] = blockSwitchingControlRight->groupLen[i];
+ }
+ }
+ }
+ } /*endif Mono or Stereo */
+
+ return(TRUE);
+}
diff --git a/media/libstagefright/codecs/aacenc/src/channel_map.c b/media/libstagefright/codecs/aacenc/src/channel_map.c
new file mode 100644
index 0000000..247293b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/channel_map.c
@@ -0,0 +1,123 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: channel_map.c
+
+ Content: channel mapping functions
+
+*******************************************************************************/
+
+#include "channel_map.h"
+#include "bitenc.h"
+#include "psy_const.h"
+#include "qc_data.h"
+
+static const Word16 maxChannelBits = MAXBITS_COEF;
+
+static Word16 initElement(ELEMENT_INFO* elInfo, ELEMENT_TYPE elType)
+{
+ Word16 error=0;
+
+ elInfo->elType=elType;
+
+ switch(elInfo->elType) {
+
+ case ID_SCE:
+ elInfo->nChannelsInEl=1;
+
+ elInfo->ChannelIndex[0]=0;
+
+ elInfo->instanceTag=0;
+ break;
+
+ case ID_CPE:
+
+ elInfo->nChannelsInEl=2;
+
+ elInfo->ChannelIndex[0]=0;
+ elInfo->ChannelIndex[1]=1;
+
+ elInfo->instanceTag=0;
+ break;
+
+ default:
+ error=1;
+ }
+
+ return error;
+}
+
+
+Word16 InitElementInfo (Word16 nChannels, ELEMENT_INFO* elInfo)
+{
+ Word16 error;
+ error = 0;
+
+ switch(nChannels) {
+
+ case 1:
+ initElement(elInfo, ID_SCE);
+ break;
+
+ case 2:
+ initElement(elInfo, ID_CPE);
+ break;
+
+ default:
+ error=4;
+ }
+
+ return error;
+}
+
+
+Word16 InitElementBits(ELEMENT_BITS *elementBits,
+ ELEMENT_INFO elInfo,
+ Word32 bitrateTot,
+ Word16 averageBitsTot,
+ Word16 staticBitsTot)
+{
+ Word16 error;
+ error = 0;
+
+ switch(elInfo.nChannelsInEl) {
+ case 1:
+ elementBits->chBitrate = bitrateTot;
+ elementBits->averageBits = averageBitsTot - staticBitsTot;
+ elementBits->maxBits = maxChannelBits;
+
+ elementBits->maxBitResBits = maxChannelBits - averageBitsTot;
+ elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7);
+ elementBits->bitResLevel = elementBits->maxBitResBits;
+ elementBits->relativeBits = 0x4000; /* 1.0f/2 */
+ break;
+
+ case 2:
+ elementBits->chBitrate = bitrateTot >> 1;
+ elementBits->averageBits = averageBitsTot - staticBitsTot;
+ elementBits->maxBits = maxChannelBits << 1;
+
+ elementBits->maxBitResBits = (maxChannelBits << 1) - averageBitsTot;
+ elementBits->maxBitResBits = elementBits->maxBitResBits - (elementBits->maxBitResBits & 7);
+ elementBits->bitResLevel = elementBits->maxBitResBits;
+ elementBits->relativeBits = 0x4000; /* 1.0f/2 */
+ break;
+
+ default:
+ error = 1;
+ }
+ return error;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/dyn_bits.c b/media/libstagefright/codecs/aacenc/src/dyn_bits.c
new file mode 100644
index 0000000..3deacca
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/dyn_bits.c
@@ -0,0 +1,545 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: dyn_bits.c
+
+ Content: Noiseless coder module functions
+
+*******************************************************************************/
+
+#include "aac_rom.h"
+#include "dyn_bits.h"
+#include "bit_cnt.h"
+#include "psy_const.h"
+
+
+/*****************************************************************************
+*
+* function name: buildBitLookUp
+* description: count bits using all possible tables
+*
+*****************************************************************************/
+static void
+buildBitLookUp(const Word16 *quantSpectrum,
+ const Word16 maxSfb,
+ const Word16 *sfbOffset,
+ const UWord16 *sfbMax,
+ Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+ SECTION_INFO * sectionInfo)
+{
+ Word32 i;
+
+ for (i=0; i<maxSfb; i++) {
+ Word16 sfbWidth, maxVal;
+
+ sectionInfo[i].sfbCnt = 1;
+ sectionInfo[i].sfbStart = i;
+ sectionInfo[i].sectionBits = INVALID_BITCOUNT;
+ sectionInfo[i].codeBook = -1;
+ sfbWidth = sfbOffset[i + 1] - sfbOffset[i];
+ maxVal = sfbMax[i];
+ bitCount(quantSpectrum + sfbOffset[i], sfbWidth, maxVal, bitLookUp[i]);
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: findBestBook
+* description: essential helper functions
+*
+*****************************************************************************/
+static Word16
+findBestBook(const Word16 *bc, Word16 *book)
+{
+ Word32 minBits, j;
+ minBits = INVALID_BITCOUNT;
+
+ for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
+
+ if (bc[j] < minBits) {
+ minBits = bc[j];
+ *book = j;
+ }
+ }
+ return extract_l(minBits);
+}
+
+static Word16
+findMinMergeBits(const Word16 *bc1, const Word16 *bc2)
+{
+ Word32 minBits, j, sum;
+ minBits = INVALID_BITCOUNT;
+
+ for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
+ sum = bc1[j] + bc2[j];
+ if (sum < minBits) {
+ minBits = sum;
+ }
+ }
+ return extract_l(minBits);
+}
+
+static void
+mergeBitLookUp(Word16 *bc1, const Word16 *bc2)
+{
+ Word32 j;
+
+ for (j=0; j<=CODE_BOOK_ESC_NDX; j++) {
+ bc1[j] = min(bc1[j] + bc2[j], INVALID_BITCOUNT);
+ }
+}
+
+static Word16
+findMaxMerge(const Word16 mergeGainLookUp[MAX_SFB_LONG],
+ const SECTION_INFO *sectionInfo,
+ const Word16 maxSfb, Word16 *maxNdx)
+{
+ Word32 i, maxMergeGain;
+ maxMergeGain = 0;
+
+ for (i=0; i+sectionInfo[i].sfbCnt < maxSfb; i += sectionInfo[i].sfbCnt) {
+
+ if (mergeGainLookUp[i] > maxMergeGain) {
+ maxMergeGain = mergeGainLookUp[i];
+ *maxNdx = i;
+ }
+ }
+ return extract_l(maxMergeGain);
+}
+
+
+
+static Word16
+CalcMergeGain(const SECTION_INFO *sectionInfo,
+ Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+ const Word16 *sideInfoTab,
+ const Word16 ndx1,
+ const Word16 ndx2)
+{
+ Word32 SplitBits;
+ Word32 MergeBits;
+ Word32 MergeGain;
+
+ /*
+ Bit amount for splitted sections
+ */
+ SplitBits = sectionInfo[ndx1].sectionBits + sectionInfo[ndx2].sectionBits;
+
+ MergeBits = sideInfoTab[sectionInfo[ndx1].sfbCnt + sectionInfo[ndx2].sfbCnt] +
+ findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2]);
+ MergeGain = (SplitBits - MergeBits);
+
+ return extract_l(MergeGain);
+}
+
+/*
+ sectioning Stage 0:find minimum codbooks
+*/
+
+static void
+gmStage0(SECTION_INFO * sectionInfo,
+ Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+ const Word16 maxSfb)
+{
+ Word32 i;
+
+ for (i=0; i<maxSfb; i++) {
+ /* Side-Info bits will be calculated in Stage 1! */
+
+ if (sectionInfo[i].sectionBits == INVALID_BITCOUNT) {
+ sectionInfo[i].sectionBits = findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
+ }
+ }
+}
+
+/*
+ sectioning Stage 1:merge all connected regions with the same code book and
+ calculate side info
+*/
+
+static void
+gmStage1(SECTION_INFO * sectionInfo,
+ Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+ const Word16 maxSfb,
+ const Word16 *sideInfoTab)
+{
+ SECTION_INFO * sectionInfo_s;
+ SECTION_INFO * sectionInfo_e;
+ Word32 mergeStart, mergeEnd;
+ mergeStart = 0;
+
+ do {
+
+ sectionInfo_s = sectionInfo + mergeStart;
+ for (mergeEnd=mergeStart+1; mergeEnd<maxSfb; mergeEnd++) {
+ sectionInfo_e = sectionInfo + mergeEnd;
+ if (sectionInfo_s->codeBook != sectionInfo_e->codeBook)
+ break;
+ sectionInfo_s->sfbCnt += 1;
+ sectionInfo_s->sectionBits += sectionInfo_e->sectionBits;
+
+ mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]);
+ }
+
+ sectionInfo_s->sectionBits += sideInfoTab[sectionInfo_s->sfbCnt];
+ sectionInfo[mergeEnd - 1].sfbStart = sectionInfo_s->sfbStart; /* speed up prev search */
+
+ mergeStart = mergeEnd;
+
+
+ } while (mergeStart - maxSfb < 0);
+}
+
+/*
+ sectioning Stage 2:greedy merge algorithm, merge connected sections with
+ maximum bit gain until no more gain is possible
+*/
+static void
+gmStage2(SECTION_INFO *sectionInfo,
+ Word16 mergeGainLookUp[MAX_SFB_LONG],
+ Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+ const Word16 maxSfb,
+ const Word16 *sideInfoTab)
+{
+ Word16 i;
+
+ for (i=0; i+sectionInfo[i].sfbCnt<maxSfb; i+=sectionInfo[i].sfbCnt) {
+ mergeGainLookUp[i] = CalcMergeGain(sectionInfo,
+ bitLookUp,
+ sideInfoTab,
+ i,
+ (i + sectionInfo[i].sfbCnt));
+ }
+
+ while (TRUE) {
+ Word16 maxMergeGain, maxNdx, maxNdxNext, maxNdxLast;
+
+ maxMergeGain = findMaxMerge(mergeGainLookUp, sectionInfo, maxSfb, &maxNdx);
+
+
+ if (maxMergeGain <= 0)
+ break;
+
+
+ maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;
+
+ sectionInfo[maxNdx].sfbCnt = sectionInfo[maxNdx].sfbCnt + sectionInfo[maxNdxNext].sfbCnt;
+ sectionInfo[maxNdx].sectionBits = sectionInfo[maxNdx].sectionBits +
+ (sectionInfo[maxNdxNext].sectionBits - maxMergeGain);
+
+
+ mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]);
+
+
+ if (maxNdx != 0) {
+ maxNdxLast = sectionInfo[maxNdx - 1].sfbStart;
+ mergeGainLookUp[maxNdxLast] = CalcMergeGain(sectionInfo,
+ bitLookUp,
+ sideInfoTab,
+ maxNdxLast,
+ maxNdx);
+ }
+ maxNdxNext = maxNdx + sectionInfo[maxNdx].sfbCnt;
+
+ sectionInfo[maxNdxNext - 1].sfbStart = sectionInfo[maxNdx].sfbStart;
+
+
+ if (maxNdxNext - maxSfb < 0) {
+ mergeGainLookUp[maxNdx] = CalcMergeGain(sectionInfo,
+ bitLookUp,
+ sideInfoTab,
+ maxNdx,
+ maxNdxNext);
+ }
+ }
+}
+
+/*
+ count bits used by the noiseless coder
+*/
+static void
+noiselessCounter(SECTION_DATA *sectionData,
+ Word16 mergeGainLookUp[MAX_SFB_LONG],
+ Word16 bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1],
+ const Word16 *quantSpectrum,
+ const UWord16 *maxValueInSfb,
+ const Word16 *sfbOffset,
+ const Word32 blockType)
+{
+ Word32 grpNdx, i;
+ Word16 *sideInfoTab = NULL;
+ SECTION_INFO *sectionInfo;
+
+ /*
+ use appropriate side info table
+ */
+ switch (blockType)
+ {
+ case LONG_WINDOW:
+ case START_WINDOW:
+ case STOP_WINDOW:
+ sideInfoTab = sideInfoTabLong;
+ break;
+ case SHORT_WINDOW:
+ sideInfoTab = sideInfoTabShort;
+ break;
+ }
+
+
+ sectionData->noOfSections = 0;
+ sectionData->huffmanBits = 0;
+ sectionData->sideInfoBits = 0;
+
+
+ if (sectionData->maxSfbPerGroup == 0)
+ return;
+
+ /*
+ loop trough groups
+ */
+ for (grpNdx=0; grpNdx<sectionData->sfbCnt; grpNdx+=sectionData->sfbPerGroup) {
+
+ sectionInfo = sectionData->sectionInfo + sectionData->noOfSections;
+
+ buildBitLookUp(quantSpectrum,
+ sectionData->maxSfbPerGroup,
+ sfbOffset + grpNdx,
+ maxValueInSfb + grpNdx,
+ bitLookUp,
+ sectionInfo);
+
+ /*
+ 0.Stage
+ */
+ gmStage0(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup);
+
+ /*
+ 1.Stage
+ */
+ gmStage1(sectionInfo, bitLookUp, sectionData->maxSfbPerGroup, sideInfoTab);
+
+
+ /*
+ 2.Stage
+ */
+ gmStage2(sectionInfo,
+ mergeGainLookUp,
+ bitLookUp,
+ sectionData->maxSfbPerGroup,
+ sideInfoTab);
+
+
+ /*
+ compress output, calculate total huff and side bits
+ */
+ for (i=0; i<sectionData->maxSfbPerGroup; i+=sectionInfo[i].sfbCnt) {
+ findBestBook(bitLookUp[i], &(sectionInfo[i].codeBook));
+ sectionInfo[i].sfbStart = sectionInfo[i].sfbStart + grpNdx;
+
+ sectionData->huffmanBits = (sectionData->huffmanBits +
+ (sectionInfo[i].sectionBits - sideInfoTab[sectionInfo[i].sfbCnt]));
+ sectionData->sideInfoBits = (sectionData->sideInfoBits + sideInfoTab[sectionInfo[i].sfbCnt]);
+ sectionData->sectionInfo[sectionData->noOfSections] = sectionInfo[i];
+ sectionData->noOfSections = sectionData->noOfSections + 1;
+ }
+ }
+}
+
+
+/*******************************************************************************
+*
+* functionname: scfCount
+* returns : ---
+* description : count bits used by scalefactors.
+*
+********************************************************************************/
+static void scfCount(const Word16 *scalefacGain,
+ const UWord16 *maxValueInSfb,
+ SECTION_DATA * sectionData)
+
+{
+ SECTION_INFO *psectionInfo;
+ SECTION_INFO *psectionInfom;
+
+ /* counter */
+ Word32 i = 0; /* section counter */
+ Word32 j = 0; /* sfb counter */
+ Word32 k = 0; /* current section auxiliary counter */
+ Word32 m = 0; /* other section auxiliary counter */
+ Word32 n = 0; /* other sfb auxiliary counter */
+
+ /* further variables */
+ Word32 lastValScf = 0;
+ Word32 deltaScf = 0;
+ Flag found = 0;
+ Word32 scfSkipCounter = 0;
+
+
+ sectionData->scalefacBits = 0;
+
+
+ if (scalefacGain == NULL) {
+ return;
+ }
+
+ lastValScf = 0;
+ sectionData->firstScf = 0;
+
+ psectionInfo = sectionData->sectionInfo;
+ for (i=0; i<sectionData->noOfSections; i++) {
+
+ if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO) {
+ sectionData->firstScf = psectionInfo->sfbStart;
+ lastValScf = scalefacGain[sectionData->firstScf];
+ break;
+ }
+ psectionInfo += 1;
+ }
+
+ psectionInfo = sectionData->sectionInfo;
+ for (i=0; i<sectionData->noOfSections; i++, psectionInfo += 1) {
+
+ if (psectionInfo->codeBook != CODE_BOOK_ZERO_NO
+ && psectionInfo->codeBook != CODE_BOOK_PNS_NO) {
+ for (j = psectionInfo->sfbStart;
+ j < (psectionInfo->sfbStart + psectionInfo->sfbCnt); j++) {
+ /* check if we can repeat the last value to save bits */
+
+ if (maxValueInSfb[j] == 0) {
+ found = 0;
+
+ if (scfSkipCounter == 0) {
+ /* end of section */
+
+ if (j - ((psectionInfo->sfbStart + psectionInfo->sfbCnt) - 1) == 0) {
+ found = 0;
+ }
+ else {
+ for (k = j + 1; k < psectionInfo->sfbStart + psectionInfo->sfbCnt; k++) {
+
+ if (maxValueInSfb[k] != 0) {
+ int tmp = L_abs(scalefacGain[k] - lastValScf);
+ found = 1;
+
+ if ( tmp < CODE_BOOK_SCF_LAV) {
+ /* save bits */
+ deltaScf = 0;
+ }
+ else {
+ /* do not save bits */
+ deltaScf = lastValScf - scalefacGain[j];
+ lastValScf = scalefacGain[j];
+ scfSkipCounter = 0;
+ }
+ break;
+ }
+ /* count scalefactor skip */
+ scfSkipCounter = scfSkipCounter + 1;
+ }
+ }
+
+ psectionInfom = psectionInfo + 1;
+ /* search for the next maxValueInSfb[] != 0 in all other sections */
+ for (m = i + 1; (m < sectionData->noOfSections) && (found == 0); m++) {
+
+ if ((psectionInfom->codeBook != CODE_BOOK_ZERO_NO) &&
+ (psectionInfom->codeBook != CODE_BOOK_PNS_NO)) {
+ for (n = psectionInfom->sfbStart;
+ n < (psectionInfom->sfbStart + psectionInfom->sfbCnt); n++) {
+
+ if (maxValueInSfb[n] != 0) {
+ found = 1;
+
+ if ( (abs_s(scalefacGain[n] - lastValScf) < CODE_BOOK_SCF_LAV)) {
+ deltaScf = 0;
+ }
+ else {
+ deltaScf = (lastValScf - scalefacGain[j]);
+ lastValScf = scalefacGain[j];
+ scfSkipCounter = 0;
+ }
+ break;
+ }
+ /* count scalefactor skip */
+ scfSkipCounter = scfSkipCounter + 1;
+ }
+ }
+
+ psectionInfom += 1;
+ }
+
+ if (found == 0) {
+ deltaScf = 0;
+ scfSkipCounter = 0;
+ }
+ }
+ else {
+ deltaScf = 0;
+ scfSkipCounter = scfSkipCounter - 1;
+ }
+ }
+ else {
+ deltaScf = lastValScf - scalefacGain[j];
+ lastValScf = scalefacGain[j];
+ }
+ sectionData->scalefacBits += bitCountScalefactorDelta(deltaScf);
+ }
+ }
+ }
+}
+
+
+typedef Word16 (*lookUpTable)[CODE_BOOK_ESC_NDX + 1];
+
+
+Word16
+dynBitCount(const Word16 *quantSpectrum,
+ const UWord16 *maxValueInSfb,
+ const Word16 *scalefac,
+ const Word16 blockType,
+ const Word16 sfbCnt,
+ const Word16 maxSfbPerGroup,
+ const Word16 sfbPerGroup,
+ const Word16 *sfbOffset,
+ SECTION_DATA *sectionData)
+{
+ sectionData->blockType = blockType;
+ sectionData->sfbCnt = sfbCnt;
+ sectionData->sfbPerGroup = sfbPerGroup;
+ if(sfbPerGroup)
+ sectionData->noOfGroups = sfbCnt/sfbPerGroup;
+ else
+ sectionData->noOfGroups = 0x7fff;
+ sectionData->maxSfbPerGroup = maxSfbPerGroup;
+
+ noiselessCounter(sectionData,
+ sectionData->mergeGainLookUp,
+ (lookUpTable)sectionData->bitLookUp,
+ quantSpectrum,
+ maxValueInSfb,
+ sfbOffset,
+ blockType);
+
+ scfCount(scalefac,
+ maxValueInSfb,
+ sectionData);
+
+
+ return (sectionData->huffmanBits + sectionData->sideInfoBits +
+ sectionData->scalefacBits);
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/grp_data.c b/media/libstagefright/codecs/aacenc/src/grp_data.c
new file mode 100644
index 0000000..08d9a76
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/grp_data.c
@@ -0,0 +1,188 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: grp_data.c
+
+ Content: Short block grouping function
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "psy_const.h"
+#include "interface.h"
+#include "grp_data.h"
+
+/*****************************************************************************
+*
+* function name: groupShortData
+* description: group short data for next quantization and coding
+*
+**********************************************************************************/
+void
+groupShortData(Word32 *mdctSpectrum,
+ Word32 *tmpSpectrum,
+ SFB_THRESHOLD *sfbThreshold,
+ SFB_ENERGY *sfbEnergy,
+ SFB_ENERGY *sfbEnergyMS,
+ SFB_ENERGY *sfbSpreadedEnergy,
+ const Word16 sfbCnt,
+ const Word16 *sfbOffset,
+ const Word16 *sfbMinSnr,
+ Word16 *groupedSfbOffset,
+ Word16 *maxSfbPerGroup,
+ Word16 *groupedSfbMinSnr,
+ const Word16 noOfGroups,
+ const Word16 *groupLen)
+{
+ Word32 i, j;
+ Word32 line;
+ Word32 sfb;
+ Word32 grp;
+ Word32 wnd;
+ Word32 offset;
+ Word32 highestSfb;
+
+ /* for short: regroup and */
+ /* cumulate energies und thresholds group-wise . */
+
+ /* calculate sfbCnt */
+ highestSfb = 0;
+ for (wnd=0; wnd<TRANS_FAC; wnd++) {
+ for (sfb=sfbCnt - 1; sfb>=highestSfb; sfb--) {
+ for (line=(sfbOffset[sfb + 1] - 1); line>=sfbOffset[sfb]; line--) {
+
+ if (mdctSpectrum[wnd*FRAME_LEN_SHORT+line] != 0) break;
+ }
+
+ if (line >= sfbOffset[sfb]) break;
+ }
+ highestSfb = max(highestSfb, sfb);
+ }
+
+ if (highestSfb < 0) {
+ highestSfb = 0;
+ }
+ *maxSfbPerGroup = highestSfb + 1;
+
+ /* calculate sfbOffset */
+ i = 0;
+ offset = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ groupedSfbOffset[i] = offset + sfbOffset[sfb] * groupLen[grp];
+ i += 1;
+ }
+ offset += groupLen[grp] * FRAME_LEN_SHORT;
+ }
+ groupedSfbOffset[i] = FRAME_LEN_LONG;
+ i += 1;
+
+ /* calculate minSnr */
+ i = 0;
+ offset = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ groupedSfbMinSnr[i] = sfbMinSnr[sfb];
+ i += 1;
+ }
+ offset += groupLen[grp] * FRAME_LEN_SHORT;
+ }
+
+
+ /* sum up sfbThresholds */
+ wnd = 0;
+ i = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ Word32 thresh = sfbThreshold->sfbShort[wnd][sfb];
+ for (j=1; j<groupLen[grp]; j++) {
+ thresh = L_add(thresh, sfbThreshold->sfbShort[wnd+j][sfb]);
+ }
+ sfbThreshold->sfbLong[i] = thresh;
+ i += 1;
+ }
+ wnd += groupLen[grp];
+ }
+
+ /* sum up sfbEnergies left/right */
+ wnd = 0;
+ i = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ Word32 energy = sfbEnergy->sfbShort[wnd][sfb];
+ for (j=1; j<groupLen[grp]; j++) {
+ energy = L_add(energy, sfbEnergy->sfbShort[wnd+j][sfb]);
+ }
+ sfbEnergy->sfbLong[i] = energy;
+ i += 1;
+ }
+ wnd += groupLen[grp];
+ }
+
+ /* sum up sfbEnergies mid/side */
+ wnd = 0;
+ i = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ Word32 energy = sfbEnergyMS->sfbShort[wnd][sfb];
+ for (j=1; j<groupLen[grp]; j++) {
+ energy = L_add(energy, sfbEnergyMS->sfbShort[wnd+j][sfb]);
+ }
+ sfbEnergyMS->sfbLong[i] = energy;
+ i += 1;
+ }
+ wnd += groupLen[grp];
+ }
+
+ /* sum up sfbSpreadedEnergies */
+ wnd = 0;
+ i = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ Word32 energy = sfbSpreadedEnergy->sfbShort[wnd][sfb];
+ for (j=1; j<groupLen[grp]; j++) {
+ energy = L_add(energy, sfbSpreadedEnergy->sfbShort[wnd+j][sfb]);
+ }
+ sfbSpreadedEnergy->sfbLong[i] = energy;
+ i += 1;
+ }
+ wnd += groupLen[grp];
+ }
+
+ /* re-group spectrum */
+ wnd = 0;
+ i = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ for (sfb = 0; sfb < sfbCnt; sfb++) {
+ for (j = 0; j < groupLen[grp]; j++) {
+ Word16 lineOffset = FRAME_LEN_SHORT * (wnd + j);
+ for (line = lineOffset + sfbOffset[sfb]; line < lineOffset + sfbOffset[sfb+1]; line++) {
+ tmpSpectrum[i] = mdctSpectrum[line];
+ i = i + 1;
+ }
+ }
+ }
+ wnd += groupLen[grp];
+ }
+
+ for(i=0;i<FRAME_LEN_LONG;i+=4) {
+ mdctSpectrum[i] = tmpSpectrum[i];
+ mdctSpectrum[i+1] = tmpSpectrum[i+1];
+ mdctSpectrum[i+2] = tmpSpectrum[i+2];
+ mdctSpectrum[i+3] = tmpSpectrum[i+3];
+ }
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/interface.c b/media/libstagefright/codecs/aacenc/src/interface.c
new file mode 100644
index 0000000..304b1d4
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/interface.c
@@ -0,0 +1,112 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: interface.c
+
+ Content: Interface psychoaccoustic/quantizer functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "psy_const.h"
+#include "interface.h"
+
+/*****************************************************************************
+*
+* function name: BuildInterface
+* description: update output parameter
+*
+**********************************************************************************/
+void BuildInterface(Word32 *groupedMdctSpectrum,
+ const Word16 mdctScale,
+ SFB_THRESHOLD *groupedSfbThreshold,
+ SFB_ENERGY *groupedSfbEnergy,
+ SFB_ENERGY *groupedSfbSpreadedEnergy,
+ const SFB_ENERGY_SUM sfbEnergySumLR,
+ const SFB_ENERGY_SUM sfbEnergySumMS,
+ const Word16 windowSequence,
+ const Word16 windowShape,
+ const Word16 groupedSfbCnt,
+ const Word16 *groupedSfbOffset,
+ const Word16 maxSfbPerGroup,
+ const Word16 *groupedSfbMinSnr,
+ const Word16 noOfGroups,
+ const Word16 *groupLen,
+ PSY_OUT_CHANNEL *psyOutCh)
+{
+ Word32 j;
+ Word32 grp;
+ Word32 mask;
+ Word16 *tmpV;
+
+ /*
+ copy values to psyOut
+ */
+ psyOutCh->maxSfbPerGroup = maxSfbPerGroup;
+ psyOutCh->sfbCnt = groupedSfbCnt;
+ if(noOfGroups)
+ psyOutCh->sfbPerGroup = groupedSfbCnt/ noOfGroups;
+ else
+ psyOutCh->sfbPerGroup = 0x7fff;
+ psyOutCh->windowSequence = windowSequence;
+ psyOutCh->windowShape = windowShape;
+ psyOutCh->mdctScale = mdctScale;
+ psyOutCh->mdctSpectrum = groupedMdctSpectrum;
+ psyOutCh->sfbEnergy = groupedSfbEnergy->sfbLong;
+ psyOutCh->sfbThreshold = groupedSfbThreshold->sfbLong;
+ psyOutCh->sfbSpreadedEnergy = groupedSfbSpreadedEnergy->sfbLong;
+
+ tmpV = psyOutCh->sfbOffsets;
+ for(j=0; j<groupedSfbCnt + 1; j++) {
+ *tmpV++ = groupedSfbOffset[j];
+ }
+
+ tmpV = psyOutCh->sfbMinSnr;
+ for(j=0;j<groupedSfbCnt; j++) {
+ *tmpV++ = groupedSfbMinSnr[j];
+ }
+
+ /* generate grouping mask */
+ mask = 0;
+ for (grp = 0; grp < noOfGroups; grp++) {
+ mask = mask << 1;
+ for (j=1; j<groupLen[grp]; j++) {
+ mask = mask << 1;
+ mask |= 1;
+ }
+ }
+ psyOutCh->groupingMask = mask;
+
+ if (windowSequence != SHORT_WINDOW) {
+ psyOutCh->sfbEnSumLR = sfbEnergySumLR.sfbLong;
+ psyOutCh->sfbEnSumMS = sfbEnergySumMS.sfbLong;
+ }
+ else {
+ Word32 i;
+ Word32 accuSumMS=0;
+ Word32 accuSumLR=0;
+ Word32 *pSumMS = sfbEnergySumMS.sfbShort;
+ Word32 *pSumLR = sfbEnergySumLR.sfbShort;
+
+ for (i=TRANS_FAC; i; i--) {
+ accuSumLR = L_add(accuSumLR, *pSumLR); pSumLR++;
+ accuSumMS = L_add(accuSumMS, *pSumMS); pSumMS++;
+ }
+ psyOutCh->sfbEnSumMS = accuSumMS;
+ psyOutCh->sfbEnSumLR = accuSumLR;
+ }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/line_pe.c b/media/libstagefright/codecs/aacenc/src/line_pe.c
new file mode 100644
index 0000000..da57647
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/line_pe.c
@@ -0,0 +1,145 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: line_pe.c
+
+ Content: Perceptual entropie module functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "typedef.h"
+#include "line_pe.h"
+
+
+static const Word16 C1_I = 12; /* log(8.0)/log(2) *4 */
+static const Word32 C2_I = 10830; /* log(2.5)/log(2) * 1024 * 4 * 2 */
+static const Word16 C3_I = 573; /* (1-C2/C1) *1024 */
+
+
+/*****************************************************************************
+*
+* function name: prepareSfbPe
+* description: constants that do not change during successive pe calculations
+*
+**********************************************************************************/
+void prepareSfbPe(PE_DATA *peData,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word16 nChannels,
+ const Word16 peOffset)
+{
+ Word32 sfbGrp, sfb;
+ Word32 ch;
+
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ PE_CHANNEL_DATA *peChanData=&peData->peChannelData[ch];
+ for(sfbGrp=0;sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup){
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ peChanData->sfbNLines4[sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb];
+ sfbNRelevantLines[ch][sfbGrp+sfb] = sfbNRelevantLines[ch][sfbGrp+sfb] >> 2;
+ peChanData->sfbLdEnergy[sfbGrp+sfb] = logSfbEnergy[ch][sfbGrp+sfb];
+ }
+ }
+ }
+ peData->offset = peOffset;
+}
+
+
+/*****************************************************************************
+*
+* function name: calcSfbPe
+* description: constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr)
+*
+**********************************************************************************/
+void calcSfbPe(PE_DATA *peData,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const Word16 nChannels)
+{
+ Word32 ch;
+ Word32 sfbGrp, sfb;
+ Word32 nLines4;
+ Word32 ldThr, ldRatio;
+ Word32 pe, constPart, nActiveLines;
+
+ peData->pe = peData->offset;
+ peData->constPart = 0;
+ peData->nActiveLines = 0;
+ for(ch=0; ch<nChannels; ch++) {
+ PSY_OUT_CHANNEL *psyOutChan = &psyOutChannel[ch];
+ PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
+ const Word32 *sfbEnergy = psyOutChan->sfbEnergy;
+ const Word32 *sfbThreshold = psyOutChan->sfbThreshold;
+
+ pe = 0;
+ constPart = 0;
+ nActiveLines = 0;
+
+ for(sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ Word32 nrg = sfbEnergy[sfbGrp+sfb];
+ Word32 thres = sfbThreshold[sfbGrp+sfb];
+ Word32 sfbLDEn = peChanData->sfbLdEnergy[sfbGrp+sfb];
+
+ if (nrg > thres) {
+ ldThr = iLog4(thres);
+
+ ldRatio = sfbLDEn - ldThr;
+
+ nLines4 = peChanData->sfbNLines4[sfbGrp+sfb];
+
+ /* sfbPe = nl*log2(en/thr)*/
+ if (ldRatio >= C1_I) {
+ peChanData->sfbPe[sfbGrp+sfb] = (nLines4*ldRatio + 8) >> 4;
+ peChanData->sfbConstPart[sfbGrp+sfb] = ((nLines4*sfbLDEn)) >> 4;
+ }
+ else {
+ /* sfbPe = nl*(c2 + c3*log2(en/thr))*/
+ peChanData->sfbPe[sfbGrp+sfb] = extract_l((L_mpy_wx(
+ (C2_I + C3_I * ldRatio * 2) << 4, nLines4) + 4) >> 3);
+ peChanData->sfbConstPart[sfbGrp+sfb] = extract_l(( L_mpy_wx(
+ (C2_I + C3_I * sfbLDEn * 2) << 4, nLines4) + 4) >> 3);
+ nLines4 = (nLines4 * C3_I + (1024<<1)) >> 10;
+ }
+ peChanData->sfbNActiveLines[sfbGrp+sfb] = nLines4 >> 2;
+ }
+ else {
+ peChanData->sfbPe[sfbGrp+sfb] = 0;
+ peChanData->sfbConstPart[sfbGrp+sfb] = 0;
+ peChanData->sfbNActiveLines[sfbGrp+sfb] = 0;
+ }
+ pe = pe + peChanData->sfbPe[sfbGrp+sfb];
+ constPart = constPart + peChanData->sfbConstPart[sfbGrp+sfb];
+ nActiveLines = nActiveLines + peChanData->sfbNActiveLines[sfbGrp+sfb];
+ }
+ }
+
+ peChanData->pe = saturate(pe);
+ peChanData->constPart = saturate(constPart);
+ peChanData->nActiveLines = saturate(nActiveLines);
+
+
+ pe += peData->pe;
+ peData->pe = saturate(pe);
+ constPart += peData->constPart;
+ peData->constPart = saturate(constPart);
+ nActiveLines += peData->nActiveLines;
+ peData->nActiveLines = saturate(nActiveLines);
+ }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/memalign.c b/media/libstagefright/codecs/aacenc/src/memalign.c
new file mode 100644
index 0000000..7d20352
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/memalign.c
@@ -0,0 +1,107 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: mem_align.c
+
+ Content: Memory alloc alignments functions
+
+*******************************************************************************/
+
+
+#include "memalign.h"
+
+/*****************************************************************************
+*
+* function name: mem_malloc
+* description: malloc the alignments memory
+* returns: the point of the memory
+*
+**********************************************************************************/
+void *
+mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID)
+{
+ int ret;
+ unsigned char *mem_ptr;
+ VO_MEM_INFO MemInfo;
+
+ if (!alignment) {
+
+ MemInfo.Flag = 0;
+ MemInfo.Size = size + 1;
+ ret = pMemop->Alloc(CodecID, &MemInfo);
+ if(ret != 0)
+ return 0;
+ mem_ptr = (unsigned char *)MemInfo.VBuffer;
+
+ pMemop->Set(CodecID, mem_ptr, 0, size + 1);
+
+ *mem_ptr = (unsigned char)1;
+
+ return ((void *)(mem_ptr+1));
+ } else {
+ unsigned char *tmp;
+
+ MemInfo.Flag = 0;
+ MemInfo.Size = size + alignment;
+ ret = pMemop->Alloc(CodecID, &MemInfo);
+ if(ret != 0)
+ return 0;
+
+ tmp = (unsigned char *)MemInfo.VBuffer;
+
+ pMemop->Set(CodecID, tmp, 0, size + alignment);
+
+ mem_ptr =
+ (unsigned char *) ((unsigned int) (tmp + alignment - 1) &
+ (~((unsigned int) (alignment - 1))));
+
+ if (mem_ptr == tmp)
+ mem_ptr += alignment;
+
+ *(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp);
+
+ return ((void *)mem_ptr);
+ }
+
+ return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: mem_free
+* description: free the memory
+*
+*******************************************************************************/
+void
+mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID)
+{
+
+ unsigned char *ptr;
+
+ if (mem_ptr == 0)
+ return;
+
+ ptr = mem_ptr;
+
+ ptr -= *(ptr - 1);
+
+ pMemop->Free(CodecID, ptr);
+}
+
+
+
diff --git a/media/libstagefright/codecs/aacenc/src/ms_stereo.c b/media/libstagefright/codecs/aacenc/src/ms_stereo.c
new file mode 100644
index 0000000..c83d07b
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/ms_stereo.c
@@ -0,0 +1,139 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: ms_stereo.c
+
+ Content: MS stereo processing function
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "psy_const.h"
+#include "ms_stereo.h"
+
+
+/********************************************************************************
+*
+* function name: MsStereoProcessing
+* description: detect use ms stereo or not
+* if ((min(thrLn, thrRn)*min(thrLn, thrRn))/(enMn*enSn))
+* >= ((thrLn *thrRn)/(enLn*enRn)) then ms stereo
+*
+**********************************************************************************/
+void MsStereoProcessing(Word32 *sfbEnergyLeft,
+ Word32 *sfbEnergyRight,
+ const Word32 *sfbEnergyMid,
+ const Word32 *sfbEnergySide,
+ Word32 *mdctSpectrumLeft,
+ Word32 *mdctSpectrumRight,
+ Word32 *sfbThresholdLeft,
+ Word32 *sfbThresholdRight,
+ Word32 *sfbSpreadedEnLeft,
+ Word32 *sfbSpreadedEnRight,
+ Word16 *msDigest,
+ Word16 *msMask,
+ const Word16 sfbCnt,
+ const Word16 sfbPerGroup,
+ const Word16 maxSfbPerGroup,
+ const Word16 *sfbOffset) {
+ Word32 temp;
+ Word32 sfb,sfboffs, j;
+ Word32 msMaskTrueSomewhere = 0;
+ Word32 msMaskFalseSomewhere = 0;
+
+ for (sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
+ for (sfboffs=0;sfboffs<maxSfbPerGroup;sfboffs++) {
+
+ Word32 temp;
+ Word32 pnlr,pnms;
+ Word32 minThreshold;
+ Word32 thrL, thrR, nrgL, nrgR;
+ Word32 idx, shift;
+
+ idx = sfb + sfboffs;
+
+ thrL = sfbThresholdLeft[idx];
+ thrR = sfbThresholdRight[idx];
+ nrgL = sfbEnergyLeft[idx];
+ nrgR = sfbEnergyRight[idx];
+
+ minThreshold = min(thrL, thrR);
+
+ nrgL = max(nrgL,thrL) + 1;
+ shift = norm_l(nrgL);
+ nrgL = Div_32(thrL << shift, nrgL << shift);
+ nrgR = max(nrgR,thrR) + 1;
+ shift = norm_l(nrgR);
+ nrgR = Div_32(thrR << shift, nrgR << shift);
+
+ pnlr = fixmul(nrgL, nrgR);
+
+ nrgL = sfbEnergyMid[idx];
+ nrgR = sfbEnergySide[idx];
+
+ nrgL = max(nrgL,minThreshold) + 1;
+ shift = norm_l(nrgL);
+ nrgL = Div_32(minThreshold << shift, nrgL << shift);
+
+ nrgR = max(nrgR,minThreshold) + 1;
+ shift = norm_l(nrgR);
+ nrgR = Div_32(minThreshold << shift, nrgR << shift);
+
+ pnms = fixmul(nrgL, nrgR);
+
+ temp = (pnlr + 1) / ((pnms >> 8) + 1);
+
+ temp = pnms - pnlr;
+ if( temp > 0 ){
+
+ msMask[idx] = 1;
+ msMaskTrueSomewhere = 1;
+
+ for (j=sfbOffset[idx]; j<sfbOffset[idx+1]; j++) {
+ Word32 left, right;
+ left = (mdctSpectrumLeft[j] >> 1);
+ right = (mdctSpectrumRight[j] >> 1);
+ mdctSpectrumLeft[j] = left + right;
+ mdctSpectrumRight[j] = left - right;
+ }
+
+ sfbThresholdLeft[idx] = minThreshold;
+ sfbThresholdRight[idx] = minThreshold;
+ sfbEnergyLeft[idx] = sfbEnergyMid[idx];
+ sfbEnergyRight[idx] = sfbEnergySide[idx];
+
+ sfbSpreadedEnRight[idx] = min(sfbSpreadedEnLeft[idx],sfbSpreadedEnRight[idx]) >> 1;
+ sfbSpreadedEnLeft[idx] = sfbSpreadedEnRight[idx];
+
+ }
+ else {
+ msMask[idx] = 0;
+ msMaskFalseSomewhere = 1;
+ }
+ }
+ if ( msMaskTrueSomewhere ) {
+ if(msMaskFalseSomewhere ) {
+ *msDigest = SI_MS_MASK_SOME;
+ } else {
+ *msDigest = SI_MS_MASK_ALL;
+ }
+ } else {
+ *msDigest = SI_MS_MASK_NONE;
+ }
+ }
+
+}
diff --git a/media/libstagefright/codecs/aacenc/src/pre_echo_control.c b/media/libstagefright/codecs/aacenc/src/pre_echo_control.c
new file mode 100644
index 0000000..f59216e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/pre_echo_control.c
@@ -0,0 +1,113 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: pre_echo_control.c
+
+ Content: Pre echo control functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+
+#include "oper_32b.h"
+#include "pre_echo_control.h"
+
+
+/*****************************************************************************
+*
+* function name:InitPreEchoControl
+* description: init pre echo control parameter
+*
+*****************************************************************************/
+void InitPreEchoControl(Word32 *pbThresholdNm1,
+ Word16 numPb,
+ Word32 *pbThresholdQuiet)
+{
+ Word16 pb;
+
+ for(pb=0; pb<numPb; pb++) {
+ pbThresholdNm1[pb] = pbThresholdQuiet[pb];
+ }
+}
+
+/*****************************************************************************
+*
+* function name:PreEchoControl
+* description: update shreshold to avoid pre echo
+* thr(n) = max(rpmin*thrq(n), min(thrq(n), rpelev*thrq1(n)))
+*
+*
+*****************************************************************************/
+void PreEchoControl(Word32 *pbThresholdNm1,
+ Word16 numPb,
+ Word32 maxAllowedIncreaseFactor,
+ Word16 minRemainingThresholdFactor,
+ Word32 *pbThreshold,
+ Word16 mdctScale,
+ Word16 mdctScalenm1)
+{
+ Word32 i;
+ Word32 tmpThreshold1, tmpThreshold2;
+ Word32 scaling;
+
+ /* maxAllowedIncreaseFactor is hard coded to 2 */
+ (void)maxAllowedIncreaseFactor;
+
+ scaling = ((mdctScale - mdctScalenm1) << 1);
+
+ if ( scaling > 0 ) {
+ for(i = 0; i < numPb; i++) {
+ tmpThreshold1 = pbThresholdNm1[i] >> (scaling-1);
+ tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor);
+
+ /* copy thresholds to internal memory */
+ pbThresholdNm1[i] = pbThreshold[i];
+
+
+ if(pbThreshold[i] > tmpThreshold1) {
+ pbThreshold[i] = tmpThreshold1;
+ }
+
+ if(tmpThreshold2 > pbThreshold[i]) {
+ pbThreshold[i] = tmpThreshold2;
+ }
+
+ }
+ }
+ else {
+ scaling = -scaling;
+ for(i = 0; i < numPb; i++) {
+
+ tmpThreshold1 = pbThresholdNm1[i] << 1;
+ tmpThreshold2 = L_mpy_ls(pbThreshold[i], minRemainingThresholdFactor);
+
+ /* copy thresholds to internal memory */
+ pbThresholdNm1[i] = pbThreshold[i];
+
+
+ if(((pbThreshold[i] >> scaling) > tmpThreshold1)) {
+ pbThreshold[i] = tmpThreshold1 << scaling;
+ }
+
+ if(tmpThreshold2 > pbThreshold[i]) {
+ pbThreshold[i] = tmpThreshold2;
+ }
+
+ }
+ }
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/psy_configuration.c b/media/libstagefright/codecs/aacenc/src/psy_configuration.c
new file mode 100644
index 0000000..586e00f
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/psy_configuration.c
@@ -0,0 +1,505 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: psy_configuration.c
+
+ Content: Psychoaccoustic configuration functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "psy_configuration.h"
+#include "adj_thr.h"
+#include "aac_rom.h"
+
+
+
+#define BARC_SCALE 100 /* integer barc values are scaled with 100 */
+#define LOG2_1000 301 /* log2*1000 */
+#define PI2_1000 1571 /* pi/2*1000*/
+#define ATAN_COEF1 3560 /* 1000/0.280872f*/
+#define ATAN_COEF2 281 /* 1000*0.280872f*/
+
+
+typedef struct{
+ Word32 sampleRate;
+ const UWord8 *paramLong;
+ const UWord8 *paramShort;
+}SFB_INFO_TAB;
+
+static const Word16 ABS_LEV = 20;
+static const Word16 BARC_THR_QUIET[] = {15, 10, 7, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 5, 10, 20, 30};
+
+
+
+static const Word16 max_bark = 24; /* maximum bark-value */
+static const Word16 maskLow = 30; /* in 1dB/bark */
+static const Word16 maskHigh = 15; /* in 1*dB/bark */
+static const Word16 c_ratio = 0x0029; /* pow(10.0f, -(29.0f/10.0f)) */
+
+static const Word16 maskLowSprEnLong = 30; /* in 1dB/bark */
+static const Word16 maskHighSprEnLong = 20; /* in 1dB/bark */
+static const Word16 maskHighSprEnLongLowBr = 15; /* in 1dB/bark */
+static const Word16 maskLowSprEnShort = 20; /* in 1dB/bark */
+static const Word16 maskHighSprEnShort = 15; /* in 1dB/bark */
+static const Word16 c_minRemainingThresholdFactor = 0x0148; /* 0.01 *(1 << 15)*/
+static const Word32 c_maxsnr = 0x66666666; /* upper limit is -1 dB */
+static const Word32 c_minsnr = 0x00624dd3; /* lower limit is -25 dB */
+
+static const Word32 c_maxClipEnergyLong = 0x77359400; /* 2.0e9f*/
+static const Word32 c_maxClipEnergyShort = 0x01dcd650; /* 2.0e9f/(AACENC_TRANS_FAC*AACENC_TRANS_FAC)*/
+
+
+Word32 GetSRIndex(Word32 sampleRate)
+{
+ if (92017 <= sampleRate) return 0;
+ if (75132 <= sampleRate) return 1;
+ if (55426 <= sampleRate) return 2;
+ if (46009 <= sampleRate) return 3;
+ if (37566 <= sampleRate) return 4;
+ if (27713 <= sampleRate) return 5;
+ if (23004 <= sampleRate) return 6;
+ if (18783 <= sampleRate) return 7;
+ if (13856 <= sampleRate) return 8;
+ if (11502 <= sampleRate) return 9;
+ if (9391 <= sampleRate) return 10;
+
+ return 11;
+}
+
+
+/*********************************************************************************
+*
+* function name: atan_1000
+* description: calculates 1000*atan(x/1000)
+* based on atan approx for x > 0
+* atan(x) = x/((float)1.0f+(float)0.280872f*x*x) if x < 1
+* = pi/2 - x/((float)0.280872f +x*x) if x >= 1
+* return: 1000*atan(x/1000)
+*
+**********************************************************************************/
+static Word16 atan_1000(Word32 val)
+{
+ Word32 y;
+
+
+ if(L_sub(val, 1000) < 0) {
+ y = extract_l(((1000 * val) / (1000 + ((val * val) / ATAN_COEF1))));
+ }
+ else {
+ y = PI2_1000 - ((1000 * val) / (ATAN_COEF2 + ((val * val) / 1000)));
+ }
+
+ return extract_l(y);
+}
+
+
+/*****************************************************************************
+*
+* function name: BarcLineValue
+* description: Calculates barc value for one frequency line
+* returns: barc value of line * BARC_SCALE
+* input: number of lines in transform, index of line to check, Fs
+* output:
+*
+*****************************************************************************/
+static Word16 BarcLineValue(Word16 noOfLines, Word16 fftLine, Word32 samplingFreq)
+{
+ Word32 center_freq, temp, bvalFFTLine;
+
+ /* center frequency of fft line */
+ center_freq = (fftLine * samplingFreq) / (noOfLines << 1);
+ temp = atan_1000((center_freq << 2) / (3*10));
+ bvalFFTLine =
+ (26600 * atan_1000((center_freq*76) / 100) + 7*temp*temp) / (2*1000*1000 / BARC_SCALE);
+
+ return saturate(bvalFFTLine);
+}
+
+/*****************************************************************************
+*
+* function name: initThrQuiet
+* description: init thredhold in quiet
+*
+*****************************************************************************/
+static void initThrQuiet(Word16 numPb,
+ Word16 *pbOffset,
+ Word16 *pbBarcVal,
+ Word32 *pbThresholdQuiet) {
+ Word16 i;
+ Word16 barcThrQuiet;
+
+ for(i=0; i<numPb; i++) {
+ Word16 bv1, bv2;
+
+
+ if (i>0)
+ bv1 = (pbBarcVal[i] + pbBarcVal[i-1]) >> 1;
+ else
+ bv1 = pbBarcVal[i] >> 1;
+
+
+ if (i < (numPb - 1))
+ bv2 = (pbBarcVal[i] + pbBarcVal[i+1]) >> 1;
+ else {
+ bv2 = pbBarcVal[i];
+ }
+
+ bv1 = min((bv1 / BARC_SCALE), max_bark);
+ bv2 = min((bv2 / BARC_SCALE), max_bark);
+
+ barcThrQuiet = min(BARC_THR_QUIET[bv1], BARC_THR_QUIET[bv2]);
+
+
+ /*
+ we calculate
+ pow(10.0f,(float)(barcThrQuiet - ABS_LEV)*0.1)*(float)ABS_LOW*(pbOffset[i+1] - pbOffset[i]);
+ */
+
+ pbThresholdQuiet[i] = pow2_xy((((barcThrQuiet - ABS_LEV) * 100) +
+ LOG2_1000*(14+2*LOG_NORM_PCM)), LOG2_1000) * (pbOffset[i+1] - pbOffset[i]);
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: initSpreading
+* description: init energy spreading parameter
+*
+*****************************************************************************/
+static void initSpreading(Word16 numPb,
+ Word16 *pbBarcValue,
+ Word16 *pbMaskLoFactor,
+ Word16 *pbMaskHiFactor,
+ Word16 *pbMaskLoFactorSprEn,
+ Word16 *pbMaskHiFactorSprEn,
+ const Word32 bitrate,
+ const Word16 blockType)
+{
+ Word16 i;
+ Word16 maskLowSprEn, maskHighSprEn;
+
+
+ if (sub(blockType, SHORT_WINDOW) != 0) {
+ maskLowSprEn = maskLowSprEnLong;
+
+ if (bitrate > 22000)
+ maskHighSprEn = maskHighSprEnLong;
+ else
+ maskHighSprEn = maskHighSprEnLongLowBr;
+ }
+ else {
+ maskLowSprEn = maskLowSprEnShort;
+ maskHighSprEn = maskHighSprEnShort;
+ }
+
+ for(i=0; i<numPb; i++) {
+
+ if (i > 0) {
+ Word32 dbVal;
+ Word16 dbark = pbBarcValue[i] - pbBarcValue[i-1];
+
+ /*
+ we calulate pow(10.0f, -0.1*dbVal/BARC_SCALE)
+ */
+ dbVal = (maskHigh * dbark);
+ pbMaskHiFactor[i] = round16(pow2_xy(L_negate(dbVal), (Word32)LOG2_1000)); /* 0.301 log10(2) */
+
+ dbVal = (maskLow * dbark);
+ pbMaskLoFactor[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
+
+
+ dbVal = (maskHighSprEn * dbark);
+ pbMaskHiFactorSprEn[i] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
+ dbVal = (maskLowSprEn * dbark);
+ pbMaskLoFactorSprEn[i-1] = round16(pow2_xy(L_negate(dbVal),(Word32)LOG2_1000));
+ }
+ else {
+ pbMaskHiFactor[i] = 0;
+ pbMaskLoFactor[numPb-1] = 0;
+
+ pbMaskHiFactorSprEn[i] = 0;
+ pbMaskLoFactorSprEn[numPb-1] = 0;
+ }
+ }
+
+}
+
+
+/*****************************************************************************
+*
+* function name: initBarcValues
+* description: init bark value
+*
+*****************************************************************************/
+static void initBarcValues(Word16 numPb,
+ Word16 *pbOffset,
+ Word16 numLines,
+ Word32 samplingFrequency,
+ Word16 *pbBval)
+{
+ Word16 i;
+ Word16 pbBval0, pbBval1;
+
+ pbBval0 = 0;
+
+ for(i=0; i<numPb; i++){
+ pbBval1 = BarcLineValue(numLines, pbOffset[i+1], samplingFrequency);
+ pbBval[i] = (pbBval0 + pbBval1) >> 1;
+ pbBval0 = pbBval1;
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: initMinSnr
+* description: calculate min snr parameter
+* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)
+*
+*****************************************************************************/
+static void initMinSnr(const Word32 bitrate,
+ const Word32 samplerate,
+ const Word16 numLines,
+ const Word16 *sfbOffset,
+ const Word16 *pbBarcVal,
+ const Word16 sfbActive,
+ Word16 *sfbMinSnr)
+{
+ Word16 sfb;
+ Word16 barcWidth;
+ Word16 pePerWindow;
+ Word32 pePart;
+ Word32 snr;
+ Word16 pbVal0, pbVal1, shift;
+
+ /* relative number of active barks */
+
+
+ pePerWindow = bits2pe(extract_l((bitrate * numLines) / samplerate));
+
+ pbVal0 = 0;
+
+ for (sfb=0; sfb<sfbActive; sfb++) {
+
+ pbVal1 = (pbBarcVal[sfb] << 1) - pbVal0;
+ barcWidth = pbVal1 - pbVal0;
+ pbVal0 = pbVal1;
+
+ /* allow at least 2.4% of pe for each active barc */
+ pePart = ((pePerWindow * 24) * (max_bark * barcWidth)) /
+ (pbBarcVal[sfbActive-1] * (sfbOffset[sfb+1] - sfbOffset[sfb]));
+
+
+ pePart = min(pePart, 8400);
+ pePart = max(pePart, 1400);
+
+ /* minSnr(n) = 1/(2^sfbPemin(n)/w(n) - 1.5)*/
+ /* we add an offset of 2^16 to the pow functions */
+ /* 0xc000 = 1.5*(1 << 15)*/
+
+ snr = pow2_xy((pePart - 16*1000),1000) - 0x0000c000;
+
+ if(snr > 0x00008000)
+ {
+ shift = norm_l(snr);
+ snr = Div_32(0x00008000 << shift, snr << shift);
+ }
+ else
+ {
+ snr = 0x7fffffff;
+ }
+
+ /* upper limit is -1 dB */
+ snr = min(snr, c_maxsnr);
+ /* lower limit is -25 dB */
+ snr = max(snr, c_minsnr);
+ sfbMinSnr[sfb] = round16(snr);
+ }
+
+}
+
+/*****************************************************************************
+*
+* function name: InitPsyConfigurationLong
+* description: init long block psychoacoustic configuration
+*
+*****************************************************************************/
+Word16 InitPsyConfigurationLong(Word32 bitrate,
+ Word32 samplerate,
+ Word16 bandwidth,
+ PSY_CONFIGURATION_LONG *psyConf)
+{
+ Word32 samplerateindex;
+ Word16 sfbBarcVal[MAX_SFB_LONG];
+ Word16 sfb;
+
+ /*
+ init sfb table
+ */
+ samplerateindex = GetSRIndex(samplerate);
+ psyConf->sfbCnt = sfBandTotalLong[samplerateindex];
+ psyConf->sfbOffset = sfBandTabLong + sfBandTabLongOffset[samplerateindex];
+ psyConf->sampRateIdx = samplerateindex;
+
+ /*
+ calculate barc values for each pb
+ */
+ initBarcValues(psyConf->sfbCnt,
+ psyConf->sfbOffset,
+ psyConf->sfbOffset[psyConf->sfbCnt],
+ samplerate,
+ sfbBarcVal);
+
+ /*
+ init thresholds in quiet
+ */
+ initThrQuiet(psyConf->sfbCnt,
+ psyConf->sfbOffset,
+ sfbBarcVal,
+ psyConf->sfbThresholdQuiet);
+
+ /*
+ calculate spreading function
+ */
+ initSpreading(psyConf->sfbCnt,
+ sfbBarcVal,
+ psyConf->sfbMaskLowFactor,
+ psyConf->sfbMaskHighFactor,
+ psyConf->sfbMaskLowFactorSprEn,
+ psyConf->sfbMaskHighFactorSprEn,
+ bitrate,
+ LONG_WINDOW);
+
+ /*
+ init ratio
+ */
+ psyConf->ratio = c_ratio;
+
+ psyConf->maxAllowedIncreaseFactor = 2;
+ psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor; /* 0.01 *(1 << 15)*/
+
+ psyConf->clipEnergy = c_maxClipEnergyLong;
+ psyConf->lowpassLine = extract_l((bandwidth<<1) * FRAME_LEN_LONG / samplerate);
+
+ for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
+ if (sub(psyConf->sfbOffset[sfb], psyConf->lowpassLine) >= 0)
+ break;
+ }
+ psyConf->sfbActive = sfb;
+
+ /*
+ calculate minSnr
+ */
+ initMinSnr(bitrate,
+ samplerate,
+ psyConf->sfbOffset[psyConf->sfbCnt],
+ psyConf->sfbOffset,
+ sfbBarcVal,
+ psyConf->sfbActive,
+ psyConf->sfbMinSnr);
+
+
+ return(0);
+}
+
+/*****************************************************************************
+*
+* function name: InitPsyConfigurationShort
+* description: init short block psychoacoustic configuration
+*
+*****************************************************************************/
+Word16 InitPsyConfigurationShort(Word32 bitrate,
+ Word32 samplerate,
+ Word16 bandwidth,
+ PSY_CONFIGURATION_SHORT *psyConf)
+{
+ Word32 samplerateindex;
+ Word16 sfbBarcVal[MAX_SFB_SHORT];
+ Word16 sfb;
+ /*
+ init sfb table
+ */
+ samplerateindex = GetSRIndex(samplerate);
+ psyConf->sfbCnt = sfBandTotalShort[samplerateindex];
+ psyConf->sfbOffset = sfBandTabShort + sfBandTabShortOffset[samplerateindex];
+ psyConf->sampRateIdx = samplerateindex;
+ /*
+ calculate barc values for each pb
+ */
+ initBarcValues(psyConf->sfbCnt,
+ psyConf->sfbOffset,
+ psyConf->sfbOffset[psyConf->sfbCnt],
+ samplerate,
+ sfbBarcVal);
+
+ /*
+ init thresholds in quiet
+ */
+ initThrQuiet(psyConf->sfbCnt,
+ psyConf->sfbOffset,
+ sfbBarcVal,
+ psyConf->sfbThresholdQuiet);
+
+ /*
+ calculate spreading function
+ */
+ initSpreading(psyConf->sfbCnt,
+ sfbBarcVal,
+ psyConf->sfbMaskLowFactor,
+ psyConf->sfbMaskHighFactor,
+ psyConf->sfbMaskLowFactorSprEn,
+ psyConf->sfbMaskHighFactorSprEn,
+ bitrate,
+ SHORT_WINDOW);
+
+ /*
+ init ratio
+ */
+ psyConf->ratio = c_ratio;
+
+ psyConf->maxAllowedIncreaseFactor = 2;
+ psyConf->minRemainingThresholdFactor = c_minRemainingThresholdFactor;
+
+ psyConf->clipEnergy = c_maxClipEnergyShort;
+
+ psyConf->lowpassLine = extract_l(((bandwidth << 1) * FRAME_LEN_SHORT) / samplerate);
+
+ for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
+
+ if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine)
+ break;
+ }
+ psyConf->sfbActive = sfb;
+
+ /*
+ calculate minSnr
+ */
+ initMinSnr(bitrate,
+ samplerate,
+ psyConf->sfbOffset[psyConf->sfbCnt],
+ psyConf->sfbOffset,
+ sfbBarcVal,
+ psyConf->sfbActive,
+ psyConf->sfbMinSnr);
+
+ return(0);
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/psy_main.c b/media/libstagefright/codecs/aacenc/src/psy_main.c
new file mode 100644
index 0000000..8746a72
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/psy_main.c
@@ -0,0 +1,810 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: psy_main.c
+
+ Content: Psychoacoustic major functions
+
+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "psy_const.h"
+#include "block_switch.h"
+#include "transform.h"
+#include "spreading.h"
+#include "pre_echo_control.h"
+#include "band_nrg.h"
+#include "psy_configuration.h"
+#include "psy_data.h"
+#include "ms_stereo.h"
+#include "interface.h"
+#include "psy_main.h"
+#include "grp_data.h"
+#include "tns_func.h"
+#include "memalign.h"
+
+/* long start short stop */
+static Word16 blockType2windowShape[] = {KBD_WINDOW,SINE_WINDOW,SINE_WINDOW,KBD_WINDOW};
+
+/*
+ forward definitions
+*/
+static Word16 advancePsychLong(PSY_DATA* psyData,
+ TNS_DATA* tnsData,
+ PSY_CONFIGURATION_LONG *hPsyConfLong,
+ PSY_OUT_CHANNEL* psyOutChannel,
+ Word32 *pScratchTns,
+ const TNS_DATA *tnsData2,
+ const Word16 ch);
+
+static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
+ const PSY_CONFIGURATION_LONG *hPsyConfLong);
+
+static Word16 advancePsychShort(PSY_DATA* psyData,
+ TNS_DATA* tnsData,
+ const PSY_CONFIGURATION_SHORT *hPsyConfShort,
+ PSY_OUT_CHANNEL* psyOutChannel,
+ Word32 *pScratchTns,
+ const TNS_DATA *tnsData2,
+ const Word16 ch);
+
+static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
+ const PSY_CONFIGURATION_SHORT *hPsyConfShort);
+
+
+/*****************************************************************************
+*
+* function name: PsyNew
+* description: allocates memory for psychoacoustic
+* returns: an error code
+* input: pointer to a psych handle
+*
+*****************************************************************************/
+Word16 PsyNew(PSY_KERNEL *hPsy, Word32 nChan, VO_MEM_OPERATOR *pMemOP)
+{
+ Word16 i;
+ Word32 *mdctSpectrum;
+ Word32 *scratchTNS;
+ Word16 *mdctDelayBuffer;
+
+ mdctSpectrum = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
+ if(NULL == mdctSpectrum)
+ return 1;
+
+ scratchTNS = (Word32 *)mem_malloc(pMemOP, nChan * FRAME_LEN_LONG * sizeof(Word32), 32, VO_INDEX_ENC_AAC);
+ if(NULL == scratchTNS)
+ {
+ return 1;
+ }
+
+ mdctDelayBuffer = (Word16 *)mem_malloc(pMemOP, nChan * BLOCK_SWITCHING_OFFSET * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
+ if(NULL == mdctDelayBuffer)
+ {
+ return 1;
+ }
+
+ for (i=0; i<nChan; i++){
+ hPsy->psyData[i].mdctDelayBuffer = mdctDelayBuffer + i*BLOCK_SWITCHING_OFFSET;
+ hPsy->psyData[i].mdctSpectrum = mdctSpectrum + i*FRAME_LEN_LONG;
+ }
+
+ hPsy->pScratchTns = scratchTNS;
+
+ return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: PsyDelete
+* description: allocates memory for psychoacoustic
+* returns: an error code
+*
+*****************************************************************************/
+Word16 PsyDelete(PSY_KERNEL *hPsy, VO_MEM_OPERATOR *pMemOP)
+{
+ Word32 nch;
+
+ if(hPsy)
+ {
+ if(hPsy->psyData[0].mdctDelayBuffer)
+ mem_free(pMemOP, hPsy->psyData[0].mdctDelayBuffer, VO_INDEX_ENC_AAC);
+
+ if(hPsy->psyData[0].mdctSpectrum)
+ mem_free(pMemOP, hPsy->psyData[0].mdctSpectrum, VO_INDEX_ENC_AAC);
+
+ for (nch=0; nch<MAX_CHANNELS; nch++){
+ hPsy->psyData[nch].mdctDelayBuffer = NULL;
+ hPsy->psyData[nch].mdctSpectrum = NULL;
+ }
+
+ if(hPsy->pScratchTns)
+ {
+ mem_free(pMemOP, hPsy->pScratchTns, VO_INDEX_ENC_AAC);
+ hPsy->pScratchTns = NULL;
+ }
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: PsyOutNew
+* description: allocates memory for psyOut struc
+* returns: an error code
+* input: pointer to a psych handle
+*
+*****************************************************************************/
+Word16 PsyOutNew(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
+{
+ pMemOP->Set(VO_INDEX_ENC_AAC, hPsyOut, 0, sizeof(PSY_OUT));
+ /*
+ alloc some more stuff, tbd
+ */
+ return 0;
+}
+
+/*****************************************************************************
+*
+* function name: PsyOutDelete
+* description: allocates memory for psychoacoustic
+* returns: an error code
+*
+*****************************************************************************/
+Word16 PsyOutDelete(PSY_OUT *hPsyOut, VO_MEM_OPERATOR *pMemOP)
+{
+ hPsyOut=NULL;
+ return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: psyMainInit
+* description: initializes psychoacoustic
+* returns: an error code
+*
+*****************************************************************************/
+
+Word16 psyMainInit(PSY_KERNEL *hPsy,
+ Word32 sampleRate,
+ Word32 bitRate,
+ Word16 channels,
+ Word16 tnsMask,
+ Word16 bandwidth)
+{
+ Word16 ch, err;
+ Word32 channelBitRate = bitRate/channels;
+
+ err = InitPsyConfigurationLong(channelBitRate,
+ sampleRate,
+ bandwidth,
+ &(hPsy->psyConfLong));
+
+ if (!err) {
+ hPsy->sampleRateIdx = hPsy->psyConfLong.sampRateIdx;
+ err = InitTnsConfigurationLong(bitRate, sampleRate, channels,
+ &hPsy->psyConfLong.tnsConf, &hPsy->psyConfLong, tnsMask&2);
+ }
+
+ if (!err)
+ err = InitPsyConfigurationShort(channelBitRate,
+ sampleRate,
+ bandwidth,
+ &hPsy->psyConfShort);
+ if (!err) {
+ err = InitTnsConfigurationShort(bitRate, sampleRate, channels,
+ &hPsy->psyConfShort.tnsConf, &hPsy->psyConfShort, tnsMask&1);
+ }
+
+ if (!err)
+ for(ch=0;ch < channels;ch++){
+
+ InitBlockSwitching(&hPsy->psyData[ch].blockSwitchingControl,
+ bitRate, channels);
+
+ InitPreEchoControl(hPsy->psyData[ch].sfbThresholdnm1,
+ hPsy->psyConfLong.sfbCnt,
+ hPsy->psyConfLong.sfbThresholdQuiet);
+ hPsy->psyData[ch].mdctScalenm1 = 0;
+ }
+
+ return(err);
+}
+
+/*****************************************************************************
+*
+* function name: psyMain
+* description: psychoacoustic main function
+* returns: an error code
+*
+* This function assumes that enough input data is in the modulo buffer.
+*
+*****************************************************************************/
+
+Word16 psyMain(Word16 nChannels,
+ ELEMENT_INFO *elemInfo,
+ Word16 *timeSignal,
+ PSY_DATA psyData[MAX_CHANNELS],
+ TNS_DATA tnsData[MAX_CHANNELS],
+ PSY_CONFIGURATION_LONG *hPsyConfLong,
+ PSY_CONFIGURATION_SHORT *hPsyConfShort,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word32 *pScratchTns,
+ Word32 sampleRate)
+{
+ Word16 maxSfbPerGroup[MAX_CHANNELS];
+ Word16 mdctScalingArray[MAX_CHANNELS];
+
+ Word16 ch; /* counts through channels */
+ Word16 sfb; /* counts through scalefactor bands */
+ Word16 line; /* counts through lines */
+ Word16 channels;
+ Word16 maxScale;
+
+ channels = elemInfo->nChannelsInEl;
+ maxScale = 0;
+
+ /* block switching */
+ for(ch = 0; ch < channels; ch++) {
+ BlockSwitching(&psyData[ch].blockSwitchingControl,
+ timeSignal+elemInfo->ChannelIndex[ch],
+ sampleRate,
+ nChannels);
+ }
+
+ /* synch left and right block type */
+ SyncBlockSwitching(&psyData[0].blockSwitchingControl,
+ &psyData[1].blockSwitchingControl,
+ channels);
+
+ /* transform
+ and get maxScale (max mdctScaling) for all channels */
+ for(ch=0; ch<channels; ch++) {
+ Transform_Real(psyData[ch].mdctDelayBuffer,
+ timeSignal+elemInfo->ChannelIndex[ch],
+ nChannels,
+ psyData[ch].mdctSpectrum,
+ &(mdctScalingArray[ch]),
+ psyData[ch].blockSwitchingControl.windowSequence);
+ maxScale = max(maxScale, mdctScalingArray[ch]);
+ }
+
+ /* common scaling for all channels */
+ for (ch=0; ch<channels; ch++) {
+ Word16 scaleDiff = maxScale - mdctScalingArray[ch];
+
+ if (scaleDiff > 0) {
+ Word32 *Spectrum = psyData[ch].mdctSpectrum;
+ for(line=0; line<FRAME_LEN_LONG; line++) {
+ *Spectrum = (*Spectrum) >> scaleDiff;
+ Spectrum++;
+ }
+ }
+ psyData[ch].mdctScale = maxScale;
+ }
+
+ for (ch=0; ch<channels; ch++) {
+
+ if(psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW) {
+ /* update long block parameter */
+ advancePsychLong(&psyData[ch],
+ &tnsData[ch],
+ hPsyConfLong,
+ &psyOutChannel[ch],
+ pScratchTns,
+ &tnsData[1 - ch],
+ ch);
+
+ /* determine maxSfb */
+ for (sfb=hPsyConfLong->sfbCnt-1; sfb>=0; sfb--) {
+ for (line=hPsyConfLong->sfbOffset[sfb+1] - 1; line>=hPsyConfLong->sfbOffset[sfb]; line--) {
+
+ if (psyData[ch].mdctSpectrum[line] != 0) break;
+ }
+ if (line >= hPsyConfLong->sfbOffset[sfb]) break;
+ }
+ maxSfbPerGroup[ch] = sfb + 1;
+
+ /* Calc bandwise energies for mid and side channel
+ Do it only if 2 channels exist */
+
+ if (ch == 1)
+ advancePsychLongMS(psyData, hPsyConfLong);
+ }
+ else {
+ advancePsychShort(&psyData[ch],
+ &tnsData[ch],
+ hPsyConfShort,
+ &psyOutChannel[ch],
+ pScratchTns,
+ &tnsData[1 - ch],
+ ch);
+
+ /* Calc bandwise energies for mid and side channel
+ Do it only if 2 channels exist */
+
+ if (ch == 1)
+ advancePsychShortMS (psyData, hPsyConfShort);
+ }
+ }
+
+ /* group short data */
+ for(ch=0; ch<channels; ch++) {
+
+ if (psyData[ch].blockSwitchingControl.windowSequence == SHORT_WINDOW) {
+ groupShortData(psyData[ch].mdctSpectrum,
+ pScratchTns,
+ &psyData[ch].sfbThreshold,
+ &psyData[ch].sfbEnergy,
+ &psyData[ch].sfbEnergyMS,
+ &psyData[ch].sfbSpreadedEnergy,
+ hPsyConfShort->sfbCnt,
+ hPsyConfShort->sfbOffset,
+ hPsyConfShort->sfbMinSnr,
+ psyOutElement->groupedSfbOffset[ch],
+ &maxSfbPerGroup[ch],
+ psyOutElement->groupedSfbMinSnr[ch],
+ psyData[ch].blockSwitchingControl.noOfGroups,
+ psyData[ch].blockSwitchingControl.groupLen);
+ }
+ }
+
+
+#if (MAX_CHANNELS>1)
+ /*
+ stereo Processing
+ */
+ if (channels == 2) {
+ psyOutElement->toolsInfo.msDigest = MS_NONE;
+ maxSfbPerGroup[0] = maxSfbPerGroup[1] = max(maxSfbPerGroup[0], maxSfbPerGroup[1]);
+
+
+ if (psyData[0].blockSwitchingControl.windowSequence != SHORT_WINDOW)
+ MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
+ psyData[1].sfbEnergy.sfbLong,
+ psyData[0].sfbEnergyMS.sfbLong,
+ psyData[1].sfbEnergyMS.sfbLong,
+ psyData[0].mdctSpectrum,
+ psyData[1].mdctSpectrum,
+ psyData[0].sfbThreshold.sfbLong,
+ psyData[1].sfbThreshold.sfbLong,
+ psyData[0].sfbSpreadedEnergy.sfbLong,
+ psyData[1].sfbSpreadedEnergy.sfbLong,
+ (Word16*)&psyOutElement->toolsInfo.msDigest,
+ (Word16*)psyOutElement->toolsInfo.msMask,
+ hPsyConfLong->sfbCnt,
+ hPsyConfLong->sfbCnt,
+ maxSfbPerGroup[0],
+ (const Word16*)hPsyConfLong->sfbOffset);
+ else
+ MsStereoProcessing(psyData[0].sfbEnergy.sfbLong,
+ psyData[1].sfbEnergy.sfbLong,
+ psyData[0].sfbEnergyMS.sfbLong,
+ psyData[1].sfbEnergyMS.sfbLong,
+ psyData[0].mdctSpectrum,
+ psyData[1].mdctSpectrum,
+ psyData[0].sfbThreshold.sfbLong,
+ psyData[1].sfbThreshold.sfbLong,
+ psyData[0].sfbSpreadedEnergy.sfbLong,
+ psyData[1].sfbSpreadedEnergy.sfbLong,
+ (Word16*)&psyOutElement->toolsInfo.msDigest,
+ (Word16*)psyOutElement->toolsInfo.msMask,
+ psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
+ hPsyConfShort->sfbCnt,
+ maxSfbPerGroup[0],
+ (const Word16*)psyOutElement->groupedSfbOffset[0]);
+ }
+
+#endif /* (MAX_CHANNELS>1) */
+
+ /*
+ build output
+ */
+ for(ch=0;ch<channels;ch++) {
+
+ if (psyData[ch].blockSwitchingControl.windowSequence != SHORT_WINDOW)
+ BuildInterface(psyData[ch].mdctSpectrum,
+ psyData[ch].mdctScale,
+ &psyData[ch].sfbThreshold,
+ &psyData[ch].sfbEnergy,
+ &psyData[ch].sfbSpreadedEnergy,
+ psyData[ch].sfbEnergySum,
+ psyData[ch].sfbEnergySumMS,
+ psyData[ch].blockSwitchingControl.windowSequence,
+ blockType2windowShape[psyData[ch].blockSwitchingControl.windowSequence],
+ hPsyConfLong->sfbCnt,
+ hPsyConfLong->sfbOffset,
+ maxSfbPerGroup[ch],
+ hPsyConfLong->sfbMinSnr,
+ psyData[ch].blockSwitchingControl.noOfGroups,
+ psyData[ch].blockSwitchingControl.groupLen,
+ &psyOutChannel[ch]);
+ else
+ BuildInterface(psyData[ch].mdctSpectrum,
+ psyData[ch].mdctScale,
+ &psyData[ch].sfbThreshold,
+ &psyData[ch].sfbEnergy,
+ &psyData[ch].sfbSpreadedEnergy,
+ psyData[ch].sfbEnergySum,
+ psyData[ch].sfbEnergySumMS,
+ SHORT_WINDOW,
+ SINE_WINDOW,
+ psyData[0].blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
+ psyOutElement->groupedSfbOffset[ch],
+ maxSfbPerGroup[ch],
+ psyOutElement->groupedSfbMinSnr[ch],
+ psyData[ch].blockSwitchingControl.noOfGroups,
+ psyData[ch].blockSwitchingControl.groupLen,
+ &psyOutChannel[ch]);
+ }
+
+ return(0); /* no error */
+}
+
+/*****************************************************************************
+*
+* function name: advancePsychLong
+* description: psychoacoustic for long blocks
+*
+*****************************************************************************/
+
+static Word16 advancePsychLong(PSY_DATA* psyData,
+ TNS_DATA* tnsData,
+ PSY_CONFIGURATION_LONG *hPsyConfLong,
+ PSY_OUT_CHANNEL* psyOutChannel,
+ Word32 *pScratchTns,
+ const TNS_DATA* tnsData2,
+ const Word16 ch)
+{
+ Word32 i;
+ Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
+ Word32 clipEnergy = hPsyConfLong->clipEnergy >> normEnergyShift;
+ Word32 *data0, *data1, tdata;
+
+ /* low pass */
+ data0 = psyData->mdctSpectrum + hPsyConfLong->lowpassLine;
+ for(i=hPsyConfLong->lowpassLine; i<FRAME_LEN_LONG; i++) {
+ *data0++ = 0;
+ }
+
+ /* Calc sfb-bandwise mdct-energies for left and right channel */
+ CalcBandEnergy( psyData->mdctSpectrum,
+ hPsyConfLong->sfbOffset,
+ hPsyConfLong->sfbActive,
+ psyData->sfbEnergy.sfbLong,
+ &psyData->sfbEnergySum.sfbLong);
+
+ /*
+ TNS detect
+ */
+ TnsDetect(tnsData,
+ hPsyConfLong->tnsConf,
+ pScratchTns,
+ (const Word16*)hPsyConfLong->sfbOffset,
+ psyData->mdctSpectrum,
+ 0,
+ psyData->blockSwitchingControl.windowSequence,
+ psyData->sfbEnergy.sfbLong);
+
+ /* TnsSync */
+ if (ch == 1) {
+ TnsSync(tnsData,
+ tnsData2,
+ hPsyConfLong->tnsConf,
+ 0,
+ psyData->blockSwitchingControl.windowSequence);
+ }
+
+ /* Tns Encoder */
+ TnsEncode(&psyOutChannel->tnsInfo,
+ tnsData,
+ hPsyConfLong->sfbCnt,
+ hPsyConfLong->tnsConf,
+ hPsyConfLong->lowpassLine,
+ psyData->mdctSpectrum,
+ 0,
+ psyData->blockSwitchingControl.windowSequence);
+
+ /* first part of threshold calculation */
+ data0 = psyData->sfbEnergy.sfbLong;
+ data1 = psyData->sfbThreshold.sfbLong;
+ for (i=hPsyConfLong->sfbCnt; i; i--) {
+ tdata = L_mpy_ls(*data0++, hPsyConfLong->ratio);
+ *data1++ = min(tdata, clipEnergy);
+ }
+
+ /* Calc sfb-bandwise mdct-energies for left and right channel again */
+ if (tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive!=0) {
+ Word16 tnsStartBand = hPsyConfLong->tnsConf.tnsStartBand;
+ CalcBandEnergy( psyData->mdctSpectrum,
+ hPsyConfLong->sfbOffset+tnsStartBand,
+ hPsyConfLong->sfbActive - tnsStartBand,
+ psyData->sfbEnergy.sfbLong+tnsStartBand,
+ &psyData->sfbEnergySum.sfbLong);
+
+ data0 = psyData->sfbEnergy.sfbLong;
+ tdata = psyData->sfbEnergySum.sfbLong;
+ for (i=0; i<tnsStartBand; i++)
+ tdata += *data0++;
+
+ psyData->sfbEnergySum.sfbLong = tdata;
+ }
+
+
+ /* spreading energy */
+ SpreadingMax(hPsyConfLong->sfbCnt,
+ hPsyConfLong->sfbMaskLowFactor,
+ hPsyConfLong->sfbMaskHighFactor,
+ psyData->sfbThreshold.sfbLong);
+
+ /* threshold in quiet */
+ data0 = psyData->sfbThreshold.sfbLong;
+ data1 = hPsyConfLong->sfbThresholdQuiet;
+ for (i=hPsyConfLong->sfbCnt; i; i--)
+ {
+ *data0 = max(*data0, (*data1 >> normEnergyShift));
+ data0++; data1++;
+ }
+
+ /* preecho control */
+ if (psyData->blockSwitchingControl.windowSequence == STOP_WINDOW) {
+ data0 = psyData->sfbThresholdnm1;
+ for (i=hPsyConfLong->sfbCnt; i; i--) {
+ *data0++ = MAX_32;
+ }
+ psyData->mdctScalenm1 = 0;
+ }
+
+ PreEchoControl( psyData->sfbThresholdnm1,
+ hPsyConfLong->sfbCnt,
+ hPsyConfLong->maxAllowedIncreaseFactor,
+ hPsyConfLong->minRemainingThresholdFactor,
+ psyData->sfbThreshold.sfbLong,
+ psyData->mdctScale,
+ psyData->mdctScalenm1);
+ psyData->mdctScalenm1 = psyData->mdctScale;
+
+
+ if (psyData->blockSwitchingControl.windowSequence== START_WINDOW) {
+ data0 = psyData->sfbThresholdnm1;
+ for (i=hPsyConfLong->sfbCnt; i; i--) {
+ *data0++ = MAX_32;
+ }
+ psyData->mdctScalenm1 = 0;
+ }
+
+ /* apply tns mult table on cb thresholds */
+ ApplyTnsMultTableToRatios(hPsyConfLong->tnsConf.tnsRatioPatchLowestCb,
+ hPsyConfLong->tnsConf.tnsStartBand,
+ tnsData->dataRaw.tnsLong.subBlockInfo,
+ psyData->sfbThreshold.sfbLong);
+
+
+ /* spreaded energy */
+ data0 = psyData->sfbSpreadedEnergy.sfbLong;
+ data1 = psyData->sfbEnergy.sfbLong;
+ for (i=hPsyConfLong->sfbCnt; i; i--) {
+ //psyData->sfbSpreadedEnergy.sfbLong[i] = psyData->sfbEnergy.sfbLong[i];
+ *data0++ = *data1++;
+ }
+
+ /* spreading energy */
+ SpreadingMax(hPsyConfLong->sfbCnt,
+ hPsyConfLong->sfbMaskLowFactorSprEn,
+ hPsyConfLong->sfbMaskHighFactorSprEn,
+ psyData->sfbSpreadedEnergy.sfbLong);
+
+ return 0;
+}
+
+/*****************************************************************************
+*
+* function name: advancePsychLongMS
+* description: update mdct-energies for left add or minus right channel
+* for long block
+*
+*****************************************************************************/
+static Word16 advancePsychLongMS (PSY_DATA psyData[MAX_CHANNELS],
+ const PSY_CONFIGURATION_LONG *hPsyConfLong)
+{
+ CalcBandEnergyMS(psyData[0].mdctSpectrum,
+ psyData[1].mdctSpectrum,
+ hPsyConfLong->sfbOffset,
+ hPsyConfLong->sfbActive,
+ psyData[0].sfbEnergyMS.sfbLong,
+ &psyData[0].sfbEnergySumMS.sfbLong,
+ psyData[1].sfbEnergyMS.sfbLong,
+ &psyData[1].sfbEnergySumMS.sfbLong);
+
+ return 0;
+}
+
+
+/*****************************************************************************
+*
+* function name: advancePsychShort
+* description: psychoacoustic for short blocks
+*
+*****************************************************************************/
+
+static Word16 advancePsychShort(PSY_DATA* psyData,
+ TNS_DATA* tnsData,
+ const PSY_CONFIGURATION_SHORT *hPsyConfShort,
+ PSY_OUT_CHANNEL* psyOutChannel,
+ Word32 *pScratchTns,
+ const TNS_DATA *tnsData2,
+ const Word16 ch)
+{
+ Word32 w;
+ Word32 normEnergyShift = (psyData->mdctScale + 1) << 1; /* in reference code, mdct spectrum must be multipied with 2, so +1 */
+ Word32 clipEnergy = hPsyConfShort->clipEnergy >> normEnergyShift;
+ Word32 wOffset = 0;
+ Word32 *data0, *data1;
+
+ for(w = 0; w < TRANS_FAC; w++) {
+ Word32 i, tdata;
+
+ /* low pass */
+ data0 = psyData->mdctSpectrum + wOffset + hPsyConfShort->lowpassLine;
+ for(i=hPsyConfShort->lowpassLine; i<FRAME_LEN_SHORT; i++){
+ *data0++ = 0;
+ }
+
+ /* Calc sfb-bandwise mdct-energies for left and right channel */
+ CalcBandEnergy( psyData->mdctSpectrum+wOffset,
+ hPsyConfShort->sfbOffset,
+ hPsyConfShort->sfbActive,
+ psyData->sfbEnergy.sfbShort[w],
+ &psyData->sfbEnergySum.sfbShort[w]);
+ /*
+ TNS
+ */
+ TnsDetect(tnsData,
+ hPsyConfShort->tnsConf,
+ pScratchTns,
+ (const Word16*)hPsyConfShort->sfbOffset,
+ psyData->mdctSpectrum+wOffset,
+ w,
+ psyData->blockSwitchingControl.windowSequence,
+ psyData->sfbEnergy.sfbShort[w]);
+
+ /* TnsSync */
+ if (ch == 1) {
+ TnsSync(tnsData,
+ tnsData2,
+ hPsyConfShort->tnsConf,
+ w,
+ psyData->blockSwitchingControl.windowSequence);
+ }
+
+ TnsEncode(&psyOutChannel->tnsInfo,
+ tnsData,
+ hPsyConfShort->sfbCnt,
+ hPsyConfShort->tnsConf,
+ hPsyConfShort->lowpassLine,
+ psyData->mdctSpectrum+wOffset,
+ w,
+ psyData->blockSwitchingControl.windowSequence);
+
+ /* first part of threshold calculation */
+ data0 = psyData->sfbThreshold.sfbShort[w];
+ data1 = psyData->sfbEnergy.sfbShort[w];
+ for (i=hPsyConfShort->sfbCnt; i; i--) {
+ tdata = L_mpy_ls(*data1++, hPsyConfShort->ratio);
+ *data0++ = min(tdata, clipEnergy);
+ }
+
+ /* Calc sfb-bandwise mdct-energies for left and right channel again */
+ if (tnsData->dataRaw.tnsShort.subBlockInfo[w].tnsActive != 0) {
+ Word16 tnsStartBand = hPsyConfShort->tnsConf.tnsStartBand;
+ CalcBandEnergy( psyData->mdctSpectrum+wOffset,
+ hPsyConfShort->sfbOffset+tnsStartBand,
+ (hPsyConfShort->sfbActive - tnsStartBand),
+ psyData->sfbEnergy.sfbShort[w]+tnsStartBand,
+ &psyData->sfbEnergySum.sfbShort[w]);
+
+ tdata = psyData->sfbEnergySum.sfbShort[w];
+ data0 = psyData->sfbEnergy.sfbShort[w];
+ for (i=tnsStartBand; i; i--)
+ tdata += *data0++;
+
+ psyData->sfbEnergySum.sfbShort[w] = tdata;
+ }
+
+ /* spreading */
+ SpreadingMax(hPsyConfShort->sfbCnt,
+ hPsyConfShort->sfbMaskLowFactor,
+ hPsyConfShort->sfbMaskHighFactor,
+ psyData->sfbThreshold.sfbShort[w]);
+
+
+ /* threshold in quiet */
+ data0 = psyData->sfbThreshold.sfbShort[w];
+ data1 = hPsyConfShort->sfbThresholdQuiet;
+ for (i=hPsyConfShort->sfbCnt; i; i--)
+ {
+ *data0 = max(*data0, (*data1 >> normEnergyShift));
+
+ data0++; data1++;
+ }
+
+
+ /* preecho */
+ PreEchoControl( psyData->sfbThresholdnm1,
+ hPsyConfShort->sfbCnt,
+ hPsyConfShort->maxAllowedIncreaseFactor,
+ hPsyConfShort->minRemainingThresholdFactor,
+ psyData->sfbThreshold.sfbShort[w],
+ psyData->mdctScale,
+ w==0 ? psyData->mdctScalenm1 : psyData->mdctScale);
+
+ /* apply tns mult table on cb thresholds */
+ ApplyTnsMultTableToRatios( hPsyConfShort->tnsConf.tnsRatioPatchLowestCb,
+ hPsyConfShort->tnsConf.tnsStartBand,
+ tnsData->dataRaw.tnsShort.subBlockInfo[w],
+ psyData->sfbThreshold.sfbShort[w]);
+
+ /* spreaded energy */
+ data0 = psyData->sfbSpreadedEnergy.sfbShort[w];
+ data1 = psyData->sfbEnergy.sfbShort[w];
+ for (i=hPsyConfShort->sfbCnt; i; i--) {
+ *data0++ = *data1++;
+ }
+ SpreadingMax(hPsyConfShort->sfbCnt,
+ hPsyConfShort->sfbMaskLowFactorSprEn,
+ hPsyConfShort->sfbMaskHighFactorSprEn,
+ psyData->sfbSpreadedEnergy.sfbShort[w]);
+
+ wOffset += FRAME_LEN_SHORT;
+ } /* for TRANS_FAC */
+
+ psyData->mdctScalenm1 = psyData->mdctScale;
+
+ return 0;
+}
+
+/*****************************************************************************
+*
+* function name: advancePsychShortMS
+* description: update mdct-energies for left add or minus right channel
+* for short block
+*
+*****************************************************************************/
+static Word16 advancePsychShortMS (PSY_DATA psyData[MAX_CHANNELS],
+ const PSY_CONFIGURATION_SHORT *hPsyConfShort)
+{
+ Word32 w, wOffset;
+ wOffset = 0;
+ for(w=0; w<TRANS_FAC; w++) {
+ CalcBandEnergyMS(psyData[0].mdctSpectrum+wOffset,
+ psyData[1].mdctSpectrum+wOffset,
+ hPsyConfShort->sfbOffset,
+ hPsyConfShort->sfbActive,
+ psyData[0].sfbEnergyMS.sfbShort[w],
+ &psyData[0].sfbEnergySumMS.sfbShort[w],
+ psyData[1].sfbEnergyMS.sfbShort[w],
+ &psyData[1].sfbEnergySumMS.sfbShort[w]);
+ wOffset += FRAME_LEN_SHORT;
+ }
+
+ return 0;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/qc_main.c b/media/libstagefright/codecs/aacenc/src/qc_main.c
new file mode 100644
index 0000000..a568020
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/qc_main.c
@@ -0,0 +1,580 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: qc_main.c
+
+ Content: Quantizing & coding functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "qc_main.h"
+#include "quantize.h"
+#include "interface.h"
+#include "adj_thr.h"
+#include "sf_estim.h"
+#include "stat_bits.h"
+#include "bit_cnt.h"
+#include "dyn_bits.h"
+#include "channel_map.h"
+#include "memalign.h"
+
+
+typedef enum{
+ FRAME_LEN_BYTES_MODULO = 1,
+ FRAME_LEN_BYTES_INT = 2
+}FRAME_LEN_RESULT_MODE;
+
+static const Word16 maxFillElemBits = 7 + 270*8;
+
+/* forward declarations */
+
+static Word16 calcMaxValueInSfb(Word16 sfbCnt,
+ Word16 maxSfbPerGroup,
+ Word16 sfbPerGroup,
+ Word16 sfbOffset[MAX_GROUPED_SFB],
+ Word16 quantSpectrum[FRAME_LEN_LONG],
+ UWord16 maxValue[MAX_GROUPED_SFB]);
+
+
+/*****************************************************************************
+*
+* function name: calcFrameLen
+* description: estimate the frame length according the bitrates
+*
+*****************************************************************************/
+static Word16 calcFrameLen(Word32 bitRate,
+ Word32 sampleRate,
+ FRAME_LEN_RESULT_MODE mode)
+{
+
+ Word32 result;
+ Word32 quot;
+
+ result = (FRAME_LEN_LONG >> 3) * bitRate;
+ quot = result / sampleRate;
+
+
+ if (mode == FRAME_LEN_BYTES_MODULO) {
+ result -= quot * sampleRate;
+ }
+ else { /* FRAME_LEN_BYTES_INT */
+ result = quot;
+ }
+
+ return result;
+}
+
+/*****************************************************************************
+*
+* function name:framePadding
+* description: Calculates if padding is needed for actual frame
+* returns: paddingOn or not
+*
+*****************************************************************************/
+static Word16 framePadding(Word32 bitRate,
+ Word32 sampleRate,
+ Word32 *paddingRest)
+{
+ Word16 paddingOn;
+ Word16 difference;
+
+ paddingOn = 0;
+
+ difference = calcFrameLen( bitRate,
+ sampleRate,
+ FRAME_LEN_BYTES_MODULO );
+ *paddingRest = *paddingRest - difference;
+
+
+ if (*paddingRest <= 0 ) {
+ paddingOn = 1;
+ *paddingRest = *paddingRest + sampleRate;
+ }
+
+ return paddingOn;
+}
+
+
+/*********************************************************************************
+*
+* function name: QCOutNew
+* description: init qcout parameter
+* returns: 0 if success
+*
+**********************************************************************************/
+
+Word16 QCOutNew(QC_OUT *hQC, Word16 nChannels, VO_MEM_OPERATOR *pMemOP)
+{
+ Word32 i;
+ Word16 *quantSpec;
+ Word16 *scf;
+ UWord16 *maxValueInSfb;
+
+ quantSpec = (Word16 *)mem_malloc(pMemOP, nChannels * FRAME_LEN_LONG * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
+ if(NULL == quantSpec)
+ return 1;
+ scf = (Word16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(Word16), 32, VO_INDEX_ENC_AAC);
+ if(NULL == scf)
+ {
+ return 1;
+ }
+ maxValueInSfb = (UWord16 *)mem_malloc(pMemOP, nChannels * MAX_GROUPED_SFB * sizeof(UWord16), 32, VO_INDEX_ENC_AAC);
+ if(NULL == maxValueInSfb)
+ {
+ return 1;
+ }
+
+ for (i=0; i<nChannels; i++) {
+ hQC->qcChannel[i].quantSpec = quantSpec + i*FRAME_LEN_LONG;
+
+ hQC->qcChannel[i].maxValueInSfb = maxValueInSfb + i*MAX_GROUPED_SFB;
+
+ hQC->qcChannel[i].scf = scf + i*MAX_GROUPED_SFB;
+ }
+
+ return 0;
+}
+
+
+/*********************************************************************************
+*
+* function name: QCOutDelete
+* description: unint qcout parameter
+* returns: 0 if success
+*
+**********************************************************************************/
+void QCOutDelete(QC_OUT* hQC, VO_MEM_OPERATOR *pMemOP)
+{
+ Word32 i;
+ if(hQC)
+ {
+ if(hQC->qcChannel[0].quantSpec);
+ mem_free(pMemOP, hQC->qcChannel[0].quantSpec, VO_INDEX_ENC_AAC);
+
+ if(hQC->qcChannel[0].maxValueInSfb)
+ mem_free(pMemOP, hQC->qcChannel[0].maxValueInSfb, VO_INDEX_ENC_AAC);
+
+ if(hQC->qcChannel[0].scf)
+ mem_free(pMemOP, hQC->qcChannel[0].scf, VO_INDEX_ENC_AAC);
+
+ for (i=0; i<MAX_CHANNELS; i++) {
+ hQC->qcChannel[i].quantSpec = NULL;
+
+ hQC->qcChannel[i].maxValueInSfb = NULL;
+
+ hQC->qcChannel[i].scf = NULL;
+ }
+ }
+}
+
+/*********************************************************************************
+*
+* function name: QCNew
+* description: set QC to zero
+* returns: 0 if success
+*
+**********************************************************************************/
+Word16 QCNew(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP)
+{
+ pMemOP->Set(VO_INDEX_ENC_AAC, hQC,0,sizeof(QC_STATE));
+
+ return (0);
+}
+
+/*********************************************************************************
+*
+* function name: QCDelete
+* description: unint qcout parameter
+*
+**********************************************************************************/
+void QCDelete(QC_STATE *hQC, VO_MEM_OPERATOR *pMemOP)
+{
+
+ /*
+ nothing to do
+ */
+ hQC=NULL;
+}
+
+/*********************************************************************************
+*
+* function name: QCInit
+* description: init QD parameter
+* returns: 0 if success
+*
+**********************************************************************************/
+Word16 QCInit(QC_STATE *hQC,
+ struct QC_INIT *init)
+{
+ hQC->nChannels = init->elInfo->nChannelsInEl;
+ hQC->maxBitsTot = init->maxBits;
+ hQC->bitResTot = sub(init->bitRes, init->averageBits);
+ hQC->averageBitsTot = init->averageBits;
+ hQC->maxBitFac = init->maxBitFac;
+
+ hQC->padding.paddingRest = init->padding.paddingRest;
+
+ hQC->globStatBits = 3; /* for ID_END */
+
+ /* channel elements init */
+ InitElementBits(&hQC->elementBits,
+ *init->elInfo,
+ init->bitrate,
+ init->averageBits,
+ hQC->globStatBits);
+
+ /* threshold parameter init */
+ AdjThrInit(&hQC->adjThr,
+ init->meanPe,
+ hQC->elementBits.chBitrate);
+
+ return 0;
+}
+
+
+/*********************************************************************************
+*
+* function name: QCMain
+* description: quantization and coding the spectrum
+* returns: 0 if success
+*
+**********************************************************************************/
+Word16 QCMain(QC_STATE* hQC,
+ ELEMENT_BITS* elBits,
+ ATS_ELEMENT* adjThrStateElement,
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS], /* may be modified in-place */
+ PSY_OUT_ELEMENT* psyOutElement,
+ QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS], /* out */
+ QC_OUT_ELEMENT* qcOutElement,
+ Word16 nChannels,
+ Word16 ancillaryDataBytes)
+{
+ Word16 maxChDynBits[MAX_CHANNELS];
+ Word16 chBitDistribution[MAX_CHANNELS];
+ Word32 ch;
+
+ if (elBits->bitResLevel < 0) {
+ return -1;
+ }
+
+ if (elBits->bitResLevel > elBits->maxBitResBits) {
+ return -1;
+ }
+
+ qcOutElement->staticBitsUsed = countStaticBitdemand(psyOutChannel,
+ psyOutElement,
+ nChannels,
+ qcOutElement->adtsUsed);
+
+
+ if (ancillaryDataBytes) {
+ qcOutElement->ancBitsUsed = 7 + (ancillaryDataBytes << 3);
+
+ if (ancillaryDataBytes >= 15)
+ qcOutElement->ancBitsUsed = qcOutElement->ancBitsUsed + 8;
+ }
+ else {
+ qcOutElement->ancBitsUsed = 0;
+ }
+
+ CalcFormFactor(hQC->logSfbFormFactor, hQC->sfbNRelevantLines, hQC->logSfbEnergy, psyOutChannel, nChannels);
+
+ /*adjust thresholds for the desired bitrate */
+ AdjustThresholds(&hQC->adjThr,
+ adjThrStateElement,
+ psyOutChannel,
+ psyOutElement,
+ chBitDistribution,
+ hQC->logSfbEnergy,
+ hQC->sfbNRelevantLines,
+ qcOutElement,
+ elBits,
+ nChannels,
+ hQC->maxBitFac);
+
+ /*estimate scale factors */
+ EstimateScaleFactors(psyOutChannel,
+ qcOutChannel,
+ hQC->logSfbEnergy,
+ hQC->logSfbFormFactor,
+ hQC->sfbNRelevantLines,
+ nChannels);
+
+ /* condition to prevent empty bitreservoir */
+ for (ch = 0; ch < nChannels; ch++) {
+ Word32 maxDynBits;
+ maxDynBits = elBits->averageBits + elBits->bitResLevel - 7; /* -7 bec. of align bits */
+ maxDynBits = maxDynBits - qcOutElement->staticBitsUsed + qcOutElement->ancBitsUsed;
+ maxChDynBits[ch] = extract_l(chBitDistribution[ch] * maxDynBits / 1000);
+ }
+
+ qcOutElement->dynBitsUsed = 0;
+ for (ch = 0; ch < nChannels; ch++) {
+ Word32 chDynBits;
+ Flag constraintsFulfilled;
+ Word32 iter;
+ iter = 0;
+ do {
+ constraintsFulfilled = 1;
+
+ QuantizeSpectrum(psyOutChannel[ch].sfbCnt,
+ psyOutChannel[ch].maxSfbPerGroup,
+ psyOutChannel[ch].sfbPerGroup,
+ psyOutChannel[ch].sfbOffsets,
+ psyOutChannel[ch].mdctSpectrum,
+ qcOutChannel[ch].globalGain,
+ qcOutChannel[ch].scf,
+ qcOutChannel[ch].quantSpec);
+
+ if (calcMaxValueInSfb(psyOutChannel[ch].sfbCnt,
+ psyOutChannel[ch].maxSfbPerGroup,
+ psyOutChannel[ch].sfbPerGroup,
+ psyOutChannel[ch].sfbOffsets,
+ qcOutChannel[ch].quantSpec,
+ qcOutChannel[ch].maxValueInSfb) > MAX_QUANT) {
+ constraintsFulfilled = 0;
+ }
+
+ chDynBits = dynBitCount(qcOutChannel[ch].quantSpec,
+ qcOutChannel[ch].maxValueInSfb,
+ qcOutChannel[ch].scf,
+ psyOutChannel[ch].windowSequence,
+ psyOutChannel[ch].sfbCnt,
+ psyOutChannel[ch].maxSfbPerGroup,
+ psyOutChannel[ch].sfbPerGroup,
+ psyOutChannel[ch].sfbOffsets,
+ &qcOutChannel[ch].sectionData);
+
+ if (chDynBits >= maxChDynBits[ch]) {
+ constraintsFulfilled = 0;
+ }
+
+ if (!constraintsFulfilled) {
+ qcOutChannel[ch].globalGain = qcOutChannel[ch].globalGain + 1;
+ }
+
+ iter = iter + 1;
+
+ } while(!constraintsFulfilled);
+
+ qcOutElement->dynBitsUsed = qcOutElement->dynBitsUsed + chDynBits;
+
+ qcOutChannel[ch].mdctScale = psyOutChannel[ch].mdctScale;
+ qcOutChannel[ch].groupingMask = psyOutChannel[ch].groupingMask;
+ qcOutChannel[ch].windowShape = psyOutChannel[ch].windowShape;
+ }
+
+ /* save dynBitsUsed for correction of bits2pe relation */
+ AdjThrUpdate(adjThrStateElement, qcOutElement->dynBitsUsed);
+
+ {
+ Word16 bitResSpace = elBits->maxBitResBits - elBits->bitResLevel;
+ Word16 deltaBitRes = elBits->averageBits -
+ (qcOutElement->staticBitsUsed +
+ qcOutElement->dynBitsUsed + qcOutElement->ancBitsUsed);
+
+ qcOutElement->fillBits = max(0, (deltaBitRes - bitResSpace));
+ }
+
+ return 0; /* OK */
+}
+
+
+/*********************************************************************************
+*
+* function name: calcMaxValueInSfb
+* description: search the max Spectrum in one sfb
+*
+**********************************************************************************/
+static Word16 calcMaxValueInSfb(Word16 sfbCnt,
+ Word16 maxSfbPerGroup,
+ Word16 sfbPerGroup,
+ Word16 sfbOffset[MAX_GROUPED_SFB],
+ Word16 quantSpectrum[FRAME_LEN_LONG],
+ UWord16 maxValue[MAX_GROUPED_SFB])
+{
+ Word16 sfbOffs, sfb;
+ Word16 maxValueAll;
+
+ maxValueAll = 0;
+
+ for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
+ for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
+ Word16 line;
+ Word16 maxThisSfb;
+ maxThisSfb = 0;
+
+ for (line = sfbOffset[sfbOffs+sfb]; line < sfbOffset[sfbOffs+sfb+1]; line++) {
+ Word16 absVal;
+ absVal = abs_s(quantSpectrum[line]);
+ maxThisSfb = max(maxThisSfb, absVal);
+ }
+
+ maxValue[sfbOffs+sfb] = maxThisSfb;
+ maxValueAll = max(maxValueAll, maxThisSfb);
+ }
+ }
+ return maxValueAll;
+}
+
+
+/*********************************************************************************
+*
+* function name: updateBitres
+* description: update bitreservoir
+*
+**********************************************************************************/
+void updateBitres(QC_STATE* qcKernel,
+ QC_OUT* qcOut)
+
+{
+ ELEMENT_BITS *elBits;
+
+ qcKernel->bitResTot = 0;
+
+ elBits = &qcKernel->elementBits;
+
+
+ if (elBits->averageBits > 0) {
+ /* constant bitrate */
+ Word16 bitsUsed;
+ bitsUsed = (qcOut->qcElement.staticBitsUsed + qcOut->qcElement.dynBitsUsed) +
+ (qcOut->qcElement.ancBitsUsed + qcOut->qcElement.fillBits);
+ elBits->bitResLevel = elBits->bitResLevel + (elBits->averageBits - bitsUsed);
+ qcKernel->bitResTot = qcKernel->bitResTot + elBits->bitResLevel;
+ }
+ else {
+ /* variable bitrate */
+ elBits->bitResLevel = elBits->maxBits;
+ qcKernel->bitResTot = qcKernel->maxBitsTot;
+ }
+}
+
+/*********************************************************************************
+*
+* function name: FinalizeBitConsumption
+* description: count bits used
+*
+**********************************************************************************/
+Word16 FinalizeBitConsumption(QC_STATE *qcKernel,
+ QC_OUT* qcOut)
+{
+ Word32 nFullFillElem;
+ Word32 totFillBits;
+ Word16 diffBits;
+ Word16 bitsUsed;
+
+ totFillBits = 0;
+
+ qcOut->totStaticBitsUsed = qcKernel->globStatBits;
+ qcOut->totStaticBitsUsed += qcOut->qcElement.staticBitsUsed;
+ qcOut->totDynBitsUsed = qcOut->qcElement.dynBitsUsed;
+ qcOut->totAncBitsUsed = qcOut->qcElement.ancBitsUsed;
+ qcOut->totFillBits = qcOut->qcElement.fillBits;
+
+ if (qcOut->qcElement.fillBits) {
+ totFillBits += qcOut->qcElement.fillBits;
+ }
+
+ nFullFillElem = (max((qcOut->totFillBits - 1), 0) / maxFillElemBits) * maxFillElemBits;
+
+ qcOut->totFillBits = qcOut->totFillBits - nFullFillElem;
+
+ /* check fill elements */
+
+ if (qcOut->totFillBits > 0) {
+ /* minimum Fillelement contains 7 (TAG + byte cnt) bits */
+ qcOut->totFillBits = max(7, qcOut->totFillBits);
+ /* fill element size equals n*8 + 7 */
+ qcOut->totFillBits = qcOut->totFillBits + ((8 - ((qcOut->totFillBits - 7) & 0x0007)) & 0x0007);
+ }
+
+ qcOut->totFillBits = qcOut->totFillBits + nFullFillElem;
+
+ /* now distribute extra fillbits and alignbits over channel elements */
+ qcOut->alignBits = 7 - ((qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed +
+ qcOut->totAncBitsUsed + qcOut->totFillBits - 1) & 0x0007);
+
+
+ if ( (qcOut->alignBits + qcOut->totFillBits - totFillBits == 8) &&
+ (qcOut->totFillBits > 8))
+ qcOut->totFillBits = qcOut->totFillBits - 8;
+
+
+ diffBits = qcOut->alignBits + qcOut->totFillBits - totFillBits;
+
+ if(diffBits>=0) {
+ qcOut->qcElement.fillBits += diffBits;
+ }
+
+ bitsUsed = qcOut->totDynBitsUsed + qcOut->totStaticBitsUsed + qcOut->totAncBitsUsed;
+ bitsUsed = bitsUsed + qcOut->totFillBits + qcOut->alignBits;
+
+ if (bitsUsed > qcKernel->maxBitsTot) {
+ return -1;
+ }
+ return bitsUsed;
+}
+
+
+/*********************************************************************************
+*
+* function name: AdjustBitrate
+* description: adjusts framelength via padding on a frame to frame basis,
+* to achieve a bitrate that demands a non byte aligned
+* framelength
+* return: errorcode
+*
+**********************************************************************************/
+Word16 AdjustBitrate(QC_STATE *hQC,
+ Word32 bitRate, /* total bitrate */
+ Word32 sampleRate) /* output sampling rate */
+{
+ Word16 paddingOn;
+ Word16 frameLen;
+ Word16 codeBits;
+ Word16 codeBitsLast;
+
+ /* Do we need a extra padding byte? */
+ paddingOn = framePadding(bitRate,
+ sampleRate,
+ &hQC->padding.paddingRest);
+
+ /* frame length */
+ frameLen = paddingOn + calcFrameLen(bitRate,
+ sampleRate,
+ FRAME_LEN_BYTES_INT);
+
+ frameLen = frameLen << 3;
+ codeBitsLast = hQC->averageBitsTot - hQC->globStatBits;
+ codeBits = frameLen - hQC->globStatBits;
+
+ /* calculate bits for every channel element */
+ if (codeBits != codeBitsLast) {
+ Word16 totalBits = 0;
+
+ hQC->elementBits.averageBits = (hQC->elementBits.relativeBits * codeBits) >> 16; /* relativeBits was scaled down by 2 */
+ totalBits += hQC->elementBits.averageBits;
+
+ hQC->elementBits.averageBits = hQC->elementBits.averageBits + (codeBits - totalBits);
+ }
+
+ hQC->averageBitsTot = frameLen;
+
+ return 0;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/quantize.c b/media/libstagefright/codecs/aacenc/src/quantize.c
new file mode 100644
index 0000000..205f167
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/quantize.c
@@ -0,0 +1,445 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: quantize.c
+
+ Content: quantization functions
+
+*******************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "quantize.h"
+#include "aac_rom.h"
+
+#define MANT_DIGITS 9
+#define MANT_SIZE (1<<MANT_DIGITS)
+
+static const Word32 XROUND = 0x33e425af; /* final rounding constant (-0.0946f+ 0.5f) */
+
+
+/*****************************************************************************
+*
+* function name:pow34
+* description: calculate $x^{\frac{3}{4}}, for 0.5 < x < 1.0$.
+*
+*****************************************************************************/
+__inline Word32 pow34(Word32 x)
+{
+ /* index table using MANT_DIGITS bits, but mask out the sign bit and the MSB
+ which is always one */
+ return mTab_3_4[(x >> (INT_BITS-2-MANT_DIGITS)) & (MANT_SIZE-1)];
+}
+
+
+/*****************************************************************************
+*
+* function name:quantizeSingleLine
+* description: quantizes spectrum
+* quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
+*
+*****************************************************************************/
+static Word16 quantizeSingleLine(const Word16 gain, const Word32 absSpectrum)
+{
+ Word32 e, minusFinalExp, finalShift;
+ Word32 x;
+ Word16 qua = 0;
+
+
+ if (absSpectrum) {
+ e = norm_l(absSpectrum);
+ x = pow34(absSpectrum << e);
+
+ /* calculate the final fractional exponent times 16 (was 3*(4*e + gain) + (INT_BITS-1)*16) */
+ minusFinalExp = (e << 2) + gain;
+ minusFinalExp = (minusFinalExp << 1) + minusFinalExp;
+ minusFinalExp = minusFinalExp + ((INT_BITS-1) << 4);
+
+ /* separate the exponent into a shift, and a multiply */
+ finalShift = minusFinalExp >> 4;
+
+ if (finalShift < INT_BITS) {
+ x = L_mpy_wx(x, pow2tominusNover16[minusFinalExp & 15]);
+
+ x += XROUND >> (INT_BITS - finalShift);
+
+ /* shift and quantize */
+ finalShift--;
+
+ if(finalShift >= 0)
+ x >>= finalShift;
+ else
+ x <<= (-finalShift);
+
+ qua = saturate(x);
+ }
+ }
+
+ return qua;
+}
+
+/*****************************************************************************
+*
+* function name:quantizeLines
+* description: quantizes spectrum lines
+* quaSpectrum = mdctSpectrum^3/4*2^(-(3/16)*gain)
+* input: global gain, number of lines to process, spectral data
+* output: quantized spectrum
+*
+*****************************************************************************/
+static void quantizeLines(const Word16 gain,
+ const Word16 noOfLines,
+ const Word32 *mdctSpectrum,
+ Word16 *quaSpectrum)
+{
+ Word32 line;
+ Word32 m = gain&3;
+ Word32 g = (gain >> 2) + 4;
+ Word32 mdctSpeL;
+ Word16 *pquat;
+ /* gain&3 */
+
+ pquat = quantBorders[m];
+
+ g += 16;
+
+ if(g >= 0)
+ {
+ for (line=0; line<noOfLines; line++) {
+ Word32 qua;
+ qua = 0;
+
+ mdctSpeL = mdctSpectrum[line];
+
+ if (mdctSpeL) {
+ Word32 sa;
+ Word32 saShft;
+
+ sa = L_abs(mdctSpeL);
+ //saShft = L_shr(sa, 16 + g);
+ saShft = sa >> g;
+
+ if (saShft > pquat[0]) {
+
+ if (saShft < pquat[1]) {
+
+ qua = mdctSpeL>0 ? 1 : -1;
+ }
+ else {
+
+ if (saShft < pquat[2]) {
+
+ qua = mdctSpeL>0 ? 2 : -2;
+ }
+ else {
+
+ if (saShft < pquat[3]) {
+
+ qua = mdctSpeL>0 ? 3 : -3;
+ }
+ else {
+ qua = quantizeSingleLine(gain, sa);
+ /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
+
+ if (mdctSpeL < 0)
+ qua = -qua;
+ }
+ }
+ }
+ }
+ }
+ quaSpectrum[line] = qua ;
+ }
+ }
+ else
+ {
+ for (line=0; line<noOfLines; line++) {
+ Word32 qua;
+ qua = 0;
+
+ mdctSpeL = mdctSpectrum[line];
+
+ if (mdctSpeL) {
+ Word32 sa;
+ Word32 saShft;
+
+ sa = L_abs(mdctSpeL);
+ saShft = sa << g;
+
+ if (saShft > pquat[0]) {
+
+ if (saShft < pquat[1]) {
+
+ qua = mdctSpeL>0 ? 1 : -1;
+ }
+ else {
+
+ if (saShft < pquat[2]) {
+
+ qua = mdctSpeL>0 ? 2 : -2;
+ }
+ else {
+
+ if (saShft < pquat[3]) {
+
+ qua = mdctSpeL>0 ? 3 : -3;
+ }
+ else {
+ qua = quantizeSingleLine(gain, sa);
+ /* adjust the sign. Since 0 < qua < 1, this cannot overflow. */
+
+ if (mdctSpeL < 0)
+ qua = -qua;
+ }
+ }
+ }
+ }
+ }
+ quaSpectrum[line] = qua ;
+ }
+ }
+
+}
+
+
+/*****************************************************************************
+*
+* function name:iquantizeLines
+* description: iquantizes spectrum lines without sign
+* mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain)
+* input: global gain, number of lines to process,quantized spectrum
+* output: spectral data
+*
+*****************************************************************************/
+static void iquantizeLines(const Word16 gain,
+ const Word16 noOfLines,
+ const Word16 *quantSpectrum,
+ Word32 *mdctSpectrum)
+{
+ Word32 iquantizermod;
+ Word32 iquantizershift;
+ Word32 line;
+
+ iquantizermod = gain & 3;
+ iquantizershift = gain >> 2;
+
+ for (line=0; line<noOfLines; line++) {
+
+ if( quantSpectrum[line] != 0 ) {
+ Word32 accu;
+ Word32 ex;
+ Word32 tabIndex;
+ Word32 specExp;
+ Word32 s,t;
+
+ accu = quantSpectrum[line];
+
+ ex = norm_l(accu);
+ accu = accu << ex;
+ specExp = INT_BITS-1 - ex;
+
+ tabIndex = (accu >> (INT_BITS-2-MANT_DIGITS)) & (~MANT_SIZE);
+
+ /* calculate "mantissa" ^4/3 */
+ s = mTab_4_3[tabIndex];
+
+ /* get approperiate exponent multiplier for specExp^3/4 combined with scfMod */
+ t = specExpMantTableComb_enc[iquantizermod][specExp];
+
+ /* multiply "mantissa" ^4/3 with exponent multiplier */
+ accu = MULHIGH(s, t);
+
+ /* get approperiate exponent shifter */
+ specExp = specExpTableComb_enc[iquantizermod][specExp];
+
+ specExp += iquantizershift + 1;
+ if(specExp >= 0)
+ mdctSpectrum[line] = accu << specExp;
+ else
+ mdctSpectrum[line] = accu >> (-specExp);
+ }
+ else {
+ mdctSpectrum[line] = 0;
+ }
+ }
+}
+
+/*****************************************************************************
+*
+* function name: QuantizeSpectrum
+* description: quantizes the entire spectrum
+* returns:
+* input: number of scalefactor bands to be quantized, ...
+* output: quantized spectrum
+*
+*****************************************************************************/
+void QuantizeSpectrum(Word16 sfbCnt,
+ Word16 maxSfbPerGroup,
+ Word16 sfbPerGroup,
+ Word16 *sfbOffset,
+ Word32 *mdctSpectrum,
+ Word16 globalGain,
+ Word16 *scalefactors,
+ Word16 *quantizedSpectrum)
+{
+ Word32 sfbOffs, sfb;
+
+ for(sfbOffs=0;sfbOffs<sfbCnt;sfbOffs+=sfbPerGroup) {
+ Word32 sfbNext ;
+ for (sfb = 0; sfb < maxSfbPerGroup; sfb = sfbNext) {
+ Word16 scalefactor = scalefactors[sfbOffs+sfb];
+ /* coalesce sfbs with the same scalefactor */
+ for (sfbNext = sfb+1;
+ sfbNext < maxSfbPerGroup && scalefactor == scalefactors[sfbOffs+sfbNext];
+ sfbNext++) ;
+
+ quantizeLines(globalGain - scalefactor,
+ sfbOffset[sfbOffs+sfbNext] - sfbOffset[sfbOffs+sfb],
+ mdctSpectrum + sfbOffset[sfbOffs+sfb],
+ quantizedSpectrum + sfbOffset[sfbOffs+sfb]);
+ }
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name:calcSfbDist
+* description: quantizes and requantizes lines to calculate distortion
+* input: number of lines to be quantized, ...
+* output: distortion
+*
+*****************************************************************************/
+Word32 calcSfbDist(const Word32 *spec,
+ Word16 sfbWidth,
+ Word16 gain)
+{
+ Word32 line;
+ Word32 dist;
+ Word32 m = gain&3;
+ Word32 g = (gain >> 2) + 4;
+ Word32 g2 = (g << 1) + 1;
+ Word16 *pquat, *repquat;
+ /* gain&3 */
+
+ pquat = quantBorders[m];
+ repquat = quantRecon[m];
+
+ dist = 0;
+ g += 16;
+ if(g2 < 0 && g >= 0)
+ {
+ g2 = -g2;
+ for(line=0; line<sfbWidth; line++) {
+ if (spec[line]) {
+ Word32 diff;
+ Word32 distSingle;
+ Word32 sa;
+ Word32 saShft;
+ sa = L_abs(spec[line]);
+ //saShft = round16(L_shr(sa, g));
+ //saShft = L_shr(sa, 16+g);
+ saShft = sa >> g;
+
+ if (saShft < pquat[0]) {
+ distSingle = (saShft * saShft) >> g2;
+ }
+ else {
+
+ if (saShft < pquat[1]) {
+ diff = saShft - repquat[0];
+ distSingle = (diff * diff) >> g2;
+ }
+ else {
+
+ if (saShft < pquat[2]) {
+ diff = saShft - repquat[1];
+ distSingle = (diff * diff) >> g2;
+ }
+ else {
+
+ if (saShft < pquat[3]) {
+ diff = saShft - repquat[2];
+ distSingle = (diff * diff) >> g2;
+ }
+ else {
+ Word16 qua = quantizeSingleLine(gain, sa);
+ Word32 iqval, diff32;
+ /* now that we have quantized x, re-quantize it. */
+ iquantizeLines(gain, 1, &qua, &iqval);
+ diff32 = sa - iqval;
+ distSingle = fixmul(diff32, diff32);
+ }
+ }
+ }
+ }
+
+ dist = L_add(dist, distSingle);
+ }
+ }
+ }
+ else
+ {
+ for(line=0; line<sfbWidth; line++) {
+ if (spec[line]) {
+ Word32 diff;
+ Word32 distSingle;
+ Word32 sa;
+ Word32 saShft;
+ sa = L_abs(spec[line]);
+ //saShft = round16(L_shr(sa, g));
+ saShft = L_shr(sa, g);
+
+ if (saShft < pquat[0]) {
+ distSingle = L_shl((saShft * saShft), g2);
+ }
+ else {
+
+ if (saShft < pquat[1]) {
+ diff = saShft - repquat[0];
+ distSingle = L_shl((diff * diff), g2);
+ }
+ else {
+
+ if (saShft < pquat[2]) {
+ diff = saShft - repquat[1];
+ distSingle = L_shl((diff * diff), g2);
+ }
+ else {
+
+ if (saShft < pquat[3]) {
+ diff = saShft - repquat[2];
+ distSingle = L_shl((diff * diff), g2);
+ }
+ else {
+ Word16 qua = quantizeSingleLine(gain, sa);
+ Word32 iqval, diff32;
+ /* now that we have quantized x, re-quantize it. */
+ iquantizeLines(gain, 1, &qua, &iqval);
+ diff32 = sa - iqval;
+ distSingle = fixmul(diff32, diff32);
+ }
+ }
+ }
+ }
+ dist = L_add(dist, distSingle);
+ }
+ }
+ }
+
+ return dist;
+}
diff --git a/media/libstagefright/codecs/aacenc/src/sf_estim.c b/media/libstagefright/codecs/aacenc/src/sf_estim.c
new file mode 100644
index 0000000..d34b365
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/sf_estim.c
@@ -0,0 +1,882 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: sf_estim.c
+
+ Content: Scale factor estimation functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "sf_estim.h"
+#include "quantize.h"
+#include "bit_cnt.h"
+#include "aac_rom.h"
+
+static const Word16 MAX_SCF_DELTA = 60;
+
+/*!
+constants reference in comments
+
+ C0 = 6.75f;
+ C1 = -69.33295f; -16/3*log(MAX_QUANT+0.5-logCon)/log(2)
+ C2 = 4.0f;
+ C3 = 2.66666666f;
+
+ PE_C1 = 3.0f; log(8.0)/log(2)
+ PE_C2 = 1.3219281f; log(2.5)/log(2)
+ PE_C3 = 0.5593573f; 1-C2/C1
+
+*/
+
+#define FF_SQRT_BITS 7
+#define FF_SQRT_TABLE_SIZE (1<<FF_SQRT_BITS - 1<<(FF_SQRT_BITS-2))
+#define COEF08_31 0x66666666 /* 0.8*(1 << 31) */
+#define PE_C1_8 24 /* PE_C1*8 */
+#define PE_C2_16 21 /* PE_C2*8/PE_C3 */
+#define PE_SCALE 0x059a /* 0.7 * (1 << (15 - 1 - 3))*/
+
+#define SCALE_ESTIMATE_COEF 0x5555 /* (8.8585/(4*log2(10))) * (1 << 15)*/
+
+/*********************************************************************************
+*
+* function name: formfac_sqrt
+* description: calculates sqrt(x)/256
+*
+**********************************************************************************/
+__inline Word32 formfac_sqrt(Word32 x)
+{
+ Word32 y;
+ Word32 preshift, postshift;
+
+
+ if (x==0) return 0;
+ preshift = norm_l(x) - (INT_BITS-1-FF_SQRT_BITS);
+ postshift = preshift >> 1;
+ preshift = postshift << 1;
+ postshift = postshift + 8; /* sqrt/256 */
+ if(preshift >= 0)
+ y = x << preshift; /* now 1/4 <= y < 1 */
+ else
+ y = x >> (-preshift);
+ y = formfac_sqrttable[y-32];
+
+ if(postshift >= 0)
+ y = y >> postshift;
+ else
+ y = y << (-postshift);
+
+ return y;
+}
+
+
+/*********************************************************************************
+*
+* function name: CalcFormFactorChannel
+* description: calculate the form factor one channel
+* ffac(n) = sqrt(abs(X(k)) + sqrt(abs(X(k+1)) + ....
+*
+**********************************************************************************/
+static void
+CalcFormFactorChannel(Word16 *logSfbFormFactor,
+ Word16 *sfbNRelevantLines,
+ Word16 *logSfbEnergy,
+ PSY_OUT_CHANNEL *psyOutChan)
+{
+ Word32 sfbw, sfbw1;
+ Word32 i, j;
+ Word32 sfbOffs, sfb, shift;
+
+ sfbw = sfbw1 = 0;
+ for (sfbOffs=0; sfbOffs<psyOutChan->sfbCnt; sfbOffs+=psyOutChan->sfbPerGroup){
+ for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
+ i = sfbOffs+sfb;
+
+ if (psyOutChan->sfbEnergy[i] > psyOutChan->sfbThreshold[i]) {
+ Word32 accu, avgFormFactor,iSfbWidth;
+ Word32 *mdctSpec;
+ sfbw = psyOutChan->sfbOffsets[i+1] - psyOutChan->sfbOffsets[i];
+ iSfbWidth = invSBF[(sfbw >> 2) - 1];
+ mdctSpec = psyOutChan->mdctSpectrum + psyOutChan->sfbOffsets[i];
+ accu = 0;
+ /* calc sum of sqrt(spec) */
+ for (j=sfbw; j; j--) {
+ accu += formfac_sqrt(L_abs(*mdctSpec)); mdctSpec++;
+ }
+ logSfbFormFactor[i] = iLog4(accu);
+ logSfbEnergy[i] = iLog4(psyOutChan->sfbEnergy[i]);
+ avgFormFactor = fixmul(rsqrt(psyOutChan->sfbEnergy[i],INT_BITS), iSfbWidth);
+ avgFormFactor = rsqrt((Word32)avgFormFactor,INT_BITS) >> 10;
+ /* result is multiplied by 4 */
+ if(avgFormFactor)
+ sfbNRelevantLines[i] = accu / avgFormFactor;
+ else
+ sfbNRelevantLines[i] = 0x7fff;
+ }
+ else {
+ /* set number of lines to zero */
+ sfbNRelevantLines[i] = 0;
+ }
+ }
+ }
+}
+
+/*********************************************************************************
+*
+* function name: improveScf
+* description: find better scalefactor with analysis by synthesis
+*
+**********************************************************************************/
+static Word16 improveScf(Word32 *spec,
+ Word16 sfbWidth,
+ Word32 thresh,
+ Word16 scf,
+ Word16 minScf,
+ Word32 *dist,
+ Word16 *minScfCalculated)
+{
+ Word32 cnt;
+ Word32 sfbDist;
+ Word32 scfBest;
+ Word32 thresh125 = L_add(thresh, (thresh >> 2));
+
+ scfBest = scf;
+
+ /* calc real distortion */
+ sfbDist = calcSfbDist(spec, sfbWidth, scf);
+ *minScfCalculated = scf;
+ if(!sfbDist)
+ return scfBest;
+
+ if (sfbDist > thresh125) {
+ Word32 scfEstimated;
+ Word32 sfbDistBest;
+ scfEstimated = scf;
+ sfbDistBest = sfbDist;
+
+ cnt = 0;
+ while (sfbDist > thresh125 && (cnt < 3)) {
+
+ scf = scf + 1;
+ sfbDist = calcSfbDist(spec, sfbWidth, scf);
+
+ if (sfbDist < sfbDistBest) {
+ scfBest = scf;
+ sfbDistBest = sfbDist;
+ }
+ cnt = cnt + 1;
+ }
+ cnt = 0;
+ scf = scfEstimated;
+ sfbDist = sfbDistBest;
+ while ((sfbDist > thresh125) && (cnt < 1) && (scf > minScf)) {
+
+ scf = scf - 1;
+ sfbDist = calcSfbDist(spec, sfbWidth, scf);
+
+ if (sfbDist < sfbDistBest) {
+ scfBest = scf;
+ sfbDistBest = sfbDist;
+ }
+ *minScfCalculated = scf;
+ cnt = cnt + 1;
+ }
+ *dist = sfbDistBest;
+ }
+ else {
+ Word32 sfbDistBest;
+ Word32 sfbDistAllowed;
+ Word32 thresh08 = fixmul(COEF08_31, thresh);
+ sfbDistBest = sfbDist;
+
+ if (sfbDist < thresh08)
+ sfbDistAllowed = sfbDist;
+ else
+ sfbDistAllowed = thresh08;
+ for (cnt=0; cnt<3; cnt++) {
+ scf = scf + 1;
+ sfbDist = calcSfbDist(spec, sfbWidth, scf);
+
+ if (fixmul(COEF08_31,sfbDist) < sfbDistAllowed) {
+ *minScfCalculated = scfBest + 1;
+ scfBest = scf;
+ sfbDistBest = sfbDist;
+ }
+ }
+ *dist = sfbDistBest;
+ }
+
+ /* return best scalefactor */
+ return scfBest;
+}
+
+/*********************************************************************************
+*
+* function name: countSingleScfBits
+* description: count single scf bits in huffum
+*
+**********************************************************************************/
+static Word16 countSingleScfBits(Word16 scf, Word16 scfLeft, Word16 scfRight)
+{
+ Word16 scfBits;
+
+ scfBits = bitCountScalefactorDelta(scfLeft - scf) +
+ bitCountScalefactorDelta(scf - scfRight);
+
+ return scfBits;
+}
+
+/*********************************************************************************
+*
+* function name: calcSingleSpecPe
+* description: ldRatio = log2(en(n)) - 0,375*scfGain(n)
+* nbits = 0.7*nLines*ldRation for ldRation >= c1
+* nbits = 0.7*nLines*(c2 + c3*ldRatio) for ldRation < c1
+*
+**********************************************************************************/
+static Word16 calcSingleSpecPe(Word16 scf, Word16 sfbConstPePart, Word16 nLines)
+{
+ Word32 specPe;
+ Word32 ldRatio;
+ Word32 scf3;
+
+ ldRatio = sfbConstPePart << 3; /* (sfbConstPePart -0.375*scf)*8 */
+ scf3 = scf + scf + scf;
+ ldRatio = ldRatio - scf3;
+
+ if (ldRatio < PE_C1_8) {
+ /* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
+ ldRatio = (ldRatio + PE_C2_16) >> 1;
+ }
+ specPe = nLines * ldRatio;
+ specPe = (specPe * PE_SCALE) >> 14;
+
+ return saturate(specPe);
+}
+
+
+/*********************************************************************************
+*
+* function name: countScfBitsDiff
+* description: count different scf bits used
+*
+**********************************************************************************/
+static Word16 countScfBitsDiff(Word16 *scfOld, Word16 *scfNew,
+ Word16 sfbCnt, Word16 startSfb, Word16 stopSfb)
+{
+ Word32 scfBitsDiff;
+ Word32 sfb, sfbLast;
+ Word32 sfbPrev, sfbNext;
+
+ scfBitsDiff = 0;
+ sfb = 0;
+
+ /* search for first relevant sfb */
+ sfbLast = startSfb;
+ while (sfbLast < stopSfb && scfOld[sfbLast] == VOAAC_SHRT_MIN) {
+
+ sfbLast = sfbLast + 1;
+ }
+ /* search for previous relevant sfb and count diff */
+ sfbPrev = startSfb - 1;
+ while ((sfbPrev>=0) && scfOld[sfbPrev] == VOAAC_SHRT_MIN) {
+
+ sfbPrev = sfbPrev - 1;
+ }
+
+ if (sfbPrev>=0) {
+ scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbPrev] - scfNew[sfbLast]) -
+ bitCountScalefactorDelta(scfOld[sfbPrev] - scfOld[sfbLast]);
+ }
+ /* now loop through all sfbs and count diffs of relevant sfbs */
+ for (sfb=sfbLast+1; sfb<stopSfb; sfb++) {
+
+ if (scfOld[sfb] != VOAAC_SHRT_MIN) {
+ scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfb]) -
+ bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfb]);
+ sfbLast = sfb;
+ }
+ }
+ /* search for next relevant sfb and count diff */
+ sfbNext = stopSfb;
+ while (sfbNext < sfbCnt && scfOld[sfbNext] == VOAAC_SHRT_MIN) {
+
+ sfbNext = sfbNext + 1;
+ }
+
+ if (sfbNext < sfbCnt)
+ scfBitsDiff += bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfbNext]) -
+ bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfbNext]);
+
+ return saturate(scfBitsDiff);
+}
+
+static Word16 calcSpecPeDiff(Word16 *scfOld,
+ Word16 *scfNew,
+ Word16 *sfbConstPePart,
+ Word16 *logSfbEnergy,
+ Word16 *logSfbFormFactor,
+ Word16 *sfbNRelevantLines,
+ Word16 startSfb,
+ Word16 stopSfb)
+{
+ Word32 specPeDiff;
+ Word32 sfb;
+
+ specPeDiff = 0;
+
+ /* loop through all sfbs and count pe difference */
+ for (sfb=startSfb; sfb<stopSfb; sfb++) {
+
+
+ if (scfOld[sfb] != VOAAC_SHRT_MIN) {
+ Word32 ldRatioOld, ldRatioNew;
+ Word32 scf3;
+
+
+ if (sfbConstPePart[sfb] == MIN_16) {
+ sfbConstPePart[sfb] = ((logSfbEnergy[sfb] -
+ logSfbFormFactor[sfb]) + 11-8*4+3) >> 2;
+ }
+
+
+ ldRatioOld = sfbConstPePart[sfb] << 3;
+ scf3 = scfOld[sfb] + scfOld[sfb] + scfOld[sfb];
+ ldRatioOld = ldRatioOld - scf3;
+ ldRatioNew = sfbConstPePart[sfb] << 3;
+ scf3 = scfNew[sfb] + scfNew[sfb] + scfNew[sfb];
+ ldRatioNew = ldRatioNew - scf3;
+
+ if (ldRatioOld < PE_C1_8) {
+ /* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
+ ldRatioOld = (ldRatioOld + PE_C2_16) >> 1;
+ }
+
+ if (ldRatioNew < PE_C1_8) {
+ /* 21 : 2*8*PE_C2, 2*PE_C3 ~ 1*/
+ ldRatioNew = (ldRatioNew + PE_C2_16) >> 1;
+ }
+
+ specPeDiff += sfbNRelevantLines[sfb] * (ldRatioNew - ldRatioOld);
+ }
+ }
+
+ specPeDiff = (specPeDiff * PE_SCALE) >> 14;
+
+ return saturate(specPeDiff);
+}
+
+
+/*********************************************************************************
+*
+* function name: assimilateSingleScf
+* description: searched for single scalefactor bands, where the number of bits gained
+* by using a smaller scfgain(n) is greater than the estimated increased
+* bit demand
+*
+**********************************************************************************/
+static void assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan,
+ Word16 *scf,
+ Word16 *minScf,
+ Word32 *sfbDist,
+ Word16 *sfbConstPePart,
+ Word16 *logSfbEnergy,
+ Word16 *logSfbFormFactor,
+ Word16 *sfbNRelevantLines,
+ Word16 *minScfCalculated,
+ Flag restartOnSuccess)
+{
+ Word32 sfbLast, sfbAct, sfbNext, scfAct, scfMin;
+ Word16 *scfLast, *scfNext;
+ Word32 sfbPeOld, sfbPeNew;
+ Word32 sfbDistNew;
+ Word32 j;
+ Flag success;
+ Word16 deltaPe, deltaPeNew, deltaPeTmp;
+ Word16 *prevScfLast = psyOutChan->prevScfLast;
+ Word16 *prevScfNext = psyOutChan->prevScfNext;
+ Word16 *deltaPeLast = psyOutChan->deltaPeLast;
+ Flag updateMinScfCalculated;
+
+ success = 0;
+ deltaPe = 0;
+
+ for(j=0;j<psyOutChan->sfbCnt;j++){
+ prevScfLast[j] = MAX_16;
+ prevScfNext[j] = MAX_16;
+ deltaPeLast[j] = MAX_16;
+ }
+
+ sfbLast = -1;
+ sfbAct = -1;
+ sfbNext = -1;
+ scfLast = 0;
+ scfNext = 0;
+ scfMin = MAX_16;
+ do {
+ /* search for new relevant sfb */
+ sfbNext = sfbNext + 1;
+ while (sfbNext < psyOutChan->sfbCnt && scf[sfbNext] == MIN_16) {
+
+ sfbNext = sfbNext + 1;
+ }
+
+ if ((sfbLast>=0) && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) {
+ /* relevant scfs to the left and to the right */
+ scfAct = scf[sfbAct];
+ scfLast = scf + sfbLast;
+ scfNext = scf + sfbNext;
+ scfMin = min(*scfLast, *scfNext);
+ }
+ else {
+
+ if (sfbLast == -1 && (sfbAct>=0) && sfbNext < psyOutChan->sfbCnt) {
+ /* first relevant scf */
+ scfAct = scf[sfbAct];
+ scfLast = &scfAct;
+ scfNext = scf + sfbNext;
+ scfMin = *scfNext;
+ }
+ else {
+
+ if ((sfbLast>=0) && (sfbAct>=0) && sfbNext == psyOutChan->sfbCnt) {
+ /* last relevant scf */
+ scfAct = scf[sfbAct];
+ scfLast = scf + sfbLast;
+ scfNext = &scfAct;
+ scfMin = *scfLast;
+ }
+ }
+ }
+
+ if (sfbAct>=0)
+ scfMin = max(scfMin, minScf[sfbAct]);
+
+ if ((sfbAct >= 0) &&
+ (sfbLast>=0 || sfbNext < psyOutChan->sfbCnt) &&
+ scfAct > scfMin &&
+ (*scfLast != prevScfLast[sfbAct] ||
+ *scfNext != prevScfNext[sfbAct] ||
+ deltaPe < deltaPeLast[sfbAct])) {
+ success = 0;
+
+ /* estimate required bits for actual scf */
+ if (sfbConstPePart[sfbAct] == MIN_16) {
+ sfbConstPePart[sfbAct] = logSfbEnergy[sfbAct] -
+ logSfbFormFactor[sfbAct] + 11-8*4; /* 4*log2(6.75) - 32 */
+
+ if (sfbConstPePart[sfbAct] < 0)
+ sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] + 3;
+ sfbConstPePart[sfbAct] = sfbConstPePart[sfbAct] >> 2;
+ }
+
+ sfbPeOld = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) +
+ countSingleScfBits(scfAct, *scfLast, *scfNext);
+ deltaPeNew = deltaPe;
+ updateMinScfCalculated = 1;
+ do {
+ scfAct = scfAct - 1;
+ /* check only if the same check was not done before */
+
+ if (scfAct < minScfCalculated[sfbAct]) {
+ sfbPeNew = calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], sfbNRelevantLines[sfbAct]) +
+ countSingleScfBits(scfAct, *scfLast, *scfNext);
+ /* use new scf if no increase in pe and
+ quantization error is smaller */
+ deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld;
+
+ if (deltaPeTmp < 10) {
+ sfbDistNew = calcSfbDist(psyOutChan->mdctSpectrum+
+ psyOutChan->sfbOffsets[sfbAct],
+ (psyOutChan->sfbOffsets[sfbAct+1] - psyOutChan->sfbOffsets[sfbAct]),
+ scfAct);
+ if (sfbDistNew < sfbDist[sfbAct]) {
+ /* success, replace scf by new one */
+ scf[sfbAct] = scfAct;
+ sfbDist[sfbAct] = sfbDistNew;
+ deltaPeNew = deltaPeTmp;
+ success = 1;
+ }
+ /* mark as already checked */
+
+ if (updateMinScfCalculated) {
+ minScfCalculated[sfbAct] = scfAct;
+ }
+ }
+ else {
+ updateMinScfCalculated = 0;
+ }
+ }
+
+ } while (scfAct > scfMin);
+ deltaPe = deltaPeNew;
+ /* save parameters to avoid multiple computations of the same sfb */
+ prevScfLast[sfbAct] = *scfLast;
+ prevScfNext[sfbAct] = *scfNext;
+ deltaPeLast[sfbAct] = deltaPe;
+ }
+
+ if (success && restartOnSuccess) {
+ /* start again at first sfb */
+ sfbLast = -1;
+ sfbAct = -1;
+ sfbNext = -1;
+ scfLast = 0;
+ scfNext = 0;
+ scfMin = MAX_16;
+ success = 0;
+ }
+ else {
+ /* shift sfbs for next band */
+ sfbLast = sfbAct;
+ sfbAct = sfbNext;
+ }
+
+ } while (sfbNext < psyOutChan->sfbCnt);
+}
+
+
+/*********************************************************************************
+*
+* function name: assimilateMultipleScf
+* description: scalefactor difference reduction
+*
+**********************************************************************************/
+static void assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan,
+ Word16 *scf,
+ Word16 *minScf,
+ Word32 *sfbDist,
+ Word16 *sfbConstPePart,
+ Word16 *logSfbEnergy,
+ Word16 *logSfbFormFactor,
+ Word16 *sfbNRelevantLines)
+{
+ Word32 sfb, startSfb, stopSfb, scfMin, scfMax, scfAct;
+ Flag possibleRegionFound;
+ Word32 deltaScfBits;
+ Word32 deltaSpecPe;
+ Word32 deltaPe, deltaPeNew;
+ Word32 sfbCnt;
+ Word32 *sfbDistNew = psyOutChan->sfbDistNew;
+ Word16 *scfTmp = psyOutChan->prevScfLast;
+
+ deltaPe = 0;
+ sfbCnt = psyOutChan->sfbCnt;
+
+ /* calc min and max scalfactors */
+ scfMin = MAX_16;
+ scfMax = MIN_16;
+ for (sfb=0; sfb<sfbCnt; sfb++) {
+
+ if (scf[sfb] != MIN_16) {
+ scfMin = min(scfMin, scf[sfb]);
+ scfMax = max(scfMax, scf[sfb]);
+ }
+ }
+
+ if (scfMax != MIN_16) {
+
+ scfAct = scfMax;
+
+ do {
+ scfAct = scfAct - 1;
+ for (sfb=0; sfb<sfbCnt; sfb++) {
+ scfTmp[sfb] = scf[sfb];
+ }
+ stopSfb = 0;
+ do {
+ sfb = stopSfb;
+
+ while (sfb < sfbCnt && (scf[sfb] == MIN_16 || scf[sfb] <= scfAct)) {
+ sfb = sfb + 1;
+ }
+ startSfb = sfb;
+ sfb = sfb + 1;
+
+ while (sfb < sfbCnt && (scf[sfb] == MIN_16 || scf[sfb] > scfAct)) {
+ sfb = sfb + 1;
+ }
+ stopSfb = sfb;
+
+ possibleRegionFound = 0;
+
+ if (startSfb < sfbCnt) {
+ possibleRegionFound = 1;
+ for (sfb=startSfb; sfb<stopSfb; sfb++) {
+
+ if (scf[sfb]!=MIN_16) {
+
+ if (scfAct < minScf[sfb]) {
+ possibleRegionFound = 0;
+ break;
+ }
+ }
+ }
+ }
+
+
+ if (possibleRegionFound) { /* region found */
+
+ /* replace scfs in region by scfAct */
+ for (sfb=startSfb; sfb<stopSfb; sfb++) {
+
+ if (scfTmp[sfb]!=MIN_16)
+ scfTmp[sfb] = scfAct;
+ }
+
+ /* estimate change in bit demand for new scfs */
+ deltaScfBits = countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
+ deltaSpecPe = calcSpecPeDiff(scf, scfTmp, sfbConstPePart,
+ logSfbEnergy, logSfbFormFactor, sfbNRelevantLines,
+ startSfb, stopSfb);
+ deltaPeNew = deltaPe + deltaScfBits + deltaSpecPe;
+
+
+ if (deltaPeNew < 10) {
+ Word32 distOldSum, distNewSum;
+
+ /* quantize and calc sum of new distortion */
+ distOldSum = 0;
+ distNewSum = 0;
+ for (sfb=startSfb; sfb<stopSfb; sfb++) {
+
+ if (scfTmp[sfb] != MIN_16) {
+ distOldSum = L_add(distOldSum, sfbDist[sfb]);
+
+ sfbDistNew[sfb] = calcSfbDist(psyOutChan->mdctSpectrum +
+ psyOutChan->sfbOffsets[sfb],
+ (psyOutChan->sfbOffsets[sfb+1] - psyOutChan->sfbOffsets[sfb]),
+ scfAct);
+
+
+ if (sfbDistNew[sfb] > psyOutChan->sfbThreshold[sfb]) {
+ distNewSum = distOldSum << 1;
+ break;
+ }
+ distNewSum = L_add(distNewSum, sfbDistNew[sfb]);
+ }
+ }
+
+ if (distNewSum < distOldSum) {
+ deltaPe = deltaPeNew;
+ for (sfb=startSfb; sfb<stopSfb; sfb++) {
+
+ if (scf[sfb]!=MIN_16) {
+ scf[sfb] = scfAct;
+ sfbDist[sfb] = sfbDistNew[sfb];
+ }
+ }
+ }
+ }
+ }
+ } while (stopSfb <= sfbCnt);
+ } while (scfAct > scfMin);
+ }
+}
+
+/*********************************************************************************
+*
+* function name: EstimateScaleFactorsChannel
+* description: estimate scale factors for one channel
+*
+**********************************************************************************/
+static void
+EstimateScaleFactorsChannel(PSY_OUT_CHANNEL *psyOutChan,
+ Word16 *scf,
+ Word16 *globalGain,
+ Word16 *logSfbEnergy,
+ Word16 *logSfbFormFactor,
+ Word16 *sfbNRelevantLines)
+{
+ Word32 i, j;
+ Word32 thresh, energy;
+ Word32 energyPart, thresholdPart;
+ Word32 scfInt, minScf, maxScf, maxAllowedScf, lastSf;
+ Word32 maxSpec;
+ Word32 *sfbDist = psyOutChan->sfbDist;
+ Word16 *minSfMaxQuant = psyOutChan->minSfMaxQuant;
+ Word16 *minScfCalculated = psyOutChan->minScfCalculated;
+
+
+ for (i=0; i<psyOutChan->sfbCnt; i++) {
+ Word32 sbfwith, sbfStart;
+ Word32 *mdctSpec;
+ thresh = psyOutChan->sfbThreshold[i];
+ energy = psyOutChan->sfbEnergy[i];
+
+ sbfStart = psyOutChan->sfbOffsets[i];
+ sbfwith = psyOutChan->sfbOffsets[i+1] - sbfStart;
+ mdctSpec = psyOutChan->mdctSpectrum+sbfStart;
+
+ maxSpec = 0;
+ /* maximum of spectrum */
+ for (j=sbfwith; j; j-- ) {
+ Word32 absSpec = L_abs(*mdctSpec); mdctSpec++;
+ maxSpec |= absSpec;
+ }
+
+ /* scfs without energy or with thresh>energy are marked with MIN_16 */
+ scf[i] = MIN_16;
+ minSfMaxQuant[i] = MIN_16;
+
+ if ((maxSpec > 0) && (energy > thresh)) {
+
+ energyPart = logSfbFormFactor[i];
+ thresholdPart = iLog4(thresh);
+ /* -20 = 4*log2(6.75) - 32 */
+ scfInt = ((thresholdPart - energyPart - 20) * SCALE_ESTIMATE_COEF) >> 15;
+
+ minSfMaxQuant[i] = iLog4(maxSpec) - 68; /* 68 -16/3*log(MAX_QUANT+0.5-logCon)/log(2) + 1 */
+
+
+ if (minSfMaxQuant[i] > scfInt) {
+ scfInt = minSfMaxQuant[i];
+ }
+
+ /* find better scalefactor with analysis by synthesis */
+ scfInt = improveScf(psyOutChan->mdctSpectrum+sbfStart,
+ sbfwith,
+ thresh, scfInt, minSfMaxQuant[i],
+ &sfbDist[i], &minScfCalculated[i]);
+
+ scf[i] = scfInt;
+ }
+ }
+
+
+ /* scalefactor differece reduction */
+ {
+ Word16 sfbConstPePart[MAX_GROUPED_SFB];
+ for(i=0;i<psyOutChan->sfbCnt;i++) {
+ sfbConstPePart[i] = MIN_16;
+ }
+
+ assimilateSingleScf(psyOutChan, scf,
+ minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy,
+ logSfbFormFactor, sfbNRelevantLines, minScfCalculated, 1);
+
+ assimilateMultipleScf(psyOutChan, scf,
+ minSfMaxQuant, sfbDist, sfbConstPePart, logSfbEnergy,
+ logSfbFormFactor, sfbNRelevantLines);
+ }
+
+ /* get max scalefac for global gain */
+ maxScf = MIN_16;
+ minScf = MAX_16;
+ for (i=0; i<psyOutChan->sfbCnt; i++) {
+
+ if (maxScf < scf[i]) {
+ maxScf = scf[i];
+ }
+
+ if ((scf[i] != MIN_16) && (minScf > scf[i])) {
+ minScf = scf[i];
+ }
+ }
+ /* limit scf delta */
+ maxAllowedScf = minScf + MAX_SCF_DELTA;
+ for(i=0; i<psyOutChan->sfbCnt; i++) {
+
+ if ((scf[i] != MIN_16) && (maxAllowedScf < scf[i])) {
+ scf[i] = maxAllowedScf;
+ }
+ }
+ /* new maxScf if any scf has been limited */
+
+ if (maxAllowedScf < maxScf) {
+ maxScf = maxAllowedScf;
+ }
+
+ /* calc loop scalefactors */
+
+ if (maxScf > MIN_16) {
+ *globalGain = maxScf;
+ lastSf = 0;
+
+ for(i=0; i<psyOutChan->sfbCnt; i++) {
+
+ if (scf[i] == MIN_16) {
+ scf[i] = lastSf;
+ /* set band explicitely to zero */
+ for (j=psyOutChan->sfbOffsets[i]; j<psyOutChan->sfbOffsets[i+1]; j++) {
+ psyOutChan->mdctSpectrum[j] = 0;
+ }
+ }
+ else {
+ scf[i] = maxScf - scf[i];
+ lastSf = scf[i];
+ }
+ }
+ }
+ else{
+ *globalGain = 0;
+ /* set spectrum explicitely to zero */
+ for(i=0; i<psyOutChan->sfbCnt; i++) {
+ scf[i] = 0;
+ for (j=psyOutChan->sfbOffsets[i]; j<psyOutChan->sfbOffsets[i+1]; j++) {
+ psyOutChan->mdctSpectrum[j] = 0;
+ }
+ }
+ }
+}
+
+/*********************************************************************************
+*
+* function name: CalcFormFactor
+* description: estimate Form factors for all channel
+*
+**********************************************************************************/
+void
+CalcFormFactor(Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ const Word16 nChannels)
+{
+ Word16 j;
+
+ for (j=0; j<nChannels; j++) {
+ CalcFormFactorChannel(logSfbFormFactor[j], sfbNRelevantLines[j], logSfbEnergy[j], &psyOutChannel[j]);
+ }
+}
+
+/*********************************************************************************
+*
+* function name: EstimateScaleFactors
+* description: estimate scale factors for all channel
+*
+**********************************************************************************/
+void
+EstimateScaleFactors(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ QC_OUT_CHANNEL qcOutChannel[MAX_CHANNELS],
+ Word16 logSfbEnergy[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 logSfbFormFactor[MAX_CHANNELS][MAX_GROUPED_SFB],
+ Word16 sfbNRelevantLines[MAX_CHANNELS][MAX_GROUPED_SFB],
+ const Word16 nChannels)
+{
+ Word16 j;
+
+ for (j=0; j<nChannels; j++) {
+ EstimateScaleFactorsChannel(&psyOutChannel[j],
+ qcOutChannel[j].scf,
+ &(qcOutChannel[j].globalGain),
+ logSfbEnergy[j],
+ logSfbFormFactor[j],
+ sfbNRelevantLines[j]);
+ }
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/spreading.c b/media/libstagefright/codecs/aacenc/src/spreading.c
new file mode 100644
index 0000000..e6fc7da
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/spreading.c
@@ -0,0 +1,52 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: spreading.c
+
+ Content: Spreading of energy function
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "spreading.h"
+
+/*********************************************************************************
+*
+* function name: SpreadingMax
+* description: spreading the energy
+* higher frequencies thr(n) = max(thr(n), sh(n)*thr(n-1))
+* lower frequencies thr(n) = max(thr(n), sl(n)*thr(n+1))
+*
+**********************************************************************************/
+void SpreadingMax(const Word16 pbCnt,
+ const Word16 *maskLowFactor,
+ const Word16 *maskHighFactor,
+ Word32 *pbSpreadedEnergy)
+{
+ Word32 i;
+
+ /* slope to higher frequencies */
+ for (i=1; i<pbCnt; i++) {
+ pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i],
+ L_mpy_ls(pbSpreadedEnergy[i-1], maskHighFactor[i]));
+ }
+ /* slope to lower frequencies */
+ for (i=pbCnt - 2; i>=0; i--) {
+ pbSpreadedEnergy[i] = max(pbSpreadedEnergy[i],
+ L_mpy_ls(pbSpreadedEnergy[i+1], maskLowFactor[i]));
+ }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/stat_bits.c b/media/libstagefright/codecs/aacenc/src/stat_bits.c
new file mode 100644
index 0000000..556104e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/stat_bits.c
@@ -0,0 +1,237 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: stat_bits.c
+
+ Content: Static bit counter functions
+
+*******************************************************************************/
+
+#include "stat_bits.h"
+#include "bitenc.h"
+#include "tns.h"
+
+
+typedef enum {
+ SI_ID_BITS =(3),
+ SI_FILL_COUNT_BITS =(4),
+ SI_FILL_ESC_COUNT_BITS =(8),
+ SI_FILL_EXTENTION_BITS =(4),
+ SI_FILL_NIBBLE_BITS =(4),
+ SI_SCE_BITS =(4),
+ SI_CPE_BITS =(5),
+ SI_CPE_MS_MASK_BITS =(2) ,
+ SI_ICS_INFO_BITS_LONG =(1+2+1+6+1),
+ SI_ICS_INFO_BITS_SHORT =(1+2+1+4+7),
+ SI_ICS_BITS =(8+1+1+1)
+} SI_BITS;
+
+
+/*********************************************************************************
+*
+* function name: countMsMaskBits
+* description: count ms stereo bits demand
+*
+**********************************************************************************/
+static Word16 countMsMaskBits(Word16 sfbCnt,
+ Word16 sfbPerGroup,
+ Word16 maxSfbPerGroup,
+ struct TOOLSINFO *toolsInfo)
+{
+ Word16 msBits, sfbOff, sfb;
+ msBits = 0;
+
+
+ switch(toolsInfo->msDigest) {
+ case MS_NONE:
+ case MS_ALL:
+ break;
+
+ case MS_SOME:
+ for(sfbOff=0; sfbOff<sfbCnt; sfbOff+=sfbPerGroup)
+ for(sfb=0; sfb<maxSfbPerGroup; sfb++)
+ msBits += 1;
+ break;
+ }
+ return(msBits);
+}
+
+/*********************************************************************************
+*
+* function name: tnsCount
+* description: count tns bit demand core function
+*
+**********************************************************************************/
+static Word16 tnsCount(TNS_INFO *tnsInfo, Word16 blockType)
+{
+
+ Word32 i, k;
+ Flag tnsPresent;
+ Word32 numOfWindows;
+ Word32 count;
+ Word32 coefBits;
+ Word16 *ptcoef;
+
+ count = 0;
+
+ if (blockType == 2)
+ numOfWindows = 8;
+ else
+ numOfWindows = 1;
+ tnsPresent = 0;
+
+ for (i=0; i<numOfWindows; i++) {
+
+ if (tnsInfo->tnsActive[i]!=0) {
+ tnsPresent = 1;
+ }
+ }
+
+ if (tnsPresent) {
+ /* there is data to be written*/
+ /*count += 1; */
+ for (i=0; i<numOfWindows; i++) {
+
+ if (blockType == 2)
+ count += 1;
+ else
+ count += 2;
+
+ if (tnsInfo->tnsActive[i]) {
+ count += 1;
+
+ if (blockType == 2) {
+ count += 4;
+ count += 3;
+ }
+ else {
+ count += 6;
+ count += 5;
+ }
+
+ if (tnsInfo->order[i]) {
+ count += 1; /*direction*/
+ count += 1; /*coef_compression */
+
+ if (tnsInfo->coefRes[i] == 4) {
+ ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT;
+ coefBits = 3;
+ for(k=0; k<tnsInfo->order[i]; k++) {
+
+ if ((ptcoef[k] > 3) || (ptcoef[k] < -4)) {
+ coefBits = 4;
+ break;
+ }
+ }
+ }
+ else {
+ coefBits = 2;
+ ptcoef = tnsInfo->coef + i*TNS_MAX_ORDER_SHORT;
+ for(k=0; k<tnsInfo->order[i]; k++) {
+
+ if ((ptcoef[k] > 1) || (ptcoef[k] < -2)) {
+ coefBits = 3;
+ break;
+ }
+ }
+ }
+ for (k=0; k<tnsInfo->order[i]; k++ ) {
+ count += coefBits;
+ }
+ }
+ }
+ }
+ }
+
+ return count;
+}
+
+/**********************************************************************************
+*
+* function name: countTnsBits
+* description: count tns bit demand
+*
+**********************************************************************************/
+static Word16 countTnsBits(TNS_INFO *tnsInfo,Word16 blockType)
+{
+ return(tnsCount(tnsInfo, blockType));
+}
+
+/*********************************************************************************
+*
+* function name: countStaticBitdemand
+* description: count static bit demand include tns
+*
+**********************************************************************************/
+Word16 countStaticBitdemand(PSY_OUT_CHANNEL psyOutChannel[MAX_CHANNELS],
+ PSY_OUT_ELEMENT *psyOutElement,
+ Word16 channels,
+ Word16 adtsUsed)
+{
+ Word32 statBits;
+ Word32 ch;
+
+ statBits = 0;
+
+ /* if adts used, add 56 bits */
+ if(adtsUsed) statBits += 56;
+
+
+ switch (channels) {
+ case 1:
+ statBits += SI_ID_BITS+SI_SCE_BITS+SI_ICS_BITS;
+ statBits += countTnsBits(&(psyOutChannel[0].tnsInfo),
+ psyOutChannel[0].windowSequence);
+
+ switch(psyOutChannel[0].windowSequence){
+ case LONG_WINDOW:
+ case START_WINDOW:
+ case STOP_WINDOW:
+ statBits += SI_ICS_INFO_BITS_LONG;
+ break;
+ case SHORT_WINDOW:
+ statBits += SI_ICS_INFO_BITS_SHORT;
+ break;
+ }
+ break;
+ case 2:
+ statBits += SI_ID_BITS+SI_CPE_BITS+2*SI_ICS_BITS;
+
+ statBits += SI_CPE_MS_MASK_BITS;
+ statBits += countMsMaskBits(psyOutChannel[0].sfbCnt,
+ psyOutChannel[0].sfbPerGroup,
+ psyOutChannel[0].maxSfbPerGroup,
+ &psyOutElement->toolsInfo);
+
+ switch (psyOutChannel[0].windowSequence) {
+ case LONG_WINDOW:
+ case START_WINDOW:
+ case STOP_WINDOW:
+ statBits += SI_ICS_INFO_BITS_LONG;
+ break;
+ case SHORT_WINDOW:
+ statBits += SI_ICS_INFO_BITS_SHORT;
+ break;
+ }
+ for(ch=0; ch<2; ch++)
+ statBits += countTnsBits(&(psyOutChannel[ch].tnsInfo),
+ psyOutChannel[ch].windowSequence);
+ break;
+ }
+
+ return statBits;
+}
+
diff --git a/media/libstagefright/codecs/aacenc/src/tns.c b/media/libstagefright/codecs/aacenc/src/tns.c
new file mode 100644
index 0000000..96d890e
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/tns.c
@@ -0,0 +1,932 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: tns.c
+
+ Content: Definition TNS tools functions
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "assert.h"
+#include "aac_rom.h"
+#include "psy_const.h"
+#include "tns.h"
+#include "tns_param.h"
+#include "psy_configuration.h"
+#include "tns_func.h"
+
+#define TNS_MODIFY_BEGIN 2600 /* Hz */
+#define RATIO_PATCH_LOWER_BORDER 380 /* Hz */
+#define TNS_GAIN_THRESH 141 /* 1.41*100 */
+#define NORM_COEF 0x028f5c28
+
+static const Word32 TNS_PARCOR_THRESH = 0x0ccccccd; /* 0.1*(1 << 31) */
+/* Limit bands to > 2.0 kHz */
+static unsigned short tnsMinBandNumberLong[12] =
+{ 11, 12, 15, 16, 17, 20, 25, 26, 24, 28, 30, 31 };
+static unsigned short tnsMinBandNumberShort[12] =
+{ 2, 2, 2, 3, 3, 4, 6, 6, 8, 10, 10, 12 };
+
+/**************************************/
+/* Main/Low Profile TNS Parameters */
+/**************************************/
+static unsigned short tnsMaxBandsLongMainLow[12] =
+{ 31, 31, 34, 40, 42, 51, 46, 46, 42, 42, 42, 39 };
+
+static unsigned short tnsMaxBandsShortMainLow[12] =
+{ 9, 9, 10, 14, 14, 14, 14, 14, 14, 14, 14, 14 };
+
+
+static void CalcWeightedSpectrum(const Word32 spectrum[],
+ Word16 weightedSpectrum[],
+ Word32* sfbEnergy,
+ const Word16* sfbOffset, Word16 lpcStartLine,
+ Word16 lpcStopLine, Word16 lpcStartBand,Word16 lpcStopBand,
+ Word32 *pWork32);
+
+
+
+void AutoCorrelation(const Word16 input[], Word32 corr[],
+ Word16 samples, Word16 corrCoeff);
+static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff);
+
+static Word16 CalcTnsFilter(const Word16* signal, const Word32 window[], Word16 numOfLines,
+ Word16 tnsOrder, Word32 parcor[]);
+
+
+static void Parcor2Index(const Word32 parcor[], Word16 index[], Word16 order,
+ Word16 bitsPerCoeff);
+
+static void Index2Parcor(const Word16 index[], Word32 parcor[], Word16 order,
+ Word16 bitsPerCoeff);
+
+
+
+static void AnalysisFilterLattice(const Word32 signal[], Word16 numOfLines,
+ const Word32 parCoeff[], Word16 order,
+ Word32 output[]);
+
+
+/**
+*
+* function name: FreqToBandWithRounding
+* description: Retrieve index of nearest band border
+* returnt: index
+*
+*/
+static Word16 FreqToBandWithRounding(Word32 freq, /*!< frequency in Hertz */
+ Word32 fs, /*!< Sampling frequency in Hertz */
+ Word16 numOfBands, /*!< total number of bands */
+ const Word16 *bandStartOffset) /*!< table of band borders */
+{
+ Word32 lineNumber, band;
+ Word32 temp, shift;
+
+ /* assert(freq >= 0); */
+ shift = norm_l(fs);
+ lineNumber = (extract_l(fixmul((bandStartOffset[numOfBands] << 2),Div_32(freq << shift,fs << shift))) + 1) >> 1;
+
+ /* freq > fs/2 */
+ temp = lineNumber - bandStartOffset[numOfBands] ;
+ if (temp >= 0)
+ return numOfBands;
+
+ /* find band the line number lies in */
+ for (band=0; band<numOfBands; band++) {
+ temp = bandStartOffset[band + 1] - lineNumber;
+ if (temp > 0) break;
+ }
+
+ temp = (lineNumber - bandStartOffset[band]);
+ temp = (temp - (bandStartOffset[band + 1] - lineNumber));
+ if ( temp > 0 )
+ {
+ band = band + 1;
+ }
+
+ return extract_l(band);
+}
+
+
+/**
+*
+* function name: InitTnsConfigurationLong
+* description: Fill TNS_CONFIG structure with sensible content for long blocks
+* returns: 0 if success
+*
+*/
+Word16 InitTnsConfigurationLong(Word32 bitRate, /*!< bitrate */
+ Word32 sampleRate, /*!< Sampling frequency */
+ Word16 channels, /*!< number of channels */
+ TNS_CONFIG *tC, /*!< TNS Config struct (modified) */
+ PSY_CONFIGURATION_LONG *pC, /*!< psy config struct */
+ Word16 active) /*!< tns active flag */
+{
+
+ Word32 bitratePerChannel;
+ tC->maxOrder = TNS_MAX_ORDER;
+ tC->tnsStartFreq = 1275;
+ tC->coefRes = 4;
+
+ /* to avoid integer division */
+ if ( sub(channels,2) == 0 ) {
+ bitratePerChannel = bitRate >> 1;
+ }
+ else {
+ bitratePerChannel = bitRate;
+ }
+
+ tC->tnsMaxSfb = tnsMaxBandsLongMainLow[pC->sampRateIdx];
+
+ tC->tnsActive = active;
+
+ /* now calc band and line borders */
+ tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
+ tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
+
+ tC->tnsStartBand = FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
+ pC->sfbCnt, (const Word16*)pC->sfbOffset);
+
+ tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
+ sampleRate,
+ pC->sfbCnt,
+ (const Word16*)pC->sfbOffset);
+
+ tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
+ sampleRate,
+ pC->sfbCnt,
+ (const Word16*)pC->sfbOffset);
+
+
+ tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
+
+ tC->lpcStopBand = tnsMaxBandsLongMainLow[pC->sampRateIdx];
+ tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
+
+ tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
+
+ tC->lpcStartBand = tnsMinBandNumberLong[pC->sampRateIdx];
+
+ tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
+
+ tC->threshold = TNS_GAIN_THRESH;
+
+
+ return(0);
+}
+
+/**
+*
+* function name: InitTnsConfigurationShort
+* description: Fill TNS_CONFIG structure with sensible content for short blocks
+* returns: 0 if success
+*
+*/
+Word16 InitTnsConfigurationShort(Word32 bitRate, /*!< bitrate */
+ Word32 sampleRate, /*!< Sampling frequency */
+ Word16 channels, /*!< number of channels */
+ TNS_CONFIG *tC, /*!< TNS Config struct (modified) */
+ PSY_CONFIGURATION_SHORT *pC, /*!< psy config struct */
+ Word16 active) /*!< tns active flag */
+{
+ Word32 bitratePerChannel;
+ tC->maxOrder = TNS_MAX_ORDER_SHORT;
+ tC->tnsStartFreq = 2750;
+ tC->coefRes = 3;
+
+ /* to avoid integer division */
+ if ( sub(channels,2) == 0 ) {
+ bitratePerChannel = L_shr(bitRate,1);
+ }
+ else {
+ bitratePerChannel = bitRate;
+ }
+
+ tC->tnsMaxSfb = tnsMaxBandsShortMainLow[pC->sampRateIdx];
+
+ tC->tnsActive = active;
+
+ /* now calc band and line borders */
+ tC->tnsStopBand = min(pC->sfbCnt, tC->tnsMaxSfb);
+ tC->tnsStopLine = pC->sfbOffset[tC->tnsStopBand];
+
+ tC->tnsStartBand=FreqToBandWithRounding(tC->tnsStartFreq, sampleRate,
+ pC->sfbCnt, (const Word16*)pC->sfbOffset);
+
+ tC->tnsModifyBeginCb = FreqToBandWithRounding(TNS_MODIFY_BEGIN,
+ sampleRate,
+ pC->sfbCnt,
+ (const Word16*)pC->sfbOffset);
+
+ tC->tnsRatioPatchLowestCb = FreqToBandWithRounding(RATIO_PATCH_LOWER_BORDER,
+ sampleRate,
+ pC->sfbCnt,
+ (const Word16*)pC->sfbOffset);
+
+
+ tC->tnsStartLine = pC->sfbOffset[tC->tnsStartBand];
+
+ tC->lpcStopBand = tnsMaxBandsShortMainLow[pC->sampRateIdx];
+
+ tC->lpcStopBand = min(tC->lpcStopBand, pC->sfbActive);
+
+ tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand];
+
+ tC->lpcStartBand = tnsMinBandNumberShort[pC->sampRateIdx];
+
+ tC->lpcStartLine = pC->sfbOffset[tC->lpcStartBand];
+
+ tC->threshold = TNS_GAIN_THRESH;
+
+ return(0);
+}
+
+/**
+*
+* function name: TnsDetect
+* description: Calculate TNS filter and decide on TNS usage
+* returns: 0 if success
+*
+*/
+Word32 TnsDetect(TNS_DATA* tnsData, /*!< tns data structure (modified) */
+ TNS_CONFIG tC, /*!< tns config structure */
+ Word32* pScratchTns, /*!< pointer to scratch space */
+ const Word16 sfbOffset[], /*!< scalefactor size and table */
+ Word32* spectrum, /*!< spectral data */
+ Word16 subBlockNumber, /*!< subblock num */
+ Word16 blockType, /*!< blocktype (long or short) */
+ Word32 * sfbEnergy) /*!< sfb-wise energy */
+{
+
+ Word32 predictionGain;
+ Word32 temp;
+ Word32* pWork32 = &pScratchTns[subBlockNumber >> 8];
+ Word16* pWeightedSpectrum = (Word16 *)&pScratchTns[subBlockNumber >> 8];
+
+
+ if (tC.tnsActive) {
+ CalcWeightedSpectrum(spectrum,
+ pWeightedSpectrum,
+ sfbEnergy,
+ sfbOffset,
+ tC.lpcStartLine,
+ tC.lpcStopLine,
+ tC.lpcStartBand,
+ tC.lpcStopBand,
+ pWork32);
+
+ temp = blockType - SHORT_WINDOW;
+ if ( temp != 0 ) {
+ predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
+ tC.acfWindow,
+ tC.lpcStopLine - tC.lpcStartLine,
+ tC.maxOrder,
+ tnsData->dataRaw.tnsLong.subBlockInfo.parcor);
+
+
+ temp = predictionGain - tC.threshold;
+ if ( temp > 0 ) {
+ tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 1;
+ }
+ else {
+ tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
+ }
+
+ tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = predictionGain;
+ }
+ else{
+
+ predictionGain = CalcTnsFilter( &pWeightedSpectrum[tC.lpcStartLine],
+ tC.acfWindow,
+ tC.lpcStopLine - tC.lpcStartLine,
+ tC.maxOrder,
+ tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].parcor);
+
+ temp = predictionGain - tC.threshold;
+ if ( temp > 0 ) {
+ tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 1;
+ }
+ else {
+ tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
+ }
+
+ tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = predictionGain;
+ }
+
+ }
+ else{
+
+ temp = blockType - SHORT_WINDOW;
+ if ( temp != 0 ) {
+ tnsData->dataRaw.tnsLong.subBlockInfo.tnsActive = 0;
+ tnsData->dataRaw.tnsLong.subBlockInfo.predictionGain = 0;
+ }
+ else {
+ tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].tnsActive = 0;
+ tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber].predictionGain = 0;
+ }
+ }
+
+ return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: TnsSync
+* description: update tns parameter
+*
+*****************************************************************************/
+void TnsSync(TNS_DATA *tnsDataDest,
+ const TNS_DATA *tnsDataSrc,
+ const TNS_CONFIG tC,
+ const Word16 subBlockNumber,
+ const Word16 blockType)
+{
+ TNS_SUBBLOCK_INFO *sbInfoDest;
+ const TNS_SUBBLOCK_INFO *sbInfoSrc;
+ Word32 i, temp;
+
+ temp = blockType - SHORT_WINDOW;
+ if ( temp != 0 ) {
+ sbInfoDest = &tnsDataDest->dataRaw.tnsLong.subBlockInfo;
+ sbInfoSrc = &tnsDataSrc->dataRaw.tnsLong.subBlockInfo;
+ }
+ else {
+ sbInfoDest = &tnsDataDest->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
+ sbInfoSrc = &tnsDataSrc->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
+ }
+
+ if (100*abs_s(sbInfoDest->predictionGain - sbInfoSrc->predictionGain) <
+ (3 * sbInfoDest->predictionGain)) {
+ sbInfoDest->tnsActive = sbInfoSrc->tnsActive;
+ for ( i=0; i< tC.maxOrder; i++) {
+ sbInfoDest->parcor[i] = sbInfoSrc->parcor[i];
+ }
+ }
+}
+
+/*****************************************************************************
+*
+* function name: TnsEncode
+* description: do TNS filtering
+* returns: 0 if success
+*
+*****************************************************************************/
+Word16 TnsEncode(TNS_INFO* tnsInfo, /*!< tns info structure (modified) */
+ TNS_DATA* tnsData, /*!< tns data structure (modified) */
+ Word16 numOfSfb, /*!< number of scale factor bands */
+ TNS_CONFIG tC, /*!< tns config structure */
+ Word16 lowPassLine, /*!< lowpass line */
+ Word32* spectrum, /*!< spectral data (modified) */
+ Word16 subBlockNumber, /*!< subblock num */
+ Word16 blockType) /*!< blocktype (long or short) */
+{
+ Word32 i;
+ Word32 temp_s;
+ Word32 temp;
+ TNS_SUBBLOCK_INFO *psubBlockInfo;
+
+ temp_s = blockType - SHORT_WINDOW;
+ if ( temp_s != 0) {
+ psubBlockInfo = &tnsData->dataRaw.tnsLong.subBlockInfo;
+ if (psubBlockInfo->tnsActive == 0) {
+ tnsInfo->tnsActive[subBlockNumber] = 0;
+ return(0);
+ }
+ else {
+
+ Parcor2Index(psubBlockInfo->parcor,
+ tnsInfo->coef,
+ tC.maxOrder,
+ tC.coefRes);
+
+ Index2Parcor(tnsInfo->coef,
+ psubBlockInfo->parcor,
+ tC.maxOrder,
+ tC.coefRes);
+
+ for (i=tC.maxOrder - 1; i>=0; i--) {
+ temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
+ if ( temp > 0 )
+ break;
+ temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
+ if ( temp < 0 )
+ break;
+ }
+ tnsInfo->order[subBlockNumber] = i + 1;
+
+
+ tnsInfo->tnsActive[subBlockNumber] = 1;
+ for (i=subBlockNumber+1; i<TRANS_FAC; i++) {
+ tnsInfo->tnsActive[i] = 0;
+ }
+ tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
+ tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
+
+
+ AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]),
+ (min(tC.tnsStopLine,lowPassLine) - tC.tnsStartLine),
+ psubBlockInfo->parcor,
+ tnsInfo->order[subBlockNumber],
+ &(spectrum[tC.tnsStartLine]));
+
+ }
+ } /* if (blockType!=SHORT_WINDOW) */
+ else /*short block*/ {
+ psubBlockInfo = &tnsData->dataRaw.tnsShort.subBlockInfo[subBlockNumber];
+ if (psubBlockInfo->tnsActive == 0) {
+ tnsInfo->tnsActive[subBlockNumber] = 0;
+ return(0);
+ }
+ else {
+
+ Parcor2Index(psubBlockInfo->parcor,
+ &tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
+ tC.maxOrder,
+ tC.coefRes);
+
+ Index2Parcor(&tnsInfo->coef[subBlockNumber*TNS_MAX_ORDER_SHORT],
+ psubBlockInfo->parcor,
+ tC.maxOrder,
+ tC.coefRes);
+ for (i=(tC.maxOrder - 1); i>=0; i--) {
+ temp = psubBlockInfo->parcor[i] - TNS_PARCOR_THRESH;
+ if ( temp > 0 )
+ break;
+
+ temp = psubBlockInfo->parcor[i] + TNS_PARCOR_THRESH;
+ if ( temp < 0 )
+ break;
+ }
+ tnsInfo->order[subBlockNumber] = i + 1;
+
+ tnsInfo->tnsActive[subBlockNumber] = 1;
+ tnsInfo->coefRes[subBlockNumber] = tC.coefRes;
+ tnsInfo->length[subBlockNumber] = numOfSfb - tC.tnsStartBand;
+
+
+ AnalysisFilterLattice(&(spectrum[tC.tnsStartLine]), (tC.tnsStopLine - tC.tnsStartLine),
+ psubBlockInfo->parcor,
+ tnsInfo->order[subBlockNumber],
+ &(spectrum[tC.tnsStartLine]));
+
+ }
+ }
+
+ return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: m_pow2_cordic
+* description: Iterative power function
+*
+* Calculates pow(2.0,x-1.0*(scale+1)) with INT_BITS bit precision
+* using modified cordic algorithm
+* returns: the result of pow2
+*
+*****************************************************************************/
+static Word32 m_pow2_cordic(Word32 x, Word16 scale)
+{
+ Word32 k;
+
+ Word32 accu_y = 0x40000000;
+ accu_y = L_shr(accu_y,scale);
+
+ for(k=1; k<INT_BITS; k++) {
+ const Word32 z = m_log2_table[k];
+
+ while(L_sub(x,z) >= 0) {
+
+ x = L_sub(x, z);
+ accu_y = L_add(accu_y, (accu_y >> k));
+ }
+ }
+ return(accu_y);
+}
+
+
+/*****************************************************************************
+*
+* function name: CalcWeightedSpectrum
+* description: Calculate weighted spectrum for LPC calculation
+*
+*****************************************************************************/
+static void CalcWeightedSpectrum(const Word32 spectrum[], /*!< input spectrum */
+ Word16 weightedSpectrum[],
+ Word32 *sfbEnergy, /*!< sfb energies */
+ const Word16 *sfbOffset,
+ Word16 lpcStartLine,
+ Word16 lpcStopLine,
+ Word16 lpcStartBand,
+ Word16 lpcStopBand,
+ Word32 *pWork32)
+{
+ #define INT_BITS_SCAL 1<<(INT_BITS/2)
+
+ Word32 i, sfb, shift;
+ Word32 maxShift;
+ Word32 tmp_s, tmp2_s;
+ Word32 tmp, tmp2;
+ Word32 maxWS;
+ Word32 tnsSfbMean[MAX_SFB]; /* length [lpcStopBand-lpcStartBand] should be sufficient here */
+
+ maxWS = 0;
+
+ /* calc 1.0*2^-INT_BITS/2/sqrt(en) */
+ for( sfb = lpcStartBand; sfb < lpcStopBand; sfb++) {
+
+ tmp2 = sfbEnergy[sfb] - 2;
+ if( tmp2 > 0) {
+ tmp = rsqrt(sfbEnergy[sfb], INT_BITS);
+ if(tmp > INT_BITS_SCAL)
+ {
+ shift = norm_l(tmp);
+ tmp = Div_32( INT_BITS_SCAL << shift, tmp << shift );
+ }
+ else
+ {
+ tmp = 0x7fffffff;
+ }
+ }
+ else {
+ tmp = 0x7fffffff;
+ }
+ tnsSfbMean[sfb] = tmp;
+ }
+
+ /* spread normalized values from sfbs to lines */
+ sfb = lpcStartBand;
+ tmp = tnsSfbMean[sfb];
+ for ( i=lpcStartLine; i<lpcStopLine; i++){
+ tmp_s = sfbOffset[sfb + 1] - i;
+ if ( tmp_s == 0 ) {
+ sfb = sfb + 1;
+ tmp2_s = sfb + 1 - lpcStopBand;
+ if (tmp2_s <= 0) {
+ tmp = tnsSfbMean[sfb];
+ }
+ }
+ pWork32[i] = tmp;
+ }
+ /*filter down*/
+ for (i=(lpcStopLine - 2); i>=lpcStartLine; i--){
+ pWork32[i] = (pWork32[i] + pWork32[i + 1]) >> 1;
+ }
+ /* filter up */
+ for (i=(lpcStartLine + 1); i<lpcStopLine; i++){
+ pWork32[i] = (pWork32[i] + pWork32[i - 1]) >> 1;
+ }
+
+ /* weight and normalize */
+ for (i=lpcStartLine; i<lpcStopLine; i++){
+ pWork32[i] = MULHIGH(pWork32[i], spectrum[i]);
+ maxWS |= L_abs(pWork32[i]);
+ }
+ maxShift = norm_l(maxWS);
+
+ maxShift = 16 - maxShift;
+ if(maxShift >= 0)
+ {
+ for (i=lpcStartLine; i<lpcStopLine; i++){
+ weightedSpectrum[i] = pWork32[i] >> maxShift;
+ }
+ }
+ else
+ {
+ maxShift = -maxShift;
+ for (i=lpcStartLine; i<lpcStopLine; i++){
+ weightedSpectrum[i] = saturate(pWork32[i] << maxShift);
+ }
+ }
+}
+
+
+
+
+/*****************************************************************************
+*
+* function name: CalcTnsFilter
+* description: LPC calculation for one TNS filter
+* returns: prediction gain
+* input: signal spectrum, acf window, no. of spectral lines,
+* max. TNS order, ptr. to reflection ocefficients
+* output: reflection coefficients
+*(half) window size must be larger than tnsOrder !!*
+******************************************************************************/
+
+static Word16 CalcTnsFilter(const Word16 *signal,
+ const Word32 window[],
+ Word16 numOfLines,
+ Word16 tnsOrder,
+ Word32 parcor[])
+{
+ Word32 parcorWorkBuffer[2*TNS_MAX_ORDER+1];
+ Word32 predictionGain;
+ Word32 i;
+ Word32 tnsOrderPlus1 = tnsOrder + 1;
+
+ assert(tnsOrder <= TNS_MAX_ORDER); /* remove asserts later? (btg) */
+
+ for(i=0;i<tnsOrder;i++) {
+ parcor[i] = 0;
+ }
+
+ AutoCorrelation(signal, parcorWorkBuffer, numOfLines, tnsOrderPlus1);
+
+ /* early return if signal is very low: signal prediction off, with zero parcor coeffs */
+ if (parcorWorkBuffer[0] == 0)
+ return 0;
+
+ predictionGain = AutoToParcor(parcorWorkBuffer, parcor, tnsOrder);
+
+ return(predictionGain);
+}
+
+/*****************************************************************************
+*
+* function name: AutoCorrelation
+* description: calc. autocorrelation (acf)
+* returns: -
+* input: input values, no. of input values, no. of acf values
+* output: acf values
+*
+*****************************************************************************/
+#ifndef ARMV5E
+void AutoCorrelation(const Word16 input[],
+ Word32 corr[],
+ Word16 samples,
+ Word16 corrCoeff) {
+ Word32 i, j, isamples;
+ Word32 accu;
+ Word32 scf;
+
+ scf = 10 - 1;
+
+ isamples = samples;
+ /* calc first corrCoef: R[0] = sum { t[i] * t[i] } ; i = 0..N-1 */
+ accu = 0;
+ for(j=0; j<isamples; j++) {
+ accu = L_add(accu, ((input[j] * input[j]) >> scf));
+ }
+ corr[0] = accu;
+
+ /* early termination if all corr coeffs are likely going to be zero */
+ if(corr[0] == 0) return ;
+
+ /* calc all other corrCoef: R[j] = sum { t[i] * t[i+j] } ; i = 0..(N-j-1), j=1..p */
+ for(i=1; i<corrCoeff; i++) {
+ isamples = isamples - 1;
+ accu = 0;
+ for(j=0; j<isamples; j++) {
+ accu = L_add(accu, ((input[j] * input[j+i]) >> scf));
+ }
+ corr[i] = accu;
+ }
+}
+#endif
+
+/*****************************************************************************
+*
+* function name: AutoToParcor
+* description: conversion autocorrelation to reflection coefficients
+* returns: prediction gain
+* input: <order+1> input values, no. of output values (=order),
+* ptr. to workbuffer (required size: 2*order)
+* output: <order> reflection coefficients
+*
+*****************************************************************************/
+static Word16 AutoToParcor(Word32 workBuffer[], Word32 reflCoeff[], Word16 numOfCoeff) {
+
+ Word32 i, j, shift;
+ Word32 *pWorkBuffer; /* temp pointer */
+ Word32 predictionGain = 0;
+ Word32 num, denom;
+ Word32 temp, workBuffer0;
+
+
+ num = workBuffer[0];
+ temp = workBuffer[numOfCoeff];
+
+ for(i=0; i<numOfCoeff-1; i++) {
+ workBuffer[i + numOfCoeff] = workBuffer[i + 1];
+ }
+ workBuffer[i + numOfCoeff] = temp;
+
+ for(i=0; i<numOfCoeff; i++) {
+ Word32 refc;
+
+
+ if (workBuffer[0] < L_abs(workBuffer[i + numOfCoeff])) {
+ return 0 ;
+ }
+ shift = norm_l(workBuffer[0]);
+ workBuffer0 = Div_32(1 << shift, workBuffer[0] << shift);
+ /* calculate refc = -workBuffer[numOfCoeff+i] / workBuffer[0]; -1 <= refc < 1 */
+ refc = L_negate(fixmul(workBuffer[numOfCoeff + i], workBuffer0));
+
+ reflCoeff[i] = refc;
+
+ pWorkBuffer = &(workBuffer[numOfCoeff]);
+
+ for(j=i; j<numOfCoeff; j++) {
+ Word32 accu1, accu2;
+ accu1 = L_add(pWorkBuffer[j], fixmul(refc, workBuffer[j - i]));
+ accu2 = L_add(workBuffer[j - i], fixmul(refc, pWorkBuffer[j]));
+ pWorkBuffer[j] = accu1;
+ workBuffer[j - i] = accu2;
+ }
+ }
+
+ denom = MULHIGH(workBuffer[0], NORM_COEF);
+
+ if (denom != 0) {
+ Word32 temp;
+ shift = norm_l(denom);
+ temp = Div_32(1 << shift, denom << shift);
+ predictionGain = fixmul(num, temp);
+ }
+
+ return extract_l(predictionGain);
+}
+
+
+
+static Word16 Search3(Word32 parcor)
+{
+ Word32 index = 0;
+ Word32 i;
+ Word32 temp;
+
+ for (i=0;i<8;i++) {
+ temp = L_sub( parcor, tnsCoeff3Borders[i]);
+ if (temp > 0)
+ index=i;
+ }
+ return extract_l(index - 4);
+}
+
+static Word16 Search4(Word32 parcor)
+{
+ Word32 index = 0;
+ Word32 i;
+ Word32 temp;
+
+
+ for (i=0;i<16;i++) {
+ temp = L_sub(parcor, tnsCoeff4Borders[i]);
+ if (temp > 0)
+ index=i;
+ }
+ return extract_l(index - 8);
+}
+
+
+
+/*****************************************************************************
+*
+* functionname: Parcor2Index
+* description: quantization index for reflection coefficients
+*
+*****************************************************************************/
+static void Parcor2Index(const Word32 parcor[], /*!< parcor coefficients */
+ Word16 index[], /*!< quantized coeff indices */
+ Word16 order, /*!< filter order */
+ Word16 bitsPerCoeff) { /*!< quantizer resolution */
+ Word32 i;
+ Word32 temp;
+
+ for(i=0; i<order; i++) {
+ temp = bitsPerCoeff - 3;
+ if (temp == 0) {
+ index[i] = Search3(parcor[i]);
+ }
+ else {
+ index[i] = Search4(parcor[i]);
+ }
+ }
+}
+
+/*****************************************************************************
+*
+* functionname: Index2Parcor
+* description: Inverse quantization for reflection coefficients
+*
+*****************************************************************************/
+static void Index2Parcor(const Word16 index[], /*!< quantized values */
+ Word32 parcor[], /*!< ptr. to reflection coefficients (output) */
+ Word16 order, /*!< no. of coefficients */
+ Word16 bitsPerCoeff) /*!< quantizer resolution */
+{
+ Word32 i;
+ Word32 temp;
+
+ for (i=0; i<order; i++) {
+ temp = bitsPerCoeff - 4;
+ if ( temp == 0 ) {
+ parcor[i] = tnsCoeff4[index[i] + 8];
+ }
+ else {
+ parcor[i] = tnsCoeff3[index[i] + 4];
+ }
+ }
+}
+
+/*****************************************************************************
+*
+* functionname: FIRLattice
+* description: in place lattice filtering of spectral data
+* returns: pointer to modified data
+*
+*****************************************************************************/
+static Word32 FIRLattice(Word16 order, /*!< filter order */
+ Word32 x, /*!< spectral data */
+ Word32 *state_par, /*!< filter states */
+ const Word32 *coef_par) /*!< filter coefficients */
+{
+ Word32 i;
+ Word32 accu,tmp,tmpSave;
+
+ x = x >> 1;
+ tmpSave = x;
+
+ for (i=0; i<(order - 1); i++) {
+
+ tmp = L_add(fixmul(coef_par[i], x), state_par[i]);
+ x = L_add(fixmul(coef_par[i], state_par[i]), x);
+
+ state_par[i] = tmpSave;
+ tmpSave = tmp;
+ }
+
+ /* last stage: only need half operations */
+ accu = fixmul(state_par[order - 1], coef_par[(order - 1)]);
+ state_par[(order - 1)] = tmpSave;
+
+ x = L_add(accu, x);
+ x = L_add(x, x);
+
+ return x;
+}
+
+/*****************************************************************************
+*
+* functionname: AnalysisFilterLattice
+* description: filters spectral lines with TNS filter
+*
+*****************************************************************************/
+static void AnalysisFilterLattice(const Word32 signal[], /*!< input spectrum */
+ Word16 numOfLines, /*!< no. of lines */
+ const Word32 parCoeff[],/*!< PARC coefficients */
+ Word16 order, /*!< filter order */
+ Word32 output[]) /*!< filtered signal values */
+{
+
+ Word32 state_par[TNS_MAX_ORDER];
+ Word32 j;
+
+ for ( j=0; j<TNS_MAX_ORDER; j++ ) {
+ state_par[j] = 0;
+ }
+
+ for(j=0; j<numOfLines; j++) {
+ output[j] = FIRLattice(order,signal[j],state_par,parCoeff);
+ }
+}
+
+/*****************************************************************************
+*
+* functionname: ApplyTnsMultTableToRatios
+* description: Change thresholds according to tns
+*
+*****************************************************************************/
+void ApplyTnsMultTableToRatios(Word16 startCb,
+ Word16 stopCb,
+ TNS_SUBBLOCK_INFO subInfo, /*!< TNS subblock info */
+ Word32 *thresholds) /*!< thresholds (modified) */
+{
+ Word32 i;
+ if (subInfo.tnsActive) {
+ for(i=startCb; i<stopCb; i++) {
+ /* thresholds[i] * 0.25 */
+ thresholds[i] = (thresholds[i] >> 2);
+ }
+ }
+}
diff --git a/media/libstagefright/codecs/aacenc/src/transform.c b/media/libstagefright/codecs/aacenc/src/transform.c
new file mode 100644
index 0000000..af17b5a
--- /dev/null
+++ b/media/libstagefright/codecs/aacenc/src/transform.c
@@ -0,0 +1,672 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: transform.c
+
+ Content: MDCT Transform functionss
+
+*******************************************************************************/
+
+#include "basic_op.h"
+#include "psy_const.h"
+#include "transform.h"
+#include "aac_rom.h"
+
+
+#define LS_TRANS ((FRAME_LEN_LONG-FRAME_LEN_SHORT)/2) /* 448 */
+#define SQRT1_2 0x5a82799a /* sqrt(1/2) in Q31 */
+#define swap2(p0,p1) \
+ t = p0; t1 = *(&(p0)+1); \
+ p0 = p1; *(&(p0)+1) = *(&(p1)+1); \
+ p1 = t; *(&(p1)+1) = t1
+
+/*********************************************************************************
+*
+* function name: Shuffle
+* description: Shuffle points prepared function for fft
+*
+**********************************************************************************/
+static void Shuffle(int *buf, int num, const unsigned char* bitTab)
+{
+ int *part0, *part1;
+ int i, j;
+ int t, t1;
+
+ part0 = buf;
+ part1 = buf + num;
+
+ while ((i = *bitTab++) != 0) {
+ j = *bitTab++;
+
+ swap2(part0[4*i+0], part0[4*j+0]);
+ swap2(part0[4*i+2], part1[4*j+0]);
+ swap2(part1[4*i+0], part0[4*j+2]);
+ swap2(part1[4*i+2], part1[4*j+2]);
+ }
+
+ do {
+ swap2(part0[4*i+2], part1[4*i+0]);
+ } while ((i = *bitTab++) != 0);
+}
+
+#if !defined(ARMV5E) && !defined(ARMV7Neon)
+
+/*****************************************************************************
+*
+* function name: Radix4First
+* description: Radix 4 point prepared function for fft
+*
+**********************************************************************************/
+static void Radix4First(int *buf, int num)
+{
+ int r0, r1, r2, r3;
+ int r4, r5, r6, r7;
+
+ for (; num != 0; num--)
+ {
+ r0 = buf[0] + buf[2];
+ r1 = buf[1] + buf[3];
+ r2 = buf[0] - buf[2];
+ r3 = buf[1] - buf[3];
+ r4 = buf[4] + buf[6];
+ r5 = buf[5] + buf[7];
+ r6 = buf[4] - buf[6];
+ r7 = buf[5] - buf[7];
+
+ buf[0] = r0 + r4;
+ buf[1] = r1 + r5;
+ buf[4] = r0 - r4;
+ buf[5] = r1 - r5;
+ buf[2] = r2 + r7;
+ buf[3] = r3 - r6;
+ buf[6] = r2 - r7;
+ buf[7] = r3 + r6;
+
+ buf += 8;
+ }
+}
+
+/*****************************************************************************
+*
+* function name: Radix8First
+* description: Radix 8 point prepared function for fft
+*
+**********************************************************************************/
+static void Radix8First(int *buf, int num)
+{
+ int r0, r1, r2, r3;
+ int i0, i1, i2, i3;
+ int r4, r5, r6, r7;
+ int i4, i5, i6, i7;
+ int t0, t1, t2, t3;
+
+ for ( ; num != 0; num--)
+ {
+ r0 = buf[0] + buf[2];
+ i0 = buf[1] + buf[3];
+ r1 = buf[0] - buf[2];
+ i1 = buf[1] - buf[3];
+ r2 = buf[4] + buf[6];
+ i2 = buf[5] + buf[7];
+ r3 = buf[4] - buf[6];
+ i3 = buf[5] - buf[7];
+
+ r4 = (r0 + r2) >> 1;
+ i4 = (i0 + i2) >> 1;
+ r5 = (r0 - r2) >> 1;
+ i5 = (i0 - i2) >> 1;
+ r6 = (r1 - i3) >> 1;
+ i6 = (i1 + r3) >> 1;
+ r7 = (r1 + i3) >> 1;
+ i7 = (i1 - r3) >> 1;
+
+ r0 = buf[ 8] + buf[10];
+ i0 = buf[ 9] + buf[11];
+ r1 = buf[ 8] - buf[10];
+ i1 = buf[ 9] - buf[11];
+ r2 = buf[12] + buf[14];
+ i2 = buf[13] + buf[15];
+ r3 = buf[12] - buf[14];
+ i3 = buf[13] - buf[15];
+
+ t0 = (r0 + r2) >> 1;
+ t1 = (i0 + i2) >> 1;
+ t2 = (r0 - r2) >> 1;
+ t3 = (i0 - i2) >> 1;
+
+ buf[ 0] = r4 + t0;
+ buf[ 1] = i4 + t1;
+ buf[ 8] = r4 - t0;
+ buf[ 9] = i4 - t1;
+ buf[ 4] = r5 + t3;
+ buf[ 5] = i5 - t2;
+ buf[12] = r5 - t3;
+ buf[13] = i5 + t2;
+
+ r0 = r1 - i3;
+ i0 = i1 + r3;
+ r2 = r1 + i3;
+ i2 = i1 - r3;
+
+ t0 = MULHIGH(SQRT1_2, r0 - i0);
+ t1 = MULHIGH(SQRT1_2, r0 + i0);
+ t2 = MULHIGH(SQRT1_2, r2 - i2);
+ t3 = MULHIGH(SQRT1_2, r2 + i2);
+
+ buf[ 6] = r6 - t0;
+ buf[ 7] = i6 - t1;
+ buf[14] = r6 + t0;
+ buf[15] = i6 + t1;
+ buf[ 2] = r7 + t3;
+ buf[ 3] = i7 - t2;
+ buf[10] = r7 - t3;
+ buf[11] = i7 + t2;
+
+ buf += 16;
+ }
+}
+
+/*****************************************************************************
+*
+* function name: Radix4FFT
+* description: Radix 4 point fft core function
+*
+**********************************************************************************/
+static void Radix4FFT(int *buf, int num, int bgn, int *twidTab)
+{
+ int r0, r1, r2, r3;
+ int r4, r5, r6, r7;
+ int t0, t1;
+ int sinx, cosx;
+ int i, j, step;
+ int *xptr, *csptr;
+
+ for (num >>= 2; num != 0; num >>= 2)
+ {
+ step = 2*bgn;
+ xptr = buf;
+
+ for (i = num; i != 0; i--)
+ {
+ csptr = twidTab;
+
+ for (j = bgn; j != 0; j--)
+ {
+ r0 = xptr[0];
+ r1 = xptr[1];
+ xptr += step;
+
+ t0 = xptr[0];
+ t1 = xptr[1];
+ cosx = csptr[0];
+ sinx = csptr[1];
+ r2 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*br + sin*bi */
+ r3 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*bi - sin*br */
+ xptr += step;
+
+ t0 = r0 >> 2;
+ t1 = r1 >> 2;
+ r0 = t0 - r2;
+ r1 = t1 - r3;
+ r2 = t0 + r2;
+ r3 = t1 + r3;
+
+ t0 = xptr[0];
+ t1 = xptr[1];
+ cosx = csptr[2];
+ sinx = csptr[3];
+ r4 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*cr + sin*ci */
+ r5 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*ci - sin*cr */
+ xptr += step;
+
+ t0 = xptr[0];
+ t1 = xptr[1];
+ cosx = csptr[4];
+ sinx = csptr[5];
+ r6 = MULHIGH(cosx, t0) + MULHIGH(sinx, t1); /* cos*cr + sin*ci */
+ r7 = MULHIGH(cosx, t1) - MULHIGH(sinx, t0); /* cos*ci - sin*cr */
+ csptr += 6;
+
+ t0 = r4;
+ t1 = r5;
+ r4 = t0 + r6;
+ r5 = r7 - t1;
+ r6 = t0 - r6;
+ r7 = r7 + t1;
+
+ xptr[0] = r0 + r5;
+ xptr[1] = r1 + r6;
+ xptr -= step;
+
+ xptr[0] = r2 - r4;
+ xptr[1] = r3 - r7;
+ xptr -= step;
+
+ xptr[0] = r0 - r5;
+ xptr[1] = r1 - r6;
+ xptr -= step;
+
+ xptr[0] = r2 + r4;
+ xptr[1] = r3 + r7;
+ xptr += 2;
+ }
+ xptr += 3*step;
+ }
+ twidTab += 3*step;
+ bgn <<= 2;
+ }
+}
+
+/*********************************************************************************
+*
+* function name: PreMDCT
+* description: prepare MDCT process for next FFT compute
+*
+**********************************************************************************/
+static void PreMDCT(int *buf0, int num, const int *csptr)
+{
+ int i;
+ int tr1, ti1, tr2, ti2;
+ int cosa, sina, cosb, sinb;
+ int *buf1;
+
+ buf1 = buf0 + num - 1;
+
+ for(i = num >> 2; i != 0; i--)
+ {
+ cosa = *csptr++;
+ sina = *csptr++;
+ cosb = *csptr++;
+ sinb = *csptr++;
+
+ tr1 = *(buf0 + 0);
+ ti2 = *(buf0 + 1);
+ tr2 = *(buf1 - 1);
+ ti1 = *(buf1 + 0);
+
+ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1);
+ *buf0++ = MULHIGH(cosa, ti1) - MULHIGH(sina, tr1);
+
+ *buf1-- = MULHIGH(cosb, ti2) - MULHIGH(sinb, tr2);
+ *buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2);
+ }
+}
+
+/*********************************************************************************
+*
+* function name: PostMDCT
+* description: post MDCT process after next FFT for MDCT
+*
+**********************************************************************************/
+static void PostMDCT(int *buf0, int num, const int *csptr)
+{
+ int i;
+ int tr1, ti1, tr2, ti2;
+ int cosa, sina, cosb, sinb;
+ int *buf1;
+
+ buf1 = buf0 + num - 1;
+
+ for(i = num >> 2; i != 0; i--)
+ {
+ cosa = *csptr++;
+ sina = *csptr++;
+ cosb = *csptr++;
+ sinb = *csptr++;
+
+ tr1 = *(buf0 + 0);
+ ti1 = *(buf0 + 1);
+ ti2 = *(buf1 + 0);
+ tr2 = *(buf1 - 1);
+
+ *buf0++ = MULHIGH(cosa, tr1) + MULHIGH(sina, ti1);
+ *buf1-- = MULHIGH(sina, tr1) - MULHIGH(cosa, ti1);
+
+ *buf0++ = MULHIGH(sinb, tr2) - MULHIGH(cosb, ti2);
+ *buf1-- = MULHIGH(cosb, tr2) + MULHIGH(sinb, ti2);
+ }
+}
+#endif
+
+
+/**********************************************************************************
+*
+* function name: Mdct_Long
+* description: the long block mdct, include long_start block, end_long block
+*
+**********************************************************************************/
+void Mdct_Long(int *buf)
+{
+ PreMDCT(buf, 1024, cossintab + 128);
+
+ Shuffle(buf, 512, bitrevTab + 17);
+ Radix8First(buf, 512 >> 3);
+ Radix4FFT(buf, 512 >> 3, 8, (int *)twidTab512);
+
+ PostMDCT(buf, 1024, cossintab + 128);
+}
+
+
+/**********************************************************************************
+*
+* function name: Mdct_Short
+* description: the short block mdct
+*
+**********************************************************************************/
+void Mdct_Short(int *buf)
+{
+ PreMDCT(buf, 128, cossintab);
+
+ Shuffle(buf, 64, bitrevTab);
+ Radix4First(buf, 64 >> 2);
+ Radix4FFT(buf, 64 >> 2, 4, (int *)twidTab64);
+
+ PostMDCT(buf, 128, cossintab);
+}
+
+
+/*****************************************************************************
+*
+* function name: shiftMdctDelayBuffer
+* description: the mdct delay buffer has a size of 1600,
+* so the calculation of LONG,STOP must be spilt in two
+* passes with 1024 samples and a mid shift,
+* the SHORT transforms can be completed in the delay buffer,
+* and afterwards a shift
+*
+**********************************************************************************/
+static void shiftMdctDelayBuffer(Word16 *mdctDelayBuffer, /*! start of mdct delay buffer */
+ Word16 *timeSignal, /*! pointer to new time signal samples, interleaved */
+ Word16 chIncrement /*! number of channels */
+ )
+{
+ Word32 i;
+ Word16 *srBuf = mdctDelayBuffer;
+ Word16 *dsBuf = mdctDelayBuffer+FRAME_LEN_LONG;
+
+ for(i = 0; i < BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG; i+= 8)
+ {
+ *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
+ *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
+ *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
+ *srBuf++ = *dsBuf++; *srBuf++ = *dsBuf++;
+ }
+
+ srBuf = mdctDelayBuffer + BLOCK_SWITCHING_OFFSET-FRAME_LEN_LONG;
+ dsBuf = timeSignal;
+
+ for(i=0; i<FRAME_LEN_LONG; i+=8)
+ {
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ *srBuf++ = *dsBuf; dsBuf += chIncrement;
+ }
+}
+
+
+/*****************************************************************************
+*
+* function name: getScalefactorOfShortVectorStride
+* description: Calculate max possible scale factor for input vector of shorts
+* returns: Maximum scale factor
+*
+**********************************************************************************/
+static Word16 getScalefactorOfShortVectorStride(const Word16 *vector, /*!< Pointer to input vector */
+ Word16 len, /*!< Length of input vector */
+ Word16 stride) /*!< Stride of input vector */
+{
+ Word16 maxVal = 0;
+ Word16 absVal;
+ Word16 i;
+
+ for(i=0; i<len; i++){
+ absVal = abs_s(vector[i*stride]);
+ maxVal |= absVal;
+ }
+
+ return( maxVal ? norm_s(maxVal) : 15);
+}
+
+
+/*****************************************************************************
+*
+* function name: Transform_Real
+* description: Calculate transform filter for input vector of shorts
+* returns: TRUE if success
+*
+**********************************************************************************/
+void Transform_Real(Word16 *mdctDelayBuffer,
+ Word16 *timeSignal,
+ Word16 chIncrement,
+ Word32 *realOut,
+ Word16 *mdctScale,
+ Word16 blockType
+ )
+{
+ Word32 i,w;
+ Word32 timeSignalSample;
+ Word32 ws1,ws2;
+ Word16 *dctIn0, *dctIn1;
+ Word32 *outData0, *outData1;
+ Word32 *winPtr;
+
+ Word32 delayBufferSf,timeSignalSf,minSf;
+ Word32 headRoom=0;
+
+ switch(blockType){
+
+
+ case LONG_WINDOW:
+ /*
+ we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + 448 new timeSignal samples
+ and get the biggest scale factor for next calculate more precise
+ */
+ delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1);
+ timeSignalSf = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement);
+ minSf = min(delayBufferSf,timeSignalSf);
+ minSf = min(minSf,14);
+
+ dctIn0 = mdctDelayBuffer;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+ outData0 = realOut + FRAME_LEN_LONG/2;
+
+ /* add windows and pre add for mdct to last buffer*/
+ winPtr = (int *)LongWindowKBD;
+ for(i=0;i<FRAME_LEN_LONG/2;i++){
+ timeSignalSample = (*dctIn0++) << minSf;
+ ws1 = timeSignalSample * (*winPtr >> 16);
+ timeSignalSample = (*dctIn1--) << minSf;
+ ws2 = timeSignalSample * (*winPtr & 0xffff);
+ winPtr ++;
+ /* shift 2 to avoid overflow next */
+ *outData0++ = (ws1 >> 2) - (ws2 >> 2);
+ }
+
+ shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+
+ /* add windows and pre add for mdct to new buffer*/
+ dctIn0 = mdctDelayBuffer;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+ outData0 = realOut + FRAME_LEN_LONG/2 - 1;
+ winPtr = (int *)LongWindowKBD;
+ for(i=0;i<FRAME_LEN_LONG/2;i++){
+ timeSignalSample = (*dctIn0++) << minSf;
+ ws1 = timeSignalSample * (*winPtr & 0xffff);
+ timeSignalSample = (*dctIn1--) << minSf;
+ ws2 = timeSignalSample * (*winPtr >> 16);
+ winPtr++;
+ /* shift 2 to avoid overflow next */
+ *outData0-- = -((ws1 >> 2) + (ws2 >> 2));
+ }
+
+ Mdct_Long(realOut);
+ /* update scale factor */
+ minSf = 14 - minSf;
+ *mdctScale=minSf;
+ break;
+
+ case START_WINDOW:
+ /*
+ we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no timeSignal samples
+ and get the biggest scale factor for next calculate more precise
+ */
+ minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer,BLOCK_SWITCHING_OFFSET,1);
+ minSf = min(minSf,14);
+
+ dctIn0 = mdctDelayBuffer;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+ outData0 = realOut + FRAME_LEN_LONG/2;
+ winPtr = (int *)LongWindowKBD;
+
+ /* add windows and pre add for mdct to last buffer*/
+ for(i=0;i<FRAME_LEN_LONG/2;i++){
+ timeSignalSample = (*dctIn0++) << minSf;
+ ws1 = timeSignalSample * (*winPtr >> 16);
+ timeSignalSample = (*dctIn1--) << minSf;
+ ws2 = timeSignalSample * (*winPtr & 0xffff);
+ winPtr ++;
+ *outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */
+ }
+
+ shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+
+ outData0 = realOut + FRAME_LEN_LONG/2 - 1;
+ for(i=0;i<LS_TRANS;i++){
+ *outData0-- = -mdctDelayBuffer[i] << (15 - 2 + minSf);
+ }
+
+ /* add windows and pre add for mdct to new buffer*/
+ dctIn0 = mdctDelayBuffer + LS_TRANS;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1 - LS_TRANS;
+ outData0 = realOut + FRAME_LEN_LONG/2 - 1 -LS_TRANS;
+ winPtr = (int *)ShortWindowSine;
+ for(i=0;i<FRAME_LEN_SHORT/2;i++){
+ timeSignalSample= (*dctIn0++) << minSf;
+ ws1 = timeSignalSample * (*winPtr & 0xffff);
+ timeSignalSample= (*dctIn1--) << minSf;
+ ws2 = timeSignalSample * (*winPtr >> 16);
+ winPtr++;
+ *outData0-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */
+ }
+
+ Mdct_Long(realOut);
+ /* update scale factor */
+ minSf = 14 - minSf;
+ *mdctScale= minSf;
+ break;
+
+ case STOP_WINDOW:
+ /*
+ we access BLOCK_SWITCHING_OFFSET-LS_TRANS (1600-448 ) delay buffer samples + 448 new timeSignal samples
+ and get the biggest scale factor for next calculate more precise
+ */
+ delayBufferSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+LS_TRANS,BLOCK_SWITCHING_OFFSET-LS_TRANS,1);
+ timeSignalSf = getScalefactorOfShortVectorStride(timeSignal,2*FRAME_LEN_LONG-BLOCK_SWITCHING_OFFSET,chIncrement);
+ minSf = min(delayBufferSf,timeSignalSf);
+ minSf = min(minSf,13);
+
+ outData0 = realOut + FRAME_LEN_LONG/2;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+ for(i=0;i<LS_TRANS;i++){
+ *outData0++ = -(*dctIn1--) << (15 - 2 + minSf);
+ }
+
+ /* add windows and pre add for mdct to last buffer*/
+ dctIn0 = mdctDelayBuffer + LS_TRANS;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1 - LS_TRANS;
+ outData0 = realOut + FRAME_LEN_LONG/2 + LS_TRANS;
+ winPtr = (int *)ShortWindowSine;
+ for(i=0;i<FRAME_LEN_SHORT/2;i++){
+ timeSignalSample = (*dctIn0++) << minSf;
+ ws1 = timeSignalSample * (*winPtr >> 16);
+ timeSignalSample= (*dctIn1--) << minSf;
+ ws2 = timeSignalSample * (*winPtr & 0xffff);
+ winPtr++;
+ *outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */
+ }
+
+ shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+
+ /* add windows and pre add for mdct to new buffer*/
+ dctIn0 = mdctDelayBuffer;
+ dctIn1 = mdctDelayBuffer + FRAME_LEN_LONG - 1;
+ outData0 = realOut + FRAME_LEN_LONG/2 - 1;
+ winPtr = (int *)LongWindowKBD;
+ for(i=0;i<FRAME_LEN_LONG/2;i++){
+ timeSignalSample= (*dctIn0++) << minSf;
+ ws1 = timeSignalSample *(*winPtr & 0xffff);
+ timeSignalSample= (*dctIn1--) << minSf;
+ ws2 = timeSignalSample * (*winPtr >> 16);
+ *outData0-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */
+ winPtr++;
+ }
+
+ Mdct_Long(realOut);
+ minSf = 14 - minSf;
+ *mdctScale= minSf; /* update scale factor */
+ break;
+
+ case SHORT_WINDOW:
+ /*
+ we access BLOCK_SWITCHING_OFFSET (1600 ) delay buffer samples + no new timeSignal samples
+ and get the biggest scale factor for next calculate more precise
+ */
+ minSf = getScalefactorOfShortVectorStride(mdctDelayBuffer+TRANSFORM_OFFSET_SHORT,9*FRAME_LEN_SHORT,1);
+ minSf = min(minSf,10);
+
+
+ for(w=0;w<TRANS_FAC;w++){
+ dctIn0 = mdctDelayBuffer+w*FRAME_LEN_SHORT+TRANSFORM_OFFSET_SHORT;
+ dctIn1 = mdctDelayBuffer+w*FRAME_LEN_SHORT+TRANSFORM_OFFSET_SHORT + FRAME_LEN_SHORT-1;
+ outData0 = realOut + FRAME_LEN_SHORT/2;
+ outData1 = realOut + FRAME_LEN_SHORT/2 - 1;
+
+ winPtr = (int *)ShortWindowSine;
+ for(i=0;i<FRAME_LEN_SHORT/2;i++){
+ timeSignalSample= *dctIn0 << minSf;
+ ws1 = timeSignalSample * (*winPtr >> 16);
+ timeSignalSample= *dctIn1 << minSf;
+ ws2 = timeSignalSample * (*winPtr & 0xffff);
+ *outData0++ = (ws1 >> 2) - (ws2 >> 2); /* shift 2 to avoid overflow next */
+
+ timeSignalSample= *(dctIn0 + FRAME_LEN_SHORT) << minSf;
+ ws1 = timeSignalSample * (*winPtr & 0xffff);
+ timeSignalSample= *(dctIn1 + FRAME_LEN_SHORT) << minSf;
+ ws2 = timeSignalSample * (*winPtr >> 16);
+ *outData1-- = -((ws1 >> 2) + (ws2 >> 2)); /* shift 2 to avoid overflow next */
+
+ winPtr++;
+ dctIn0++;
+ dctIn1--;
+ }
+
+ Mdct_Short(realOut);
+ realOut += FRAME_LEN_SHORT;
+ }
+
+ minSf = 11 - minSf;
+ *mdctScale = minSf; /* update scale factor */
+
+ shiftMdctDelayBuffer(mdctDelayBuffer,timeSignal,chIncrement);
+ break;
+ }
+}
+
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
index 7728597..fb300da 100644
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
@@ -117,7 +117,8 @@ status_t AMRNBDecoder::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
CHECK(seekTimeUs >= 0);
mNumSamplesOutput = 0;
diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
index f349671..c875426 100644
--- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
@@ -29,8 +29,9 @@ namespace android {
static const int32_t kNumSamplesPerFrame = 160;
static const int32_t kSampleRate = 8000;
-AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source)
+AMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
: mSource(source),
+ mMeta(meta),
mStarted(false),
mBufferGroup(NULL),
mEncState(NULL),
@@ -69,7 +70,10 @@ static Mode PickModeFromBitrate(int32_t bps) {
}
status_t AMRNBEncoder::start(MetaData *params) {
- CHECK(!mStarted);
+ if (mStarted) {
+ LOGW("Call start() when encoder already started");
+ return OK;
+ }
mBufferGroup = new MediaBufferGroup;
mBufferGroup->add_buffer(new MediaBuffer(32));
@@ -78,7 +82,7 @@ status_t AMRNBEncoder::start(MetaData *params) {
&mEncState, &mSidState, false /* dtx_enable */),
0);
- mSource->start();
+ mSource->start(params);
mAnchorTimeUs = 0;
mNumFramesOutput = 0;
@@ -96,7 +100,10 @@ status_t AMRNBEncoder::start(MetaData *params) {
}
status_t AMRNBEncoder::stop() {
- CHECK(mStarted);
+ if (!mStarted) {
+ LOGW("Call stop() when encoder has not started.");
+ return OK;
+ }
if (mInputBuffer) {
mInputBuffer->release();
@@ -119,28 +126,16 @@ status_t AMRNBEncoder::stop() {
sp<MetaData> AMRNBEncoder::getFormat() {
sp<MetaData> srcFormat = mSource->getFormat();
- int32_t numChannels;
- int32_t sampleRate;
-
- CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
- CHECK_EQ(numChannels, 1);
-
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
- CHECK_EQ(sampleRate, kSampleRate);
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
- meta->setInt32(kKeyChannelCount, numChannels);
- meta->setInt32(kKeySampleRate, sampleRate);
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
int64_t durationUs;
if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
+ mMeta->setInt64(kKeyDuration, durationUs);
}
- meta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
+ mMeta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
- return meta;
+ return mMeta;
}
status_t AMRNBEncoder::read(
@@ -150,7 +145,8 @@ status_t AMRNBEncoder::read(
*out = NULL;
int64_t seekTimeUs;
- CHECK(options == NULL || !options->getSeekTo(&seekTimeUs));
+ ReadOptions::SeekMode mode;
+ CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
while (mNumInputSamples < kNumSamplesPerFrame) {
if (mInputBuffer == NULL) {
diff --git a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
index c17c100..2a21472 100644
--- a/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
+++ b/media/libstagefright/codecs/amrwb/AMRWBDecoder.cpp
@@ -135,7 +135,8 @@ status_t AMRWBDecoder::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode seekMode;
+ if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
CHECK(seekTimeUs >= 0);
mNumSamplesOutput = 0;
diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
new file mode 100644
index 0000000..93304d0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AMRWBEncoder"
+#include <utils/Log.h>
+
+#include "AMRWBEncoder.h"
+#include "voAMRWB.h"
+#include "cmnMemory.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+static const int32_t kNumSamplesPerFrame = 320;
+static const int32_t kBitsPerSample = 16;
+static const int32_t kInputBufferSize = (kBitsPerSample / 8) * kNumSamplesPerFrame;
+static const int32_t kSampleRate = 16000;
+static const int32_t kNumChannels = 1;
+
+AMRWBEncoder::AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta)
+ : mSource(source),
+ mMeta(meta),
+ mStarted(false),
+ mBufferGroup(NULL),
+ mInputBuffer(NULL),
+ mEncoderHandle(NULL),
+ mApiHandle(NULL),
+ mMemOperator(NULL),
+ mAnchorTimeUs(0),
+ mNumFramesOutput(0),
+ mNumInputSamples(0) {
+}
+
+static VOAMRWBMODE pickModeFromBitRate(int32_t bps) {
+ CHECK(bps >= 0);
+ if (bps <= 6600) {
+ return VOAMRWB_MD66;
+ } else if (bps <= 8850) {
+ return VOAMRWB_MD885;
+ } else if (bps <= 12650) {
+ return VOAMRWB_MD1265;
+ } else if (bps <= 14250) {
+ return VOAMRWB_MD1425;
+ } else if (bps <= 15850) {
+ return VOAMRWB_MD1585;
+ } else if (bps <= 18250) {
+ return VOAMRWB_MD1825;
+ } else if (bps <= 19850) {
+ return VOAMRWB_MD1985;
+ } else if (bps <= 23050) {
+ return VOAMRWB_MD2305;
+ }
+ return VOAMRWB_MD2385;
+}
+
+status_t AMRWBEncoder::initCheck() {
+ CHECK(mApiHandle == NULL && mEncoderHandle == NULL);
+ CHECK(mMeta->findInt32(kKeyBitRate, &mBitRate));
+
+ mApiHandle = new VO_AUDIO_CODECAPI;
+ CHECK(mApiHandle);
+
+ if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
+ LOGE("Failed to get api handle");
+ return UNKNOWN_ERROR;
+ }
+
+ mMemOperator = new VO_MEM_OPERATOR;
+ CHECK(mMemOperator != NULL);
+ mMemOperator->Alloc = cmnMemAlloc;
+ mMemOperator->Copy = cmnMemCopy;
+ mMemOperator->Free = cmnMemFree;
+ mMemOperator->Set = cmnMemSet;
+ mMemOperator->Check = cmnMemCheck;
+
+ VO_CODEC_INIT_USERDATA userData;
+ memset(&userData, 0, sizeof(userData));
+ userData.memflag = VO_IMF_USERMEMOPERATOR;
+ userData.memData = (VO_PTR) mMemOperator;
+ if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
+ LOGE("Failed to init AMRWB encoder");
+ return UNKNOWN_ERROR;
+ }
+
+ // Configure AMRWB encoder$
+ VOAMRWBMODE mode = pickModeFromBitRate(mBitRate);
+ if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mode)) {
+ LOGE("Failed to set AMRWB encoder mode to %d", mode);
+ return UNKNOWN_ERROR;
+ }
+
+ VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
+ if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
+ LOGE("Failed to set AMRWB encoder frame type to %d", type);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+AMRWBEncoder::~AMRWBEncoder() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t AMRWBEncoder::start(MetaData *params) {
+ if (mStarted) {
+ LOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ mBufferGroup = new MediaBufferGroup;
+
+ // The largest buffer size is header + 477 bits
+ mBufferGroup->add_buffer(new MediaBuffer(1024));
+
+ CHECK_EQ(OK, initCheck());
+
+ mNumFramesOutput = 0;
+ mSource->start(params);
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t AMRWBEncoder::stop() {
+ if (!mStarted) {
+ LOGW("Call stop() when encoder has not started");
+ return OK;
+ }
+
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ delete mBufferGroup;
+ mBufferGroup = NULL;
+
+
+ CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
+ mEncoderHandle = NULL;
+
+ delete mApiHandle;
+ mApiHandle = NULL;
+
+ delete mMemOperator;
+ mMemOperator;
+
+ mStarted = false;
+
+ mSource->stop();
+ return OK;
+}
+
+sp<MetaData> AMRWBEncoder::getFormat() {
+ sp<MetaData> srcFormat = mSource->getFormat();
+
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
+
+ int64_t durationUs;
+ if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+ mMeta->setInt64(kKeyDuration, durationUs);
+ }
+
+ mMeta->setCString(kKeyDecoderComponent, "AMRWBEncoder");
+
+ return mMeta;
+}
+
+status_t AMRWBEncoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ status_t err;
+
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
+
+ while (mNumInputSamples < kNumSamplesPerFrame) {
+ if (mInputBuffer == NULL) {
+ err = mSource->read(&mInputBuffer, options);
+
+ if (err != OK) {
+ if (mNumInputSamples == 0) {
+ return ERROR_END_OF_STREAM;
+ }
+ memset(&mInputFrame[mNumInputSamples],
+ 0,
+ sizeof(int16_t)
+ * (kNumSamplesPerFrame - mNumInputSamples));
+ mNumInputSamples = 0;
+ break;
+ }
+
+ size_t align = mInputBuffer->range_length() % sizeof(int16_t);
+ CHECK_EQ(align, 0);
+
+ int64_t timeUs;
+ if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+ mAnchorTimeUs = timeUs;
+ }
+ }
+
+ size_t copy =
+ (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
+
+ if (copy > mInputBuffer->range_length()) {
+ copy = mInputBuffer->range_length();
+ }
+
+ memcpy(&mInputFrame[mNumInputSamples],
+ (const uint8_t *)mInputBuffer->data()
+ + mInputBuffer->range_offset(),
+ copy);
+
+ mInputBuffer->set_range(
+ mInputBuffer->range_offset() + copy,
+ mInputBuffer->range_length() - copy);
+
+ if (mInputBuffer->range_length() == 0) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ mNumInputSamples += copy / sizeof(int16_t);
+ if (mNumInputSamples >= kNumSamplesPerFrame) {
+ mNumInputSamples %= kNumSamplesPerFrame;
+ break; // Get a whole input frame 640 bytes
+ }
+ }
+
+ VO_CODECBUFFER inputData;
+ memset(&inputData, 0, sizeof(inputData));
+ inputData.Buffer = (unsigned char*) mInputFrame;
+ inputData.Length = kInputBufferSize;
+ CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
+
+ MediaBuffer *buffer;
+ CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
+ uint8_t *outPtr = (uint8_t *)buffer->data();
+
+ VO_CODECBUFFER outputData;
+ memset(&outputData, 0, sizeof(outputData));
+ VO_AUDIO_OUTPUTINFO outputInfo;
+ memset(&outputInfo, 0, sizeof(outputInfo));
+
+ VO_U32 ret = VO_ERR_NONE;
+ outputData.Buffer = outPtr;
+ outputData.Length = buffer->size();
+ ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
+ CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
+
+ buffer->set_range(0, outputData.Length);
+ ++mNumFramesOutput;
+
+ // XXX: fix timestamp calculation
+ int64_t timestampUs = mNumFramesOutput * 20000LL;
+
+ buffer->meta_data()->setInt64(kKeyTime, timestampUs);
+
+ *out = buffer;
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/amrwbenc/Android.mk b/media/libstagefright/codecs/amrwbenc/Android.mk
new file mode 100644
index 0000000..4293287
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/Android.mk
@@ -0,0 +1,120 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+include frameworks/base/media/libstagefright/codecs/common/Config.mk
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := \
+ AMRWBEncoder.cpp \
+ src/autocorr.c \
+ src/az_isp.c \
+ src/bits.c \
+ src/c2t64fx.c \
+ src/c4t64fx.c \
+ src/convolve.c \
+ src/cor_h_x.c \
+ src/decim54.c \
+ src/deemph.c \
+ src/dtx.c \
+ src/g_pitch.c \
+ src/gpclip.c \
+ src/homing.c \
+ src/hp400.c \
+ src/hp50.c \
+ src/hp6k.c \
+ src/hp_wsp.c \
+ src/int_lpc.c \
+ src/isp_az.c \
+ src/isp_isf.c \
+ src/lag_wind.c \
+ src/levinson.c \
+ src/log2.c \
+ src/lp_dec2.c \
+ src/math_op.c \
+ src/oper_32b.c \
+ src/p_med_ol.c \
+ src/pit_shrp.c \
+ src/pitch_f4.c \
+ src/pred_lt4.c \
+ src/preemph.c \
+ src/q_gain2.c \
+ src/q_pulse.c \
+ src/qisf_ns.c \
+ src/qpisf_2s.c \
+ src/random.c \
+ src/residu.c \
+ src/scale.c \
+ src/stream.c \
+ src/syn_filt.c \
+ src/updt_tar.c \
+ src/util.c \
+ src/voAMRWBEnc.c \
+ src/voicefac.c \
+ src/wb_vad.c \
+ src/weight_a.c \
+ src/mem_align.c
+
+
+ifeq ($(VOTT), v5)
+LOCAL_SRC_FILES += \
+ src/asm/ARMV5E/convolve_opt.s \
+ src/asm/ARMV5E/cor_h_vec_opt.s \
+ src/asm/ARMV5E/Deemph_32_opt.s \
+ src/asm/ARMV5E/Dot_p_opt.s \
+ src/asm/ARMV5E/Filt_6k_7k_opt.s \
+ src/asm/ARMV5E/Norm_Corr_opt.s \
+ src/asm/ARMV5E/pred_lt4_1_opt.s \
+ src/asm/ARMV5E/residu_asm_opt.s \
+ src/asm/ARMV5E/scale_sig_opt.s \
+ src/asm/ARMV5E/Syn_filt_32_opt.s \
+ src/asm/ARMV5E/syn_filt_opt.s
+
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_SRC_FILES += \
+ src/asm/ARMV7/convolve_neon.s \
+ src/asm/ARMV7/cor_h_vec_neon.s \
+ src/asm/ARMV7/Deemph_32_neon.s \
+ src/asm/ARMV7/Dot_p_neon.s \
+ src/asm/ARMV7/Filt_6k_7k_neon.s \
+ src/asm/ARMV7/Norm_Corr_neon.s \
+ src/asm/ARMV7/pred_lt4_1_neon.s \
+ src/asm/ARMV7/residu_asm_neon.s \
+ src/asm/ARMV7/scale_sig_neon.s \
+ src/asm/ARMV7/Syn_filt_32_neon.s \
+ src/asm/ARMV7/syn_filt_neon.s
+
+endif
+
+LOCAL_MODULE := libstagefright_amrwbenc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_SHARED_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+ frameworks/base/media/libstagefright/include \
+ frameworks/base/media/libstagefright/codecs/common/include \
+ frameworks/base/include \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/inc
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+ifeq ($(VOTT), v5)
+LOCAL_CFLAGS += -DARM -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
new file mode 100644
index 0000000..792d3cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/AMRWB_E_SAMPLE.c
@@ -0,0 +1,364 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+#ifdef LINUX
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "voAMRWB.h"
+#include "cmnMemory.h"
+
+#define VOAMRWB_RFC3267_HEADER_INFO "#!AMR-WB\n"
+
+#define INPUT_SIZE 640
+#define OUTPUT_SIZE 1024
+unsigned char InputBuf[INPUT_SIZE];
+unsigned char OutputBuf[OUTPUT_SIZE];
+
+void usage (void) {
+ printf ("AMR_WB Encoder HELP Displays this text\n");
+ printf ("\n");
+ printf ("Usage:\n");
+ printf ("AMRWBEnc [options] Input_file output_file \n");
+ printf ("\n");
+ printf ("Options +M* +F* +DTX \n");
+ printf ("Support \n");
+ printf ("Options +M* for seting compression bitrate mode, default is 23.85kbps\n");
+ printf (" +M0 = 6.6kbps \n");
+ printf (" +M1 = 8.85kbps \n");
+ printf (" +M2 = 12.65kbps \n");
+ printf (" +M3 = 14.25kbps \n");
+ printf (" +M4 = 15.58kbps \n");
+ printf (" +M5 = 18.25kbps \n");
+ printf (" +M6 = 19.85kbps \n");
+ printf (" +M7 = 23.05kbps \n");
+ printf (" +M8 = 23.85kbps \n");
+ printf ("\n");
+ printf ("Options +F* for setting output frame Type, default is RFC3267 \n");
+ printf ("+F0 for AMR_WB Defualt bit extern short data frame type \n");
+ printf ("+F1 for AMR_WB_ITU bit extern short data frame type \n");
+ printf ("+F2 for RFC3267\n ");
+ printf ("\n");
+ printf ("Options +DTX enable DTX mode, default is disable.\n");
+ printf ("File names, input raw PCM data, and output is AMR_WB bit-stream file.\n");
+ printf ("\n");
+}
+
+int GetNextBuf(FILE* inFile,unsigned char* dst,int size)
+{
+ int size2 = (int)fread(dst, sizeof(signed char), size,inFile);
+ return size2;
+}
+
+typedef int (VO_API * VOGETAUDIOENCAPI) (VO_AUDIO_CODECAPI * pEncHandle);
+
+int encode(
+ int mode,
+ short allow_dtx,
+ VOAMRWBFRAMETYPE frameType,
+ const char* srcfile,
+ const char* dstfile
+ )
+{
+ int ret = 0;
+ int returnCode;
+ FILE *fsrc = NULL;
+ FILE *fdst = NULL;
+ int framenum = 0;
+ int eofFile = 0;
+ int size1 = 0;
+ int Relens;
+
+ VO_AUDIO_CODECAPI AudioAPI;
+ VO_MEM_OPERATOR moper;
+ VO_CODEC_INIT_USERDATA useData;
+ VO_HANDLE hCodec;
+ VO_CODECBUFFER inData;
+ VO_CODECBUFFER outData;
+ VO_AUDIO_OUTPUTINFO outFormat;
+
+ unsigned char *inBuf = InputBuf;
+ unsigned char *outBuf = OutputBuf;
+
+
+#ifdef LINUX
+ void *handle = NULL;
+ void *pfunc;
+ VOGETAUDIOENCAPI pGetAPI;
+#endif
+
+ clock_t start, finish;
+ double duration = 0.0;
+
+ if ((fsrc = fopen (srcfile, "rb")) == NULL)
+ {
+ ret = -1;
+ goto safe_exit;
+ }
+
+ if ((fdst = fopen (dstfile, "wb")) == NULL)
+ {
+ ret = -1;
+ goto safe_exit;
+ }
+
+ moper.Alloc = cmnMemAlloc;
+ moper.Copy = cmnMemCopy;
+ moper.Free = cmnMemFree;
+ moper.Set = cmnMemSet;
+ moper.Check = cmnMemCheck;
+
+ useData.memflag = VO_IMF_USERMEMOPERATOR;
+ useData.memData = (VO_PTR)(&moper);
+
+#ifdef LINUX
+ handle = dlopen("/data/local/tmp/voAMRWBEnc.so", RTLD_NOW);
+ if(handle == 0)
+ {
+ printf("open dll error......");
+ return -1;
+ }
+
+ pfunc = dlsym(handle, "voGetAMRWBEncAPI");
+ if(pfunc == 0)
+ {
+ printf("open function error......");
+ return -1;
+ }
+
+ pGetAPI = (VOGETAUDIOENCAPI)pfunc;
+
+ returnCode = pGetAPI(&AudioAPI);
+ if(returnCode)
+ {
+ printf("get APIs error......");
+ return -1;
+ }
+#else
+ ret = voGetAMRWBEncAPI(&AudioAPI);
+ if(ret)
+ {
+ ret = -1;
+ printf("get APIs error......");
+ goto safe_exit;
+ }
+#endif
+
+ //####################################### Init Encoding Section #########################################
+ ret = AudioAPI.Init(&hCodec, VO_AUDIO_CodingAMRWB, &useData);
+
+ if(ret)
+ {
+ ret = -1;
+ printf("APIs init error......");
+ goto safe_exit;
+ }
+
+ Relens = GetNextBuf(fsrc,InputBuf,INPUT_SIZE);
+ if(Relens!=INPUT_SIZE && !feof(fsrc))
+ {
+ ret = -1; //Invalid magic number
+ printf("get next buffer error......");
+ goto safe_exit;
+ }
+
+ //###################################### set encode Mode ##################################################
+ ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_FRAMETYPE, &frameType);
+ ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_MODE, &mode);
+ ret = AudioAPI.SetParam(hCodec, VO_PID_AMRWB_DTX, &allow_dtx);
+
+ if(frameType == VOAMRWB_RFC3267)
+ {
+ /* write RFC3267 Header info to indicate single channel AMR file storage format */
+ size1 = (int)strlen(VOAMRWB_RFC3267_HEADER_INFO);
+ memcpy(outBuf, VOAMRWB_RFC3267_HEADER_INFO, size1);
+ outBuf += size1;
+ }
+
+ //####################################### Encoding Section #########################################
+ printf(" \n ---------------- Running -------------------------\n ");
+
+ do{
+ inData.Buffer = (unsigned char *)inBuf;
+ inData.Length = Relens;
+ outData.Buffer = outBuf;
+
+ start = clock();
+
+ /* decode one amr block */
+ returnCode = AudioAPI.SetInputData(hCodec,&inData);
+
+ do {
+ returnCode = AudioAPI.GetOutputData(hCodec,&outData, &outFormat);
+ if(returnCode == 0)
+ {
+ framenum++;
+ printf(" Frames processed: %hd\r", framenum);
+ if(framenum == 1)
+ {
+ fwrite(OutputBuf, 1, outData.Length + size1, fdst);
+ fflush(fdst);
+ }
+ else
+ {
+ fwrite(outData.Buffer, 1, outData.Length, fdst);
+ fflush(fdst);
+ }
+ }
+ else if(returnCode == VO_ERR_LICENSE_ERROR)
+ {
+ printf("Encoder time reach upper limit......");
+ goto safe_exit;
+ }
+ } while(returnCode != VO_ERR_INPUT_BUFFER_SMALL);
+
+ finish = clock();
+ duration += finish - start;
+
+ if (!eofFile) {
+ Relens = GetNextBuf(fsrc, InputBuf, INPUT_SIZE);
+ inBuf = InputBuf;
+ if (feof(fsrc) && Relens == 0)
+ eofFile = 1;
+ }
+ } while (!eofFile && returnCode);
+ //####################################### End Encoding Section #########################################
+
+safe_exit:
+ returnCode = AudioAPI.Uninit(hCodec);
+
+ printf( "\n%2.5f seconds\n", (double)duration/CLOCKS_PER_SEC);
+
+ if (fsrc)
+ fclose(fsrc);
+ if (fdst)
+ fclose(fdst);
+
+#ifdef LINUX
+ dlclose(handle);
+#endif
+
+ return ret;
+}
+
+int main(int argc, char **argv) // for gcc compiler;
+{
+ int mode, r;
+ int arg, filename=0;
+ char *inFileName = NULL;
+ char *outFileName = NULL;
+ short allow_dtx;
+ VOAMRWBFRAMETYPE frameType;
+
+ printf("\n");
+ printf("************************Adaptive Multi-Rate Wide Band Encoder (AMR-WB)*******************************\n");
+ printf("***********************************DEFINITIONS:*******************************************************\n");
+ printf("AMR-WB encoder scheme is based on the principle of Algebraic Code Excited Linear Prediction algorithm\n");
+ printf("The AMR-WB encoder compression MONO liner PCM speech input data at 16kHz sampling rate\n");
+ printf("to one of nine data rate modes-6.60, 8.85, 12.65, 14.25, 15.85, 18.25, 19.25, 23.05 and 23.85kbps.\n");
+ printf("The encoder supports output format AMRWB ITU, AMRWB RFC3267.\n");
+ printf("\n");
+
+ /*Encoder Default setting */
+ mode = VOAMRWB_MD2385;
+ allow_dtx = 0;
+ frameType = VOAMRWB_RFC3267;
+
+ if(argc < 3){
+ usage();
+ return 0;
+ }else{
+ for (arg = 1; arg < argc; arg++) {
+ if (argv [arg] [0] == '+') {
+ if(argv[arg][1] == 'M')
+ {
+ switch(argv[arg][2])
+ {
+ case '0': mode = VOAMRWB_MD66;
+ break;
+ case '1': mode = VOAMRWB_MD885;
+ break;
+ case '2': mode = VOAMRWB_MD1265;
+ break;
+ case '3': mode = VOAMRWB_MD1425;
+ break;
+ case '4': mode = VOAMRWB_MD1585;
+ break;
+ case '5': mode = VOAMRWB_MD1825;
+ break;
+ case '6': mode = VOAMRWB_MD1985;
+ break;
+ case '7': mode = VOAMRWB_MD2305;
+ break;
+ case '8': mode = VOAMRWB_MD2385;
+ break;
+ default:
+ usage();
+ printf ("Invalid parameter '%s'.\n", argv [arg]);
+ break;
+ }
+ }else if(argv[arg][1] == 'F')
+ {
+ switch(argv[arg][2])
+ {
+ case '0': frameType = VOAMRWB_DEFAULT;
+ break;
+ case '1': frameType = VOAMRWB_ITU;
+ break;
+ case '2': frameType = VOAMRWB_RFC3267 ;
+ break;
+ default:
+ usage();
+ printf ("Invalid parameter '%s'.\n", argv [arg]);
+ break;
+
+
+ }
+ }else if(strcmp (argv[arg], "+DTX") == 0)
+ {
+ allow_dtx = 1;
+ }
+
+ } else {
+ switch (filename) {
+ case 0:
+ inFileName = argv[arg];
+ break;
+ case 1:
+ outFileName = argv[arg];
+ break;
+ default:
+ usage ();
+ fprintf (stderr, "Invalid parameter '%s'.\n", argv [arg]);
+ return 0;
+ }
+ filename++;
+ }
+ }
+ }
+
+ r = encode(mode, allow_dtx, frameType, inFileName, outFileName);
+ if(r)
+ {
+ fprintf(stderr, "error: %d\n", r);
+ }
+ return r;
+}
+
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
new file mode 100644
index 0000000..7edb166
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/Android.mk
@@ -0,0 +1,27 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := AMRWB_E_SAMPLE.c
+
+LOCAL_SRC_FILES += \
+ ../../../Common/cmnMemory.c
+
+LOCAL_MODULE := TestvoAMRWBEnc
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_SHARED_LIBRARIES := libvoAMRWBEnc
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/ \
+ $(LOCAL_PATH)/../../../Common \
+ $(LOCAL_PATH)/../../../Include \
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+include $(BUILD_EXECUTABLE)
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
new file mode 100644
index 0000000..55b876a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/eclair/Makefile
@@ -0,0 +1,56 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+
+# target6
+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
+VOTT:= v6
+
+
+# module type
+# please specify the type of your module: lib or exe
+VOMT:= exe
+
+
+# module macros
+# please append the additional macro definitions here for your module if necessary.
+# e.g. -DVISUALON, macro VISUALON defined for your module
+VOMM:= #ARMV5E
+
+
+
+# please specify the name of your module
+VOTARGET:= voAMRWBEnc_Test
+
+
+# please modify here to be sure to see the g1.mk
+include ../../../../Tools/eclair.mk
+
+# dependent libraries.
+VODEPLIBS:=-ldl
+
+
+# module source
+# please modify here to be sure to see the ms.mk which specifies all source info of your module
+include ../ms.mk
+
+
+# please specify where is the voRelease on your PC, relative path is suggested
+VORELDIR:=../
+
+
+# please modify here to be sure to see the doit.mk
+include ../../../../Tools/doit.mk
+
diff --git a/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
new file mode 100644
index 0000000..74e8913
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/SampleCode/ms.mk
@@ -0,0 +1,24 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+# please list all objects needed by your target here
+OBJS:=AMRWB_E_SAMPLE.o cmnMemory.o
+
+# please list all directories that all source files relative with your module(.h .c .cpp) locate
+VOSRCDIR:=../ \
+ ../../../../Common \
+ ../../../../Include
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
new file mode 100644
index 0000000..58fda29
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV5E/Makefile
@@ -0,0 +1,53 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+
+# target type
+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
+VOTT:= v5
+
+
+# module type
+# please specify the type of your module: lib or exe
+VOMT:= lib
+
+
+# module macros
+# please append the additional macro definitions here for your module if necessary.
+ifeq ($(VOTT), v5)
+VOMM:=-DARM -DASM_OPT
+endif
+
+# please specify the name of your module
+VOTARGET:= libvoAMRWBEncv5
+
+
+# please modify here to be sure to see the g1.mk
+include ../../../../../Tools/eclair.mk
+
+# dependent libraries.
+VODEPLIBS:=-ldl -lstdc++ -lcutils
+
+# module source
+# please modify here to be sure to see the ms.mk which specifies all source info of your module
+include ../ms.mk
+
+
+# please specify where is the voRelease on your PC, relative path is suggested
+VORELDIR:=../../../../../../Release
+
+# please modify here to be sure to see the doit.mk
+include ../../../../../Tools/doit.mk
+
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
new file mode 100644
index 0000000..5686411
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ARMV7/Makefile
@@ -0,0 +1,53 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+
+# target type
+# available: pc, v4(armv4), v5(armv5), v5x(armv5 xscale), v6(armv6), v7(cortex-a8 neon)
+VOTT:= v7
+
+
+# module type
+# please specify the type of your module: lib or exe
+VOMT:= lib
+
+
+# module macros
+# please append the additional macro definitions here for your module if necessary.
+ifeq ($(VOTT), v7)
+VOMM:=-DARM -DARMV7 -DASM_OPT
+endif
+
+# please specify the name of your module
+VOTARGET:= libvoAMRWBEncv7
+
+
+# please modify here to be sure to see the g1.mk
+include ../../../../../Tools/eclair.mk
+
+# dependent libraries.
+VODEPLIBS:=-ldl -lstdc++ -lcutils
+
+# module source
+# please modify here to be sure to see the ms.mk which specifies all source info of your module
+include ../ms.mk
+
+
+# please specify where is the voRelease on your PC, relative path is suggested
+VORELDIR:=../../../../../../Release
+
+# please modify here to be sure to see the doit.mk
+include ../../../../../Tools/doit.mk
+
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/makefile b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
new file mode 100644
index 0000000..3473a1a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/makefile
@@ -0,0 +1,39 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+# Just acting as Father Makefile of Modules
+# please keep the name 'makefile' unchanged
+
+# Module Subdirs
+VOMSD:=$(dir $(shell find . -name 'Makefile'))
+
+all:
+ for dir in $(VOMSD); \
+ do \
+ $(MAKE) -C $$dir; \
+ done
+
+.PHONY:clean devel
+clean:
+ for dir in $(VOMSD); \
+ do \
+ $(MAKE) -C $$dir clean; \
+ done
+
+devel:
+ for dir in $(VOMSD); \
+ do \
+ $(MAKE) -C $$dir devel; \
+ done
diff --git a/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
new file mode 100644
index 0000000..bd6620c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/build/eclair/ms.mk
@@ -0,0 +1,43 @@
+#/*
+# ** Copyright 2003-2010, VisualOn, Inc.
+# **
+# ** Licensed under the Apache License, Version 2.0 (the "License");
+# ** you may not use this file except in compliance with the License.
+# ** You may obtain a copy of the License at
+# **
+# ** http://www.apache.org/licenses/LICENSE-2.0
+# **
+# ** Unless required by applicable law or agreed to in writing, software
+# ** distributed under the License is distributed on an "AS IS" BASIS,
+# ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# ** See the License for the specific language governing permissions and
+# ** limitations under the License.
+# */
+# please list all directories that all source files relative with your module(.h .c .cpp) locate
+VOSRCDIR:=../../../inc \
+ ../../../src \
+ ../../../../../Include
+
+# please list all objects needed by your target here
+OBJS:= autocorr.o az_isp.o bits.o c2t64fx.o c4t64fx.o convolve.o cor_h_x.o decim54.o \
+ deemph.o dtx.o g_pitch.o gpclip.o homing.o hp400.o hp50.o hp6k.o hp_wsp.o \
+ int_lpc.o isp_az.o isp_isf.o lag_wind.o levinson.o log2.o lp_dec2.o math_op.o mem_align.o \
+ oper_32b.o p_med_ol.o pit_shrp.o pitch_f4.o pred_lt4.o preemph.o q_gain2.o q_pulse.o \
+ qisf_ns.o qpisf_2s.o random.o residu.o scale.o stream.o syn_filt.o updt_tar.o util.o \
+ voAMRWBEnc.o voicefac.o wb_vad.o weight_a.o
+
+
+ifeq ($(VOTT), v5)
+OBJS += cor_h_vec_opt.o Deemph_32_opt.o Dot_p_opt.o Filt_6k_7k_opt.o residu_asm_opt.o \
+ scale_sig_opt.o Syn_filt_32_opt.o syn_filt_opt.o pred_lt4_1_opt.o convolve_opt.o \
+ Norm_Corr_opt.o
+VOSRCDIR+= ../../../src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+OBJS+= cor_h_vec_neon.o Deemph_32_neon.o Dot_p_neon.o Filt_6k_7k_neon.o residu_asm_neon.o \
+ scale_sig_neon.o Syn_filt_32_neon.o syn_filt_neon.o pred_lt4_1_neon.o convolve_neon.o \
+ Norm_Corr_neon.o
+VOSRCDIR+= ../../../src/asm/ARMV7
+endif
+
diff --git a/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf
new file mode 100644
index 0000000..5bade44
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/doc/voAMRWBEncoderSDK.pdf
Binary files differ
diff --git a/media/libstagefright/codecs/amrwbenc/inc/acelp.h b/media/libstagefright/codecs/amrwbenc/inc/acelp.h
new file mode 100644
index 0000000..4cb38a1
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/acelp.h
@@ -0,0 +1,521 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * ACELP.H *
+ *--------------------------------------------------------------------------*
+ * Function *
+ *--------------------------------------------------------------------------*/
+#ifndef __ACELP_H__
+#define __ACELP_H__
+
+#include "typedef.h"
+#include "cod_main.h"
+
+/*-----------------------------------------------------------------*
+ * LPC prototypes *
+ *-----------------------------------------------------------------*/
+
+Word16 median5(Word16 x[]);
+
+void Autocorr(
+ Word16 x[], /* (i) : Input signal */
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (o) : Autocorrelations (msb) */
+ Word16 r_l[] /* (o) : Autocorrelations (lsb) */
+ );
+
+void Lag_window(
+ Word16 r_h[], /* (i/o) : Autocorrelations (msb) */
+ Word16 r_l[] /* (i/o) : Autocorrelations (lsb) */
+ );
+
+void Init_Levinson(
+ Word16 * mem /* output :static memory (18 words) */
+ );
+
+void Levinson(
+ Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */
+ Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */
+ Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */
+ Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */
+ Word16 * mem /* (i/o) :static memory (18 words) */
+ );
+
+void Az_isp(
+ Word16 a[], /* (i) Q12 : predictor coefficients */
+ Word16 isp[], /* (o) Q15 : Immittance spectral pairs */
+ Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */
+ );
+
+void Isp_Az(
+ Word16 isp[], /* (i) Q15 : Immittance spectral pairs */
+ Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */
+ Word16 m,
+ Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */
+ /* 1 : adaptive scaling enabled */
+ );
+
+void Isp_isf(
+ Word16 isp[], /* (i) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 isf[], /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 m /* (i) : LPC order */
+ );
+
+void Isf_isp(
+ Word16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 m /* (i) : LPC order */
+ );
+
+void Int_isp(
+ Word16 isp_old[], /* input : isps from past frame */
+ Word16 isp_new[], /* input : isps from present frame */
+ Word16 frac[], /* input : fraction for 3 first subfr (Q15) */
+ Word16 Az[] /* output: LP coefficients in 4 subframes */
+ );
+
+void Weight_a(
+ Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
+ Word16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */
+ Word16 gamma, /* (i) Q15 : Spectral expansion factor. */
+ Word16 m /* (i) : LPC order. */
+ );
+
+
+/*-----------------------------------------------------------------*
+ * isf quantizers *
+ *-----------------------------------------------------------------*/
+
+void Qpisf_2s_46b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+ );
+
+void Qpisf_2s_36b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+ );
+
+void Dpisf_2s_46b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+ );
+
+void Dpisf_2s_36b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+ );
+
+void Qisf_ns(
+ Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* output: quantized ISF */
+ Word16 * indice /* output: quantization indices */
+ );
+
+void Disf_ns(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+ );
+
+Word16 Sub_VQ( /* output: return quantization index */
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word32 * distance /* output: error of quantization */
+ );
+
+void Reorder_isf(
+ Word16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */
+ Word16 min_dist, /* (i) Q15 : minimum distance to keep */
+ Word16 n /* (i) : number of ISF */
+ );
+
+/*-----------------------------------------------------------------*
+ * filter prototypes *
+ *-----------------------------------------------------------------*/
+
+void Init_Decim_12k8(
+ Word16 mem[] /* output: memory (2*NB_COEF_DOWN) set to zeros */
+ );
+void Decim_12k8(
+ Word16 sig16k[], /* input: signal to downsampling */
+ Word16 lg, /* input: length of input */
+ Word16 sig12k8[], /* output: decimated signal */
+ Word16 mem[] /* in/out: memory (2*NB_COEF_DOWN) */
+ );
+
+void Init_HP50_12k8(Word16 mem[]);
+void HP50_12k8(
+ Word16 signal[], /* input/output signal */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+ );
+void Init_HP400_12k8(Word16 mem[]);
+void HP400_12k8(
+ Word16 signal[], /* input/output signal */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+ );
+
+void Init_Filt_6k_7k(Word16 mem[]);
+void Filt_6k_7k(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+ );
+void Filt_6k_7k_asm(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+ );
+
+void LP_Decim2(
+ Word16 x[], /* in/out: signal to process */
+ Word16 l, /* input : size of filtering */
+ Word16 mem[] /* in/out: memory (size=3) */
+ );
+
+void Preemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+ );
+void Preemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+ );
+void Deemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ );
+void Deemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ );
+void Deemph_32(
+ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+ Word16 y[], /* (o) : output signal (x16) */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ );
+
+void Deemph_32_asm(
+ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+ Word16 y[], /* (o) : output signal (x16) */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ );
+
+void Convolve(
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) Q15 : impulse response */
+ Word16 y[], /* (o) 12 bits: output vector */
+ Word16 L /* (i) : vector size */
+ );
+
+void Convolve_asm(
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) Q15 : impulse response */
+ Word16 y[], /* (o) 12 bits: output vector */
+ Word16 L /* (i) : vector size */
+ );
+
+void Residu(
+ Word16 a[], /* (i) Q12 : prediction coefficients */
+ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */
+ Word16 y[], /* (o) : residual signal */
+ Word16 lg /* (i) : size of filtering */
+ );
+
+void Residu_opt(
+ Word16 a[], /* (i) Q12 : prediction coefficients */
+ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */
+ Word16 y[], /* (o) : residual signal */
+ Word16 lg /* (i) : size of filtering */
+ );
+
+void Syn_filt(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 x[], /* (i) : input signal */
+ Word16 y[], /* (o) : output signal */
+ Word16 lg, /* (i) : size of filtering */
+ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+ Word16 update /* (i) : 0=no update, 1=update of memory. */
+ );
+
+void Syn_filt_asm(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 x[], /* (i) : input signal */
+ Word16 y[], /* (o) : output signal */
+ Word16 mem[] /* (i/o) : memory associated with this filtering. */
+ );
+
+void Syn_filt_32(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ Word16 sig_hi[], /* (o) /16 : synthesis high */
+ Word16 sig_lo[], /* (o) /16 : synthesis low */
+ Word16 lg /* (i) : size of filtering */
+ );
+
+void Syn_filt_32_asm(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ Word16 sig_hi[], /* (o) /16 : synthesis high */
+ Word16 sig_lo[], /* (o) /16 : synthesis low */
+ Word16 lg /* (i) : size of filtering */
+ );
+/*-----------------------------------------------------------------*
+ * pitch prototypes *
+ *-----------------------------------------------------------------*/
+
+Word16 Pitch_ol( /* output: open loop pitch lag */
+ Word16 signal[], /* input : signal used to compute the open loop pitch */
+/* signal[-pit_max] to signal[-1] should be known */
+ Word16 pit_min, /* input : minimum pitch lag */
+ Word16 pit_max, /* input : maximum pitch lag */
+ Word16 L_frame /* input : length of frame to compute pitch */
+);
+
+Word16 Pitch_med_ol( /* output: open loop pitch lag */
+ Word16 wsp[], /* input : signal used to compute the open loop pitch */
+ /* wsp[-pit_max] to wsp[-1] should be known */
+ Coder_State *st, /* i/o : global codec structure */
+ Word16 L_frame /* input : length of frame to compute pitch */
+);
+
+Word16 Med_olag( /* output : median of 5 previous open-loop lags */
+ Word16 prev_ol_lag, /* input : previous open-loop lag */
+ Word16 old_ol_lag[5]
+);
+
+void Init_Hp_wsp(Word16 mem[]);
+void scale_mem_Hp_wsp(Word16 mem[], Word16 exp);
+void Hp_wsp(
+ Word16 wsp[], /* i : wsp[] signal */
+ Word16 hp_wsp[], /* o : hypass wsp[] */
+ Word16 lg, /* i : lenght of signal */
+ Word16 mem[] /* i/o : filter memory [9] */
+);
+
+Word16 Pitch_fr4( /* (o) : pitch period. */
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 t0_min, /* (i) : minimum value in the searched range. */
+ Word16 t0_max, /* (i) : maximum value in the searched range. */
+ Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */
+ Word16 i_subfr, /* (i) : indicator for first subframe. */
+ Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */
+ Word16 t0_fr1, /* (i) : minimum value for resolution 1 */
+ Word16 L_subfr /* (i) : Length of subframe */
+);
+void Pred_lt4(
+ Word16 exc[], /* in/out: excitation buffer */
+ Word16 T0, /* input : integer pitch lag */
+ Word16 frac, /* input : fraction of lag */
+ Word16 L_subfr /* input : subframe size */
+);
+
+void pred_lt4_asm(
+ Word16 exc[], /* in/out: excitation buffer */
+ Word16 T0, /* input : integer pitch lag */
+ Word16 frac, /* input : fraction of lag */
+ Word16 L_subfr /* input : subframe size */
+);
+
+/*-----------------------------------------------------------------*
+ * gain prototypes *
+ *-----------------------------------------------------------------*/
+
+Word16 G_pitch( /* (o) Q14 : Gain of pitch lag saturated to 1.2 */
+ Word16 xn[], /* (i) : Pitch target. */
+ Word16 y1[], /* (i) : filtered adaptive codebook. */
+ Word16 g_coeff[], /* : Correlations need for gain quantization. */
+ Word16 L_subfr /* : Length of subframe. */
+);
+void Init_Q_gain2(
+ Word16 * mem /* output :static memory (2 words) */
+);
+Word16 Q_gain2( /* Return index of quantization. */
+ Word16 xn[], /* (i) Q_xn:Target vector. */
+ Word16 y1[], /* (i) Q_xn:Adaptive codebook. */
+ Word16 Q_xn, /* (i) :xn and y1 format */
+ Word16 y2[], /* (i) Q9 :Filtered innovative vector. */
+ Word16 code[], /* (i) Q9 :Innovative vector. */
+ Word16 g_coeff[], /* (i) :Correlations <xn y1> <y1 y1> */
+/* Compute in G_pitch(). */
+ Word16 L_subfr, /* (i) :Subframe lenght. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 * gain_pit, /* (i/o)Q14:Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 :Code gain. */
+ Word16 gp_clip, /* (i) : Gp Clipping flag */
+ Word16 * mem /* (i/o) :static memory (2 words) */
+);
+
+void Init_D_gain2(
+ Word16 * mem /* output :static memory (4 words) */
+);
+void D_gain2(
+ Word16 index, /* (i) :index of quantization. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 code[], /* (i) Q9 :Innovative vector. */
+ Word16 L_subfr, /* (i) :Subframe lenght. */
+ Word16 * gain_pit, /* (o) Q14 :Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 :Code gain. */
+ Word16 bfi, /* (i) :bad frame indicator */
+ Word16 prev_bfi, /* (i) : Previous BF indicator */
+ Word16 state, /* (i) : State of BFH */
+ Word16 unusable_frame, /* (i) : UF indicator */
+ Word16 vad_hist, /* (i) :number of non-speech frames */
+ Word16 * mem /* (i/o) :static memory (4 words) */
+);
+
+/*-----------------------------------------------------------------*
+ * acelp prototypes *
+ *-----------------------------------------------------------------*/
+
+void cor_h_x(
+ Word16 h[], /* (i) Q12 : impulse response of weighted synthesis filter */
+ Word16 x[], /* (i) Q0 : target vector */
+ Word16 dn[] /* (o) <12bit : correlation between target and h[] */
+);
+void ACELP_2t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */
+);
+
+void ACELP_4t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ Word16 ser_size, /* (i) : bit rate */
+ Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */
+ /* (o) : index (36): 9+9+9+9 = 36 bits. */
+ /* (o) : index (44): 13+9+13+9 = 44 bits. */
+ /* (o) : index (52): 13+13+13+13 = 52 bits. */
+ /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+);
+
+void Pit_shrp(
+ Word16 * x, /* in/out: impulse response (or algebraic code) */
+ Word16 pit_lag, /* input : pitch lag */
+ Word16 sharp, /* input : pitch sharpening factor (Q15) */
+ Word16 L_subfr /* input : subframe size */
+);
+
+
+/*-----------------------------------------------------------------*
+ * others prototypes *
+ *-----------------------------------------------------------------*/
+
+void Copy(
+ Word16 x[], /* (i) : input vector */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector length */
+);
+void Set_zero(
+ Word16 x[], /* (o) : vector to clear */
+ Word16 L /* (i) : length of vector */
+);
+void Updt_tar(
+ Word16 * x, /* (i) Q0 : old target (for pitch search) */
+ Word16 * x2, /* (o) Q0 : new target (for codebook search) */
+ Word16 * y, /* (i) Q0 : filtered adaptive codebook vector */
+ Word16 gain, /* (i) Q14 : adaptive codebook gain */
+ Word16 L /* (i) : subframe size */
+);
+Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
+ Word16 exc[], /* (i) Q_exc: pitch excitation */
+ Word16 Q_exc, /* (i) : exc format */
+ Word16 gain_pit, /* (i) Q14 : gain of pitch */
+ Word16 code[], /* (i) Q9 : Fixed codebook excitation */
+ Word16 gain_code, /* (i) Q0 : gain of code */
+ Word16 L_subfr /* (i) : subframe length */
+);
+void Scale_sig(
+ Word16 x[], /* (i/o) : signal to scale */
+ Word16 lg, /* (i) : size of x[] */
+ Word16 exp /* (i) : exponent: x = round(x << exp) */
+);
+
+void Scale_sig_opt(
+ Word16 x[], /* (i/o) : signal to scale */
+ Word16 lg, /* (i) : size of x[] */
+ Word16 exp /* (i) : exponent: x = round(x << exp) */
+);
+
+Word16 Random(Word16 * seed);
+
+void Init_gp_clip(
+ Word16 mem[] /* (o) : memory of gain of pitch clipping algorithm */
+);
+Word16 Gp_clip(
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+);
+void Gp_clip_test_isf(
+ Word16 isf[], /* (i) : isf values (in frequency domain) */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+);
+void Gp_clip_test_gain_pit(
+ Word16 gain_pit, /* (i) : gain of quantized pitch */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+);
+
+
+#endif //__ACELP_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
new file mode 100644
index 0000000..6a2f860
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -0,0 +1,1094 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+#ifndef __BASIC_OP_H__
+#define __BASIC_OP_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+
+#define MAX_32 (Word32)0x7fffffffL
+#define MIN_32 (Word32)0x80000000L
+
+#define MAX_16 (Word16)+32767 /* 0x7fff */
+#define MIN_16 (Word16)-32768 /* 0x8000 */
+
+
+#ifdef LINUX
+#define static_vo static __inline__
+#else
+#define static_vo static __inline
+#endif
+
+#define saturate(L_var1) (((L_var1) > 0X00007fffL) ? (MAX_16): (((L_var1) < (Word32) 0xffff8000L) ? (MIN_16): ((L_var1) & 0xffff)))
+
+#define abs_s(x) ((Word16)(((x) != MIN_16) ? (((x) >= 0) ? (x) : (-(x))) : MAX_16)) /* Short abs, 1 */
+#define L_deposit_h(x) (((Word32)(x)) << 16) /* 16 bit var1 -> MSB, 2 */
+#define L_deposit_l(x) ((Word32)(x)) /* 16 bit var1 -> LSB, 2 */
+#define L_abs(x) (((x) != MIN_32) ? (((x) >= 0) ? (x) : (-(x))) : MAX_32) /* Long abs, 3*/
+#define negate(var1) ((Word16)(((var1) == MIN_16) ? MAX_16 : (-(var1)))) /* Short negate, 1*/
+#define L_negate(L_var1) (((L_var1) == (MIN_32)) ? (MAX_32) : (-(L_var1))) /* Long negate, 2*/
+
+
+#define extract_h(a) ((Word16)(a >> 16))
+#define extract_l(x) (Word16)((x))
+#define add1(a,b) (a + b)
+#define vo_L_msu(a,b,c) ( a - (( b * c ) << 1) )
+#define vo_mult32(a, b) ((a) * (b))
+#define vo_mult(a,b) (( a * b ) >> 15 )
+#define vo_L_mult(a,b) (((a) * (b)) << 1)
+#define vo_shr_r(var1, var2) ((var1+((Word16)(1L<<(var2-1))))>>var2)
+#define vo_sub(a,b) (a - b)
+#define vo_L_deposit_h(a) ((Word32)((a) << 16))
+#define vo_round(a) ((a + 0x00008000) >> 16)
+#define vo_extract_l(a) ((Word16)(a))
+#define vo_L_add(a,b) (a + b)
+#define vo_L_sub(a,b) (a - b)
+#define vo_mult_r(a,b) ((( a * b ) + 0x4000 ) >> 15 )
+#define vo_negate(a) (-a)
+#define vo_L_shr_r(L_var1, var2) ((L_var1+((Word32)(1L<<(var2-1))))>>var2)
+
+
+/*___________________________________________________________________________
+| |
+| Prototypes for basic arithmetic operators |
+|___________________________________________________________________________|
+*/
+static_vo Word16 add (Word16 var1, Word16 var2); /* Short add,1 */
+static_vo Word16 sub (Word16 var1, Word16 var2); /* Short sub,1 */
+static_vo Word16 shl (Word16 var1, Word16 var2); /* Short shift left, 1 */
+static_vo Word16 shr (Word16 var1, Word16 var2); /* Short shift right, 1 */
+static_vo Word16 mult (Word16 var1, Word16 var2); /* Short mult, 1 */
+static_vo Word32 L_mult (Word16 var1, Word16 var2); /* Long mult, 1 */
+static_vo Word16 voround (Word32 L_var1); /* Round, 1 */
+static_vo Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2); /* Mac, 1 */
+static_vo Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2); /* Msu, 1 */
+static_vo Word32 L_add (Word32 L_var1, Word32 L_var2); /* Long add, 2 */
+static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2); /* Long sub, 2 */
+static_vo Word16 mult_r (Word16 var1, Word16 var2); /* Mult with round, 2 */
+static_vo Word32 L_shl2(Word32 L_var1, Word16 var2); /* var2 > 0*/
+static_vo Word32 L_shl (Word32 L_var1, Word16 var2); /* Long shift left, 2 */
+static_vo Word32 L_shr (Word32 L_var1, Word16 var2); /* Long shift right, 2*/
+static_vo Word32 L_shr_r (Word32 L_var1, Word16 var2); /* Long shift right with round, 3 */
+static_vo Word16 norm_s (Word16 var1); /* Short norm, 15 */
+static_vo Word16 div_s (Word16 var1, Word16 var2); /* Short division, 18 */
+static_vo Word16 norm_l (Word32 L_var1); /* Long norm, 30 */
+
+/*___________________________________________________________________________
+| |
+| Functions |
+|___________________________________________________________________________|
+*/
+/*___________________________________________________________________________
+| |
+| Function Name : add |
+| |
+| Purpose : |
+| |
+| Performs the addition (var1+var2) with overflow control and saturation;|
+| the 16 bit result is set at +32767 when overflow occurs or at -32768 |
+| when underflow occurs. |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+static_vo Word16 add (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_sum;
+ L_sum = (Word32) var1 + var2;
+ var_out = saturate (L_sum);
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : sub |
+| |
+| Purpose : |
+| |
+| Performs the subtraction (var1+var2) with overflow control and satu- |
+| ration; the 16 bit result is set at +32767 when overflow occurs or at |
+| -32768 when underflow occurs. |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 sub (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_diff;
+ L_diff = (Word32) var1 - var2;
+ var_out = saturate (L_diff);
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : shl |
+| |
+| Purpose : |
+| |
+| Arithmetically shift the 16 bit input var1 left var2 positions.Zero fill|
+| the var2 LSB of the result. If var2 is negative, arithmetically shift |
+| var1 right by -var2 with sign extension. Saturate the result in case of |
+| underflows or overflows. |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 shl (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 result;
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = var1 >> ((Word16)-var2);
+ }
+ else
+ {
+ result = (Word32) var1 *((Word32) 1 << var2);
+ if ((var2 > 15 && var1 != 0) || (result != (Word32) ((Word16) result)))
+ {
+ var_out = (Word16)((var1 > 0) ? MAX_16 : MIN_16);
+ }
+ else
+ {
+ var_out = extract_l (result);
+ }
+ }
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : shr |
+| |
+| Purpose : |
+| |
+| Arithmetically shift the 16 bit input var1 right var2 positions with |
+| sign extension. If var2 is negative, arithmetically shift var1 left by |
+| -var2 with sign extension. Saturate the result in case of underflows or |
+| overflows. |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 shr (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ if (var2 < 0)
+ {
+ if (var2 < -16)
+ var2 = -16;
+ var_out = shl(var1, (Word16)-var2);
+ }
+ else
+ {
+ if (var2 >= 15)
+ {
+ var_out = (Word16)((var1 < 0) ? -1 : 0);
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var_out = (Word16)(~((~var1) >> var2));
+ }
+ else
+ {
+ var_out = (Word16)(var1 >> var2);
+ }
+ }
+ }
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : mult |
+| |
+| Purpose : |
+| |
+| Performs the multiplication of var1 by var2 and gives a 16 bit result |
+| which is scaled i.e.: |
+| mult(var1,var2) = extract_l(L_shr((var1 times var2),15)) and |
+| mult(-32768,-32768) = 32767. |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 mult (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product;
+ L_product = (Word32) var1 *(Word32) var2;
+ L_product = (L_product & (Word32) 0xffff8000L) >> 15;
+ if (L_product & (Word32) 0x00010000L)
+ L_product = L_product | (Word32) 0xffff0000L;
+ var_out = saturate (L_product);
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_mult |
+| |
+| Purpose : |
+| |
+| L_mult is the 32 bit result of the multiplication of var1 times var2 |
+| with one shift left i.e.: |
+| L_mult(var1,var2) = L_shl((var1 times var2),1) and |
+| L_mult(-32768,-32768) = 2147483647. |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_mult (Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ L_var_out = (Word32) var1 *(Word32) var2;
+ if (L_var_out != (Word32) 0x40000000L)
+ {
+ L_var_out *= 2;
+ }
+ else
+ {
+ L_var_out = MAX_32;
+ }
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : round |
+| |
+| Purpose : |
+| |
+| Round the lower 16 bits of the 32 bit input number into the MS 16 bits |
+| with saturation. Shift the resulting bits right by 16 and return the 16 |
+| bit number: |
+| round(L_var1) = extract_h(L_add(L_var1,32768)) |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| L_var1 |
+| 32 bit long signed integer (Word32 ) whose value falls in the |
+| range : 0x8000 0000 <= L_var1 <= 0x7fff ffff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 voround (Word32 L_var1)
+{
+ Word16 var_out;
+ Word32 L_rounded;
+ L_rounded = L_add (L_var1, (Word32) 0x00008000L);
+ var_out = extract_h (L_rounded);
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_mac |
+| |
+| Purpose : |
+| |
+| Multiply var1 by var2 and shift the result left by 1. Add the 32 bit |
+| result to L_var3 with saturation, return a 32 bit result: |
+| L_mac(L_var3,var1,var2) = L_add(L_var3,L_mult(var1,var2)). |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| L_var3 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_mac (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+ L_product = ((var1 * var2) << 1);
+ L_var_out = L_add (L_var3, L_product);
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_msu |
+| |
+| Purpose : |
+| |
+| Multiply var1 by var2 and shift the result left by 1. Subtract the 32 |
+| bit result to L_var3 with saturation, return a 32 bit result: |
+| L_msu(L_var3,var1,var2) = L_sub(L_var3,L_mult(var1,var2)). |
+| |
+| Complexity weight : 1 |
+| |
+| Inputs : |
+| |
+| L_var3 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_msu (Word32 L_var3, Word16 var1, Word16 var2)
+{
+ Word32 L_var_out;
+ Word32 L_product;
+ L_product = (var1 * var2)<<1;
+ L_var_out = L_sub (L_var3, L_product);
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_add |
+| |
+| Purpose : |
+| |
+| 32 bits addition of the two 32 bits variables (L_var1+L_var2) with |
+| overflow control and saturation; the result is set at +2147483647 when |
+| overflow occurs or at -2147483648 when underflow occurs. |
+| |
+| Complexity weight : 2 |
+| |
+| Inputs : |
+| |
+| L_var1 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| L_var2 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_add (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+ L_var_out = L_var1 + L_var2;
+ if (((L_var1 ^ L_var2) & MIN_32) == 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
+ }
+ }
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_sub |
+| |
+| Purpose : |
+| |
+| 32 bits subtraction of the two 32 bits variables (L_var1-L_var2) with |
+| overflow control and saturation; the result is set at +2147483647 when |
+| overflow occurs or at -2147483648 when underflow occurs. |
+| |
+| Complexity weight : 2 |
+| |
+| Inputs : |
+| |
+| L_var1 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| L_var2 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2)
+{
+ Word32 L_var_out;
+ L_var_out = L_var1 - L_var2;
+ if (((L_var1 ^ L_var2) & MIN_32) != 0)
+ {
+ if ((L_var_out ^ L_var1) & MIN_32)
+ {
+ L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
+ }
+ }
+ return (L_var_out);
+}
+
+
+/*___________________________________________________________________________
+| |
+| Function Name : mult_r |
+| |
+| Purpose : |
+| |
+| Same as mult with rounding, i.e.: |
+| mult_r(var1,var2) = extract_l(L_shr(((var1 * var2) + 16384),15)) and |
+| mult_r(-32768,-32768) = 32767. |
+| |
+| Complexity weight : 2 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var_out <= 0x0000 7fff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 mult_r (Word16 var1, Word16 var2)
+{
+ Word16 var_out;
+ Word32 L_product_arr;
+ L_product_arr = (Word32) var1 *(Word32) var2; /* product */
+ L_product_arr += (Word32) 0x00004000L; /* round */
+ L_product_arr &= (Word32) 0xffff8000L;
+ L_product_arr >>= 15; /* shift */
+ if (L_product_arr & (Word32) 0x00010000L) /* sign extend when necessary */
+ {
+ L_product_arr |= (Word32) 0xffff0000L;
+ }
+ var_out = saturate (L_product_arr);
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_shl |
+| |
+| Purpose : |
+| |
+| Arithmetically shift the 32 bit input L_var1 left var2 positions. Zero |
+| fill the var2 LSB of the result. If var2 is negative, arithmetically |
+| shift L_var1 right by -var2 with sign extension. Saturate the result in |
+| case of underflows or overflows. |
+| |
+| Complexity weight : 2 |
+| |
+| Inputs : |
+| |
+| L_var1 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_shl (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out = 0L;
+ if (var2 <= 0)
+ {
+ if (var2 < -32)
+ var2 = -32;
+ L_var_out = (L_var1 >> (Word16)-var2);
+ }
+ else
+ {
+ for (; var2 > 0; var2--)
+ {
+ if (L_var1 > (Word32) 0X3fffffffL)
+ {
+ L_var_out = MAX_32;
+ break;
+ }
+ else
+ {
+ if (L_var1 < (Word32) 0xc0000000L)
+ {
+ //Overflow = 1;
+ L_var_out = MIN_32;
+ break;
+ }
+ }
+ L_var1 *= 2;
+ L_var_out = L_var1;
+ }
+ }
+ return (L_var_out);
+}
+
+static_vo Word32 L_shl2(Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out = 0L;
+
+ for (; var2 > 0; var2--)
+ {
+ if (L_var1 > (Word32) 0X3fffffffL)
+ {
+ L_var_out = MAX_32;
+ break;
+ }
+ else
+ {
+ if (L_var1 < (Word32) 0xc0000000L)
+ {
+ L_var_out = MIN_32;
+ break;
+ }
+ }
+ L_var1 <<=1 ;
+ L_var_out = L_var1;
+ }
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_shr |
+| |
+| Purpose : |
+| |
+| Arithmetically shift the 32 bit input L_var1 right var2 positions with |
+| sign extension. If var2 is negative, arithmetically shift L_var1 left |
+| by -var2 and zero fill the -var2 LSB of the result. Saturate the result |
+| in case of underflows or overflows. |
+| |
+| Complexity weight : 2 |
+| |
+| Inputs : |
+| |
+| L_var1 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var3 <= 0x7fff ffff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= L_var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_shr (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+ if (var2 < 0)
+ {
+ if (var2 < -32)
+ var2 = -32;
+ L_var_out = L_shl2(L_var1, (Word16)-var2);
+ }
+ else
+ {
+ if (var2 >= 31)
+ {
+ L_var_out = (L_var1 < 0L) ? -1 : 0;
+ }
+ else
+ {
+ if (L_var1 < 0)
+ {
+ L_var_out = ~((~L_var1) >> var2);
+ }
+ else
+ {
+ L_var_out = L_var1 >> var2;
+ }
+ }
+ }
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : L_shr_r |
+| |
+| Purpose : |
+| |
+| Same as L_shr(L_var1,var2) but with rounding. Saturate the result in |
+| case of underflows or overflows : |
+| - If var2 is greater than zero : |
+| if (L_sub(L_shl(L_shr(L_var1,var2),1),L_shr(L_var1,sub(var2,1))))|
+| is equal to zero |
+| then |
+| L_shr_r(L_var1,var2) = L_shr(L_var1,var2) |
+| else |
+| L_shr_r(L_var1,var2) = L_add(L_shr(L_var1,var2),1) |
+| - If var2 is less than or equal to zero : |
+| L_shr_r(L_var1,var2) = L_shr(L_var1,var2). |
+| |
+| Complexity weight : 3 |
+| |
+| Inputs : |
+| |
+| L_var1 |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| L_var_out |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= var_out <= 0x7fff ffff. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word32 L_shr_r (Word32 L_var1, Word16 var2)
+{
+ Word32 L_var_out;
+ if (var2 > 31)
+ {
+ L_var_out = 0;
+ }
+ else
+ {
+ L_var_out = L_shr (L_var1, var2);
+ if (var2 > 0)
+ {
+ if ((L_var1 & ((Word32) 1 << (var2 - 1))) != 0)
+ {
+ L_var_out++;
+ }
+ }
+ }
+ return (L_var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : norm_s |
+| |
+| Purpose : |
+| |
+| Produces the number of left shift needed to normalize the 16 bit varia- |
+| ble var1 for positive values on the interval with minimum of 16384 and |
+| maximum of 32767, and for negative values on the interval with minimum |
+| of -32768 and maximum of -16384; in order to normalize the result, the |
+| following operation must be done : |
+| norm_var1 = shl(var1,norm_s(var1)). |
+| |
+| Complexity weight : 15 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0xffff 8000 <= var1 <= 0x0000 7fff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0x0000 0000 <= var_out <= 0x0000 000f. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 norm_s (Word16 var1)
+{
+ Word16 var_out = 0;
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == -1)
+ {
+ var_out = 15;
+ }
+ else
+ {
+ if (var1 < 0)
+ {
+ var1 = (Word16)~var1;
+ }
+ for (var_out = 0; var1 < 0x4000; var_out++)
+ {
+ var1 <<= 1;
+ }
+ }
+ }
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : div_s |
+| |
+| Purpose : |
+| |
+| Produces a result which is the fractional integer division of var1 by |
+| var2; var1 and var2 must be positive and var2 must be greater or equal |
+| to var1; the result is positive (leading bit equal to 0) and truncated |
+| to 16 bits. |
+| If var1 = var2 then div(var1,var2) = 32767. |
+| |
+| Complexity weight : 18 |
+| |
+| Inputs : |
+| |
+| var1 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0x0000 0000 <= var1 <= var2 and var2 != 0. |
+| |
+| var2 |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : var1 <= var2 <= 0x0000 7fff and var2 != 0. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0x0000 0000 <= var_out <= 0x0000 7fff. |
+| It's a Q15 value (point between b15 and b14). |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 div_s (Word16 var1, Word16 var2)
+{
+ Word16 var_out = 0;
+ Word16 iteration;
+ Word32 L_num;
+ Word32 L_denom;
+ if ((var1 < 0) || (var2 < 0))
+ {
+ var_out = MAX_16;
+ return var_out;
+ }
+ if (var2 == 0)
+ {
+ var_out = MAX_16;
+ return var_out;
+ }
+ if (var1 == 0)
+ {
+ var_out = 0;
+ }
+ else
+ {
+ if (var1 == var2)
+ {
+ var_out = MAX_16;
+ }
+ else
+ {
+ L_num = L_deposit_l (var1);
+ L_denom = L_deposit_l(var2);
+ for (iteration = 0; iteration < 15; iteration++)
+ {
+ var_out <<= 1;
+ L_num <<= 1;
+ if (L_num >= L_denom)
+ {
+ L_num -= L_denom;
+ var_out += 1;
+ }
+ }
+ }
+ }
+ return (var_out);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : norm_l |
+| |
+| Purpose : |
+| |
+| Produces the number of left shifts needed to normalize the 32 bit varia-|
+| ble L_var1 for positive values on the interval with minimum of |
+| 1073741824 and maximum of 2147483647, and for negative values on the in-|
+| terval with minimum of -2147483648 and maximum of -1073741824; in order |
+| to normalize the result, the following operation must be done : |
+| norm_L_var1 = L_shl(L_var1,norm_l(L_var1)). |
+| |
+| Complexity weight : 30 |
+| |
+| Inputs : |
+| |
+| L_var1 |
+| 32 bit long signed integer (Word32) whose value falls in the |
+| range : 0x8000 0000 <= var1 <= 0x7fff ffff. |
+| |
+| Outputs : |
+| |
+| none |
+| |
+| Return Value : |
+| |
+| var_out |
+| 16 bit short signed integer (Word16) whose value falls in the |
+| range : 0x0000 0000 <= var_out <= 0x0000 001f. |
+|___________________________________________________________________________|
+*/
+
+static_vo Word16 norm_l (Word32 L_var1)
+{
+ Word16 var_out = 0;
+ if (L_var1 != 0)
+ {
+ var_out = 31;
+ if (L_var1 != (Word32) 0xffffffffL)
+ {
+ L_var1 ^= (L_var1 >>31);
+ for (var_out = 0; L_var1 < (Word32) 0x40000000L; var_out++)
+ {
+ L_var1 <<= 1;
+ }
+ }
+ }
+ return (var_out);
+}
+
+#endif //__BASIC_OP_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/bits.h b/media/libstagefright/codecs/amrwbenc/inc/bits.h
new file mode 100644
index 0000000..77146de
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/bits.h
@@ -0,0 +1,92 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+* BITS.H *
+*--------------------------------------------------------------------------*
+* Number of bits for different modes *
+*--------------------------------------------------------------------------*/
+
+#ifndef __BITS_H__
+#define __BITS_H__
+
+#include <stdio.h>
+#include "typedef.h"
+#include "cnst.h"
+#include "cod_main.h"
+
+#define NBBITS_7k 132 /* 6.60k */
+#define NBBITS_9k 177 /* 8.85k */
+#define NBBITS_12k 253 /* 12.65k */
+#define NBBITS_14k 285 /* 14.25k */
+#define NBBITS_16k 317 /* 15.85k */
+#define NBBITS_18k 365 /* 18.25k */
+#define NBBITS_20k 397 /* 19.85k */
+#define NBBITS_23k 461 /* 23.05k */
+#define NBBITS_24k 477 /* 23.85k */
+
+#define NBBITS_SID 35
+#define NB_BITS_MAX NBBITS_24k
+
+#define BIT_0 (Word16)-127
+#define BIT_1 (Word16)127
+#define BIT_0_ITU (Word16)0x007F
+#define BIT_1_ITU (Word16)0x0081
+
+#define SIZE_MAX1 (3+NB_BITS_MAX) /* serial size max */
+#define TX_FRAME_TYPE (Word16)0x6b21
+#define RX_FRAME_TYPE (Word16)0x6b20
+
+static const Word16 nb_of_bits[NUM_OF_MODES] = {
+ NBBITS_7k,
+ NBBITS_9k,
+ NBBITS_12k,
+ NBBITS_14k,
+ NBBITS_16k,
+ NBBITS_18k,
+ NBBITS_20k,
+ NBBITS_23k,
+ NBBITS_24k,
+ NBBITS_SID
+};
+
+/*typedef struct
+{
+Word16 sid_update_counter;
+Word16 sid_handover_debt;
+Word16 prev_ft;
+} TX_State;
+*/
+
+//typedef struct
+//{
+// Word16 prev_ft;
+// Word16 prev_mode;
+//} RX_State;
+
+int PackBits(Word16 prms[], Word16 coding_mode, Word16 mode, Coder_State *st);
+
+
+void Parm_serial(
+ Word16 value, /* input : parameter value */
+ Word16 no_of_bits, /* input : number of bits */
+ Word16 ** prms
+ );
+
+
+#endif //__BITS_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/cnst.h b/media/libstagefright/codecs/amrwbenc/inc/cnst.h
new file mode 100644
index 0000000..ffdbd88
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/cnst.h
@@ -0,0 +1,81 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * CNST.H *
+ *--------------------------------------------------------------------------*
+ * Codec constant parameters (coder and decoder) *
+ *--------------------------------------------------------------------------*/
+
+#ifndef __CNST_H__
+#define __CNST_H__
+
+#define L_FRAME16k 320 /* Frame size at 16kHz */
+#define L_FRAME 256 /* Frame size */
+#define L_SUBFR16k 80 /* Subframe size at 16kHz */
+
+#define L_SUBFR 64 /* Subframe size */
+#define NB_SUBFR 4 /* Number of subframe per frame */
+
+#define L_NEXT 64 /* Overhead in LP analysis */
+#define L_WINDOW 384 /* window size in LP analysis */
+#define L_TOTAL 384 /* Total size of speech buffer. */
+#define M 16 /* Order of LP filter */
+#define M16k 20
+
+#define L_FILT16k 15 /* Delay of down-sampling filter */
+#define L_FILT 12 /* Delay of up-sampling filter */
+
+#define GP_CLIP 15565 /* Pitch gain clipping = 0.95 Q14 */
+#define PIT_SHARP 27853 /* pitch sharpening factor = 0.85 Q15 */
+
+#define PIT_MIN 34 /* Minimum pitch lag with resolution 1/4 */
+#define PIT_FR2 128 /* Minimum pitch lag with resolution 1/2 */
+#define PIT_FR1_9b 160 /* Minimum pitch lag with resolution 1 */
+#define PIT_FR1_8b 92 /* Minimum pitch lag with resolution 1 */
+#define PIT_MAX 231 /* Maximum pitch lag */
+#define L_INTERPOL (16+1) /* Length of filter for interpolation */
+
+#define OPL_DECIM 2 /* Decimation in open-loop pitch analysis */
+
+#define PREEMPH_FAC 22282 /* preemphasis factor (0.68 in Q15) */
+#define GAMMA1 30147 /* Weighting factor (numerator) (0.92 in Q15) */
+#define TILT_FAC 22282 /* tilt factor (denominator) (0.68 in Q15) */
+
+#define Q_MAX 8 /* scaling max for signal (see syn_filt_32) */
+
+#define RANDOM_INITSEED 21845 /* own random init value */
+
+#define L_MEANBUF 3
+#define ONE_PER_MEANBUF 10923
+
+#define MODE_7k 0
+#define MODE_9k 1
+#define MODE_12k 2
+#define MODE_14k 3
+#define MODE_16k 4
+#define MODE_18k 5
+#define MODE_20k 6
+#define MODE_23k 7
+#define MODE_24k 8
+#define MRDTX 9
+#define NUM_OF_MODES 10 /* see bits.h for bits definition */
+
+#define EHF_MASK (Word16)0x0008 /* homing frame pattern */
+
+#endif //__CNST_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/cod_main.h b/media/libstagefright/codecs/amrwbenc/inc/cod_main.h
new file mode 100644
index 0000000..1fd5787
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/cod_main.h
@@ -0,0 +1,103 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * COD_MAIN.H *
+ *--------------------------------------------------------------------------*
+ * Static memory in the encoder *
+ *--------------------------------------------------------------------------*/
+#ifndef __COD_MAIN_H__
+#define __COD_MAIN_H__
+
+#include "cnst.h" /* coder constant parameters */
+
+#include "wb_vad.h"
+#include "dtx.h"
+#include "stream.h"
+#include "voAMRWB.h"
+
+typedef struct
+{
+ Word16 mem_decim[2 * L_FILT16k]; /* speech decimated filter memory */
+ Word16 mem_sig_in[6]; /* hp50 filter memory */
+ Word16 mem_preemph; /* speech preemph filter memory */
+ Word16 old_speech[L_TOTAL - L_FRAME]; /* old speech vector at 12.8kHz */
+ Word16 old_wsp[PIT_MAX / OPL_DECIM]; /* old decimated weighted speech vector */
+ Word16 old_exc[PIT_MAX + L_INTERPOL]; /* old excitation vector */
+ Word16 mem_levinson[M + 2]; /* levinson routine memory */
+ Word16 ispold[M]; /* old isp (immittance spectral pairs) */
+ Word16 ispold_q[M]; /* quantized old isp */
+ Word16 past_isfq[M]; /* past isf quantizer */
+ Word16 mem_wsp; /* wsp vector memory */
+ Word16 mem_decim2[3]; /* wsp decimation filter memory */
+ Word16 mem_w0; /* target vector memory */
+ Word16 mem_syn[M]; /* synthesis memory */
+ Word16 tilt_code; /* tilt of code */
+ Word16 old_wsp_max; /* old wsp maximum value */
+ Word16 old_wsp_shift; /* old wsp shift */
+ Word16 Q_old; /* old scaling factor */
+ Word16 Q_max[2]; /* old maximum scaling factor */
+ Word16 gp_clip[2]; /* gain of pitch clipping memory */
+ Word16 qua_gain[4]; /* gain quantizer memory */
+
+ Word16 old_T0_med;
+ Word16 ol_gain;
+ Word16 ada_w;
+ Word16 ol_wght_flg;
+ Word16 old_ol_lag[5];
+ Word16 hp_wsp_mem[9];
+ Word16 old_hp_wsp[L_FRAME / OPL_DECIM + (PIT_MAX / OPL_DECIM)];
+ VadVars *vadSt;
+ dtx_encState *dtx_encSt;
+ Word16 first_frame;
+ Word16 isfold[M]; /* old isf (frequency domain) */
+ Word32 L_gc_thres; /* threshold for noise enhancer */
+ Word16 mem_syn_hi[M]; /* modified synthesis memory (MSB) */
+ Word16 mem_syn_lo[M]; /* modified synthesis memory (LSB) */
+ Word16 mem_deemph; /* speech deemph filter memory */
+ Word16 mem_sig_out[6]; /* hp50 filter memory for synthesis */
+ Word16 mem_hp400[6]; /* hp400 filter memory for synthesis */
+ Word16 mem_oversamp[2 * L_FILT]; /* synthesis oversampled filter memory */
+ Word16 mem_syn_hf[M]; /* HF synthesis memory */
+ Word16 mem_hf[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 mem_hf2[2 * L_FILT16k]; /* HF band-pass filter memory */
+ Word16 seed2; /* random memory for HF generation */
+ Word16 vad_hist;
+ Word16 gain_alpha;
+ /* TX_State structure */
+ Word16 sid_update_counter;
+ Word16 sid_handover_debt;
+ Word16 prev_ft;
+ Word16 allow_dtx;
+ /*some input/output buffer parameters */
+ unsigned char *inputStream;
+ int inputSize;
+ VOAMRWBMODE mode;
+ VOAMRWBFRAMETYPE frameType;
+ unsigned short *outputStream;
+ int outputSize;
+ FrameStream *stream;
+ VO_MEM_OPERATOR *pvoMemop;
+ VO_MEM_OPERATOR voMemoprator;
+ VO_PTR hCheck;
+} Coder_State;
+
+typedef void* HAMRENC;
+
+#endif //__COD_MAIN_H__
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/dtx.h b/media/libstagefright/codecs/amrwbenc/inc/dtx.h
new file mode 100644
index 0000000..e52c2d0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/dtx.h
@@ -0,0 +1,115 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * DTX.H *
+ *--------------------------------------------------------------------------*
+ * Static memory, constants and frametypes for the DTX *
+ *--------------------------------------------------------------------------*/
+
+#ifndef __DTX_H__
+#define __DTX_H__
+
+#define DTX_MAX_EMPTY_THRESH 50
+#define DTX_HIST_SIZE 8
+#define DTX_HIST_SIZE_MIN_ONE 7
+#define DTX_ELAPSED_FRAMES_THRESH (24 + 7 -1)
+#define DTX_HANG_CONST 7 /* yields eight frames of SP HANGOVER */
+#define INV_MED_THRESH 14564
+#define ISF_GAP 128 /* 50 */
+#define ONE_MINUS_ISF_GAP 16384 - ISF_GAP
+#define ISF_GAP 128
+#define ISF_DITH_GAP 448
+#define ISF_FACTOR_LOW 256
+#define ISF_FACTOR_STEP 2
+#define GAIN_THR 180
+#define GAIN_FACTOR 75
+
+typedef struct
+{
+ Word16 isf_hist[M * DTX_HIST_SIZE];
+ Word16 log_en_hist[DTX_HIST_SIZE];
+ Word16 hist_ptr;
+ Word16 log_en_index;
+ Word16 cng_seed;
+ /* DTX handler stuff */
+ Word16 dtxHangoverCount;
+ Word16 decAnaElapsedCount;
+ Word32 D[28];
+ Word32 sumD[DTX_HIST_SIZE];
+} dtx_encState;
+
+#define SPEECH 0
+#define DTX 1
+#define DTX_MUTE 2
+
+#define TX_SPEECH 0
+#define TX_SID_FIRST 1
+#define TX_SID_UPDATE 2
+#define TX_NO_DATA 3
+
+#define RX_SPEECH_GOOD 0
+#define RX_SPEECH_PROBABLY_DEGRADED 1
+#define RX_SPEECH_LOST 2
+#define RX_SPEECH_BAD 3
+#define RX_SID_FIRST 4
+#define RX_SID_UPDATE 5
+#define RX_SID_BAD 6
+#define RX_NO_DATA 7
+
+/*****************************************************************************
+ *
+ * DEFINITION OF DATA TYPES
+ *****************************************************************************/
+
+Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP);
+Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[]);
+void dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP);
+
+Word16 dtx_enc(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf[M], /* o : CN ISF vector */
+ Word16 * exc2, /* o : CN excitation */
+ Word16 ** prms
+);
+
+Word16 dtx_buffer(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf_new[], /* i : isf vector */
+ Word32 enr, /* i : residual energy (in L_FRAME) */
+ Word16 codec_mode
+);
+
+void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */
+ Word16 vad_flag, /* i : vad decision */
+ Word16 * usedMode /* i/o : mode changed or not */
+);
+
+void Qisf_ns(
+ Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* output: quantized ISF */
+ Word16 * indice /* output: quantization indices */
+);
+
+
+void Disf_ns(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+);
+
+#endif //__DTX_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/grid100.tab b/media/libstagefright/codecs/amrwbenc/inc/grid100.tab
new file mode 100644
index 0000000..efee18d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/grid100.tab
@@ -0,0 +1,53 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+
+/*-------------------------------------------------------------*
+ * Table for az_isp() *
+ * *
+ * Vector grid[] is in Q15 *
+ * *
+ * grid[0] = 1.0; *
+ * grid[grid_points+1] = -1.0; *
+ * for (i = 1; i < grid_points; i++) *
+ * grid[i] = cos((6.283185307*i)/(2.0*grid_points)); *
+ * *
+ *-------------------------------------------------------------*/
+
+/* Version 101 points */
+
+#define GRID_POINTS 100
+
+const Word16 vogrid[GRID_POINTS+1] ={
+ 32767, 32751, 32703, 32622, 32509, 32364,
+ 32187, 31978, 31738, 31466, 31164, 30830,
+ 30466, 30072, 29649, 29196, 28714, 28204,
+ 27666, 27101, 26509, 25891, 25248, 24579,
+ 23886, 23170, 22431, 21669, 20887, 20083,
+ 19260, 18418, 17557, 16680, 15786, 14876,
+ 13951, 13013, 12062, 11099, 10125, 9141,
+ 8149, 7148, 6140, 5126, 4106, 3083,
+ 2057, 1029, 0, -1029, -2057, -3083,
+ -4106, -5126, -6140, -7148, -8149, -9141,
+ -10125, -11099, -12062, -13013, -13951, -14876,
+ -15786, -16680, -17557, -18418, -19260, -20083,
+ -20887, -21669, -22431, -23170, -23886, -24579,
+ -25248, -25891, -26509, -27101, -27666, -28204,
+ -28714, -29196, -29649, -30072, -30466, -30830,
+ -31164, -31466, -31738, -31978, -32187, -32364,
+ -32509, -32622, -32703, -32751, -32760};
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab b/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab
new file mode 100644
index 0000000..91f8690
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/ham_wind.tab
@@ -0,0 +1,73 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/* Hamming_cos window for LPC analysis. */
+/* Create with function hamm_cos(window,384-128,128) */
+
+#define L_WINDOW 384
+
+const Word16 vo_window[L_WINDOW] = {
+ 2621, 2622, 2626, 2632, 2640, 2650, 2662, 2677,
+ 2694, 2714, 2735, 2759, 2785, 2814, 2844, 2877,
+ 2912, 2949, 2989, 3031, 3075, 3121, 3169, 3220,
+ 3273, 3328, 3385, 3444, 3506, 3569, 3635, 3703,
+ 3773, 3845, 3919, 3996, 4074, 4155, 4237, 4321,
+ 4408, 4496, 4587, 4680, 4774, 4870, 4969, 5069,
+ 5171, 5275, 5381, 5489, 5599, 5710, 5824, 5939,
+ 6056, 6174, 6295, 6417, 6541, 6666, 6793, 6922,
+ 7052, 7185, 7318, 7453, 7590, 7728, 7868, 8009,
+ 8152, 8296, 8442, 8589, 8737, 8887, 9038, 9191,
+ 9344, 9499, 9655, 9813, 9971, 10131, 10292, 10454,
+ 10617, 10781, 10946, 11113, 11280, 11448, 11617, 11787,
+ 11958, 12130, 12303, 12476, 12650, 12825, 13001, 13178,
+ 13355, 13533, 13711, 13890, 14070, 14250, 14431, 14612,
+ 14793, 14975, 15158, 15341, 15524, 15708, 15891, 16076,
+ 16260, 16445, 16629, 16814, 16999, 17185, 17370, 17555,
+ 17740, 17926, 18111, 18296, 18481, 18666, 18851, 19036,
+ 19221, 19405, 19589, 19773, 19956, 20139, 20322, 20504,
+ 20686, 20867, 21048, 21229, 21408, 21588, 21767, 21945,
+ 22122, 22299, 22475, 22651, 22825, 22999, 23172, 23344,
+ 23516, 23686, 23856, 24025, 24192, 24359, 24525, 24689,
+ 24853, 25016, 25177, 25337, 25496, 25654, 25811, 25967,
+ 26121, 26274, 26426, 26576, 26725, 26873, 27019, 27164,
+ 27308, 27450, 27590, 27729, 27867, 28003, 28137, 28270,
+ 28401, 28531, 28659, 28785, 28910, 29033, 29154, 29274,
+ 29391, 29507, 29622, 29734, 29845, 29953, 30060, 30165,
+ 30268, 30370, 30469, 30566, 30662, 30755, 30847, 30936,
+ 31024, 31109, 31193, 31274, 31354, 31431, 31506, 31579,
+ 31651, 31719, 31786, 31851, 31914, 31974, 32032, 32088,
+ 32142, 32194, 32243, 32291, 32336, 32379, 32419, 32458,
+ 32494, 32528, 32560, 32589, 32617, 32642, 32664, 32685,
+ 32703, 32719, 32733, 32744, 32753, 32760, 32764, 32767,
+ 32767, 32765, 32757, 32745, 32727, 32705, 32678, 32646,
+ 32609, 32567, 32520, 32468, 32411, 32349, 32283, 32211,
+ 32135, 32054, 31968, 31877, 31781, 31681, 31575, 31465,
+ 31351, 31231, 31107, 30978, 30844, 30706, 30563, 30415,
+ 30263, 30106, 29945, 29779, 29609, 29434, 29255, 29071,
+ 28883, 28691, 28494, 28293, 28087, 27878, 27664, 27446,
+ 27224, 26997, 26767, 26533, 26294, 26052, 25806, 25555,
+ 25301, 25043, 24782, 24516, 24247, 23974, 23698, 23418,
+ 23134, 22847, 22557, 22263, 21965, 21665, 21361, 21054,
+ 20743, 20430, 20113, 19794, 19471, 19146, 18817, 18486,
+ 18152, 17815, 17476, 17134, 16789, 16442, 16092, 15740,
+ 15385, 15028, 14669, 14308, 13944, 13579, 13211, 12841,
+ 12470, 12096, 11721, 11344, 10965, 10584, 10202, 9819,
+ 9433, 9047, 8659, 8270, 7879, 7488, 7095, 6701,
+ 6306, 5910, 5514, 5116, 4718, 4319, 3919, 3519,
+ 3118, 2716, 2315, 1913, 1510, 1108, 705, 302};
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/homing.tab b/media/libstagefright/codecs/amrwbenc/inc/homing.tab
new file mode 100644
index 0000000..2963da7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/homing.tab
@@ -0,0 +1,123 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+
+#define DHF_PARMS_MAX 32 /* homing frame pattern */
+#define NUM_OF_SPMODES 9
+
+#define PRML 15
+#define PRMN_7k NBBITS_7k/PRML + 1
+#define PRMN_9k NBBITS_9k/PRML + 1
+#define PRMN_12k NBBITS_12k/PRML + 1
+#define PRMN_14k NBBITS_14k/PRML + 1
+#define PRMN_16k NBBITS_16k/PRML + 1
+#define PRMN_18k NBBITS_18k/PRML + 1
+#define PRMN_20k NBBITS_20k/PRML + 1
+#define PRMN_23k NBBITS_23k/PRML + 1
+#define PRMN_24k NBBITS_24k/PRML + 1
+
+static const Word16 dfh_M7k[PRMN_7k] =
+{
+ 3168, 29954, 29213, 16121,
+ 64, 13440, 30624, 16430,
+ 19008
+};
+
+static const Word16 dfh_M9k[PRMN_9k] =
+{
+ 3168, 31665, 9943, 9123,
+ 15599, 4358, 20248, 2048,
+ 17040, 27787, 16816, 13888
+};
+
+static const Word16 dfh_M12k[PRMN_12k] =
+{
+ 3168, 31665, 9943, 9128,
+ 3647, 8129, 30930, 27926,
+ 18880, 12319, 496, 1042,
+ 4061, 20446, 25629, 28069,
+ 13948
+};
+
+static const Word16 dfh_M14k[PRMN_14k] =
+{
+ 3168, 31665, 9943, 9131,
+ 24815, 655, 26616, 26764,
+ 7238, 19136, 6144, 88,
+ 4158, 25733, 30567, 30494,
+ 221, 20321, 17823
+};
+
+static const Word16 dfh_M16k[PRMN_16k] =
+{
+ 3168, 31665, 9943, 9131,
+ 24815, 700, 3824, 7271,
+ 26400, 9528, 6594, 26112,
+ 108, 2068, 12867, 16317,
+ 23035, 24632, 7528, 1752,
+ 6759, 24576
+};
+
+static const Word16 dfh_M18k[PRMN_18k] =
+{
+ 3168, 31665, 9943, 9135,
+ 14787, 14423, 30477, 24927,
+ 25345, 30154, 916, 5728,
+ 18978, 2048, 528, 16449,
+ 2436, 3581, 23527, 29479,
+ 8237, 16810, 27091, 19052,
+ 0
+};
+
+static const Word16 dfh_M20k[PRMN_20k] =
+{
+ 3168, 31665, 9943, 9129,
+ 8637, 31807, 24646, 736,
+ 28643, 2977, 2566, 25564,
+ 12930, 13960, 2048, 834,
+ 3270, 4100, 26920, 16237,
+ 31227, 17667, 15059, 20589,
+ 30249, 29123, 0
+};
+
+static const Word16 dfh_M23k[PRMN_23k] =
+{
+ 3168, 31665, 9943, 9132,
+ 16748, 3202, 28179, 16317,
+ 30590, 15857, 19960, 8818,
+ 21711, 21538, 4260, 16690,
+ 20224, 3666, 4194, 9497,
+ 16320, 15388, 5755, 31551,
+ 14080, 3574, 15932, 50,
+ 23392, 26053, 31216
+};
+
+static const Word16 dfh_M24k[PRMN_24k] =
+{
+ 3168, 31665, 9943, 9134,
+ 24776, 5857, 18475, 28535,
+ 29662, 14321, 16725, 4396,
+ 29353, 10003, 17068, 20504,
+ 720, 0, 8465, 12581,
+ 28863, 24774, 9709, 26043,
+ 7941, 27649, 13965, 15236,
+ 18026, 22047, 16681, 3968
+};
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab
new file mode 100644
index 0000000..ff20e38
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/isp_isf.tab
@@ -0,0 +1,62 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-----------------------------------------------------*
+ | Tables for function Isf_isp() and Isp_isf() |
+ *-----------------------------------------------------*/
+
+/* table of cos(x) in Q15 */
+
+const static Word16 table[129] = {
+ 32767,
+ 32758, 32729, 32679, 32610, 32522, 32413, 32286, 32138,
+ 31972, 31786, 31581, 31357, 31114, 30853, 30572, 30274,
+ 29957, 29622, 29269, 28899, 28511, 28106, 27684, 27246,
+ 26791, 26320, 25833, 25330, 24812, 24279, 23732, 23170,
+ 22595, 22006, 21403, 20788, 20160, 19520, 18868, 18205,
+ 17531, 16846, 16151, 15447, 14733, 14010, 13279, 12540,
+ 11793, 11039, 10279, 9512, 8740, 7962, 7180, 6393,
+ 5602, 4808, 4011, 3212, 2411, 1608, 804, 0,
+ -804, -1608, -2411, -3212, -4011, -4808, -5602, -6393,
+ -7180, -7962, -8740, -9512, -10279, -11039, -11793, -12540,
+ -13279, -14010, -14733, -15447, -16151, -16846, -17531, -18205,
+ -18868, -19520, -20160, -20788, -21403, -22006, -22595, -23170,
+ -23732, -24279, -24812, -25330, -25833, -26320, -26791, -27246,
+ -27684, -28106, -28511, -28899, -29269, -29622, -29957, -30274,
+ -30572, -30853, -31114, -31357, -31581, -31786, -31972, -32138,
+ -32286, -32413, -32522, -32610, -32679, -32729, -32758, -32768};
+
+/* slope in Q11 used to compute y = acos(x) */
+
+const static Word16 slope[128] = {
+ -26214, -9039, -5243, -3799, -2979, -2405, -2064, -1771,
+ -1579, -1409, -1279, -1170, -1079, -1004, -933, -880,
+ -827, -783, -743, -708, -676, -647, -621, -599,
+ -576, -557, -538, -521, -506, -492, -479, -466,
+ -456, -445, -435, -426, -417, -410, -402, -395,
+ -389, -383, -377, -372, -367, -363, -359, -355,
+ -351, -348, -345, -342, -340, -337, -335, -333,
+ -331, -330, -329, -328, -327, -326, -326, -326,
+ -326, -326, -326, -327, -328, -329, -330, -331,
+ -333, -335, -337, -340, -342, -345, -348, -351,
+ -355, -359, -363, -367, -372, -377, -383, -389,
+ -395, -402, -410, -417, -426, -435, -445, -456,
+ -466, -479, -492, -506, -521, -538, -557, -576,
+ -599, -621, -647, -676, -708, -743, -783, -827,
+ -880, -933, -1004, -1079, -1170, -1279, -1409, -1579,
+ -1771, -2064, -2405, -2979, -3799, -5243, -9039, -26214};
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab b/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab
new file mode 100644
index 0000000..4175d66
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/lag_wind.tab
@@ -0,0 +1,81 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-----------------------------------------------------*
+ | Table of lag_window for autocorrelation. |
+ | noise floor = 1.0001 = (0.9999 on r[1] ..r[16]) |
+ | Bandwidth expansion = 60 Hz |
+ | Sampling frequency = 12800 Hz |
+ | |
+ | Special double precision format. See "math_op.c" |
+ | |
+ | lag_wind[0] = 1.00000000 (not stored) |
+ | lag_wind[1] = 0.99946642 |
+ | lag_wind[2] = 0.99816680 |
+ | lag_wind[3] = 0.99600452 |
+ | lag_wind[4] = 0.99298513 |
+ | lag_wind[5] = 0.98911655 |
+ | lag_wind[6] = 0.98440880 |
+ | lag_wind[7] = 0.97887397 |
+ | lag_wind[8] = 0.97252619 |
+ | lag_wind[9] = 0.96538186 |
+ | lag_wind[10]= 0.95745903 |
+ | lag_wind[11]= 0.94877797 |
+ | lag_wind[12]= 0.93936038 |
+ | lag_wind[13]= 0.92922986 |
+ | lag_wind[14]= 0.91841155 |
+ | lag_wind[15]= 0.90693212 |
+ | lag_wind[16]= 0.89481968 |
+ ------------------------------------------------------*/
+
+#define M 16
+
+static Word16 volag_h[M] = {
+ 32750,
+ 32707,
+ 32637,
+ 32538,
+ 32411,
+ 32257,
+ 32075,
+ 31867,
+ 31633,
+ 31374,
+ 31089,
+ 30780,
+ 30449,
+ 30094,
+ 29718,
+ 29321};
+
+static Word16 volag_l[M] = {
+ 16896,
+ 30464,
+ 2496,
+ 4480,
+ 12160,
+ 3520,
+ 24320,
+ 24192,
+ 20736,
+ 576,
+ 18240,
+ 31488,
+ 128,
+ 16704,
+ 11520,
+ 14784};
diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2.h b/media/libstagefright/codecs/amrwbenc/inc/log2.h
new file mode 100644
index 0000000..91bdbec
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/log2.h
@@ -0,0 +1,62 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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 : log2.h
+* Purpose : Computes log2(L_x)
+*
+********************************************************************************
+*/
+#ifndef __LOG2_H__
+#define __LOG2_H__
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include "typedef.h"
+
+/*
+********************************************************************************
+* DEFINITION OF DATA TYPES
+********************************************************************************
+*/
+
+/*
+********************************************************************************
+* DECLARATION OF PROTOTYPES
+********************************************************************************
+*/
+void Log2 (
+ Word32 L_x, /* (i) : input value */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1)*/
+ );
+
+void Log2_norm (
+ Word32 L_x, /* (i) : input value (normalized) */
+ Word16 exp, /* (i) : norm_l (L_x) */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ );
+
+#endif //__LOG2_H__
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h b/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h
new file mode 100644
index 0000000..7761ae6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/log2_tab.h
@@ -0,0 +1,35 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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 : log2.tab
+* Purpose : Table for routine Log2().
+* $Id $
+*
+********************************************************************************
+*/
+static const Word16 table[33] =
+{
+ 0, 1455, 2866, 4236, 5568, 6863, 8124, 9352, 10549, 11716,
+ 12855, 13967, 15054, 16117, 17156, 18172, 19167, 20142, 21097, 22033,
+ 22951, 23852, 24735, 25603, 26455, 27291, 28113, 28922, 29716, 30497,
+ 31266, 32023, 32767
+};
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/main.h b/media/libstagefright/codecs/amrwbenc/inc/main.h
new file mode 100644
index 0000000..d7e7c67
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/main.h
@@ -0,0 +1,45 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * MAIN.H *
+ *--------------------------------------------------------------------------*
+ * Main functions *
+ *--------------------------------------------------------------------------*/
+
+#ifndef __MAIN_H__
+#define __MAIN_H__
+
+void coder(
+ Word16 * mode, /* input : used mode */
+ Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */
+ Word16 prms[], /* output: output parameters */
+ Word16 * ser_size, /* output: bit rate of the used mode */
+ void *spe_state, /* i/o : State structure */
+ Word16 allow_dtx /* input : DTX ON/OFF */
+);
+
+
+
+void Reset_encoder(void *st, Word16 reset_all);
+
+
+Word16 encoder_homing_frame_test(Word16 input_frame[]);
+
+#endif //__MAIN_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/math_op.h b/media/libstagefright/codecs/amrwbenc/inc/math_op.h
new file mode 100644
index 0000000..25e29f7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/math_op.h
@@ -0,0 +1,55 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * MATH_OP.H *
+ *--------------------------------------------------------------------------*
+ * Mathematical operations *
+ *--------------------------------------------------------------------------*/
+
+#ifndef __MATH_OP_H__
+#define __MATH_OP_H__
+
+Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */
+ Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
+ );
+
+void Isqrt_n(
+ Word32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+ );
+
+Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+ );
+
+Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+ Word16 x[], /* (i) 12bits: x vector */
+ Word16 y[], /* (i) 12bits: y vector */
+ Word16 lg, /* (i) : vector length */
+ Word16 * exp /* (o) : exponent of result (0..+30) */
+ );
+
+Word32 Dot_product12_asm( /* (o) Q31: normalized result (1 < val <= -1) */
+ Word16 x[], /* (i) 12bits: x vector */
+ Word16 y[], /* (i) 12bits: y vector */
+ Word16 lg, /* (i) : vector length */
+ Word16 * exp /* (o) : exponent of result (0..+30) */
+ );
+#endif //__MATH_OP_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/mem_align.h b/media/libstagefright/codecs/amrwbenc/inc/mem_align.h
new file mode 100644
index 0000000..d6ddec3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/mem_align.h
@@ -0,0 +1,35 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: mem_align.h
+
+ Content: Memory alloc alignments functions
+
+*******************************************************************************/
+
+#ifndef __VO_MEM_ALIGN_H__
+#define __VO_MEM_ALIGN_H__
+
+#include "voMem.h"
+#include "typedef.h"
+
+extern void *mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID);
+extern void mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID);
+
+#endif /* __VO_MEM_ALIGN_H__ */
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab b/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab
new file mode 100644
index 0000000..ffc86a1
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/mime_io.tab
@@ -0,0 +1,368 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include <stdio.h>
+#include "typedef.h"
+
+static UWord8 toc_byte[16] = {0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x34, 0x3C,
+ 0x44, 0x4C, 0x54, 0x5C, 0x64, 0x6C, 0x74, 0x7C};
+
+/* number of speech bits for all modes */
+static Word16 unpacked_size[16] = {132, 177, 253, 285, 317, 365, 397, 461,
+ 477, 35, 0, 0, 0, 0, 0, 0};
+
+/* size of packed frame for each mode, excluding TOC byte */
+static Word16 packed_size[16] = {17, 23, 32, 36, 40, 46, 50, 58,
+ 60, 5, 0, 0, 0, 0, 0, 0};
+
+/* number of unused speech bits in packed format for each mode */
+static Word16 unused_size[16] = {4, 7, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0};
+
+/* sorting tables for all modes */
+
+static Word16 sort_660[132] = {
+ 0, 5, 6, 7, 61, 84, 107, 130, 62, 85,
+ 8, 4, 37, 38, 39, 40, 58, 81, 104, 127,
+ 60, 83, 106, 129, 108, 131, 128, 41, 42, 80,
+ 126, 1, 3, 57, 103, 82, 105, 59, 2, 63,
+ 109, 110, 86, 19, 22, 23, 64, 87, 18, 20,
+ 21, 17, 13, 88, 43, 89, 65, 111, 14, 24,
+ 25, 26, 27, 28, 15, 16, 44, 90, 66, 112,
+ 9, 11, 10, 12, 67, 113, 29, 30, 31, 32,
+ 34, 33, 35, 36, 45, 51, 68, 74, 91, 97,
+ 114, 120, 46, 69, 92, 115, 52, 75, 98, 121,
+ 47, 70, 93, 116, 53, 76, 99, 122, 48, 71,
+ 94, 117, 54, 77, 100, 123, 49, 72, 95, 118,
+ 55, 78, 101, 124, 50, 73, 96, 119, 56, 79,
+ 102, 125
+};
+
+static Word16 sort_885[177] = {
+ 0, 4, 6, 7, 5, 3, 47, 48, 49, 112,
+ 113, 114, 75, 106, 140, 171, 80, 111, 145, 176,
+ 77, 108, 142, 173, 78, 109, 143, 174, 79, 110,
+ 144, 175, 76, 107, 141, 172, 50, 115, 51, 2,
+ 1, 81, 116, 146, 19, 21, 12, 17, 18, 20,
+ 16, 25, 13, 10, 14, 24, 23, 22, 26, 8,
+ 15, 52, 117, 31, 82, 147, 9, 33, 11, 83,
+ 148, 53, 118, 28, 27, 84, 149, 34, 35, 29,
+ 46, 32, 30, 54, 119, 37, 36, 39, 38, 40,
+ 85, 150, 41, 42, 43, 44, 45, 55, 60, 65,
+ 70, 86, 91, 96, 101, 120, 125, 130, 135, 151,
+ 156, 161, 166, 56, 87, 121, 152, 61, 92, 126,
+ 157, 66, 97, 131, 162, 71, 102, 136, 167, 57,
+ 88, 122, 153, 62, 93, 127, 158, 67, 98, 132,
+ 163, 72, 103, 137, 168, 58, 89, 123, 154, 63,
+ 94, 128, 159, 68, 99, 133, 164, 73, 104, 138,
+ 169, 59, 90, 124, 155, 64, 95, 129, 160, 69,
+ 100, 134, 165, 74, 105, 139, 170
+};
+
+static Word16 sort_1265[253] = {
+ 0, 4, 6, 93, 143, 196, 246, 7, 5, 3,
+ 47, 48, 49, 50, 51, 150, 151, 152, 153, 154,
+ 94, 144, 197, 247, 99, 149, 202, 252, 96, 146,
+ 199, 249, 97, 147, 200, 250, 100, 203, 98, 148,
+ 201, 251, 95, 145, 198, 248, 52, 2, 1, 101,
+ 204, 155, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 156, 31, 102, 205, 9, 33, 11, 103, 206, 54,
+ 157, 28, 27, 104, 207, 34, 35, 29, 46, 32,
+ 30, 55, 158, 37, 36, 39, 38, 40, 105, 208,
+ 41, 42, 43, 44, 45, 56, 106, 159, 209, 57,
+ 66, 75, 84, 107, 116, 125, 134, 160, 169, 178,
+ 187, 210, 219, 228, 237, 58, 108, 161, 211, 62,
+ 112, 165, 215, 67, 117, 170, 220, 71, 121, 174,
+ 224, 76, 126, 179, 229, 80, 130, 183, 233, 85,
+ 135, 188, 238, 89, 139, 192, 242, 59, 109, 162,
+ 212, 63, 113, 166, 216, 68, 118, 171, 221, 72,
+ 122, 175, 225, 77, 127, 180, 230, 81, 131, 184,
+ 234, 86, 136, 189, 239, 90, 140, 193, 243, 60,
+ 110, 163, 213, 64, 114, 167, 217, 69, 119, 172,
+ 222, 73, 123, 176, 226, 78, 128, 181, 231, 82,
+ 132, 185, 235, 87, 137, 190, 240, 91, 141, 194,
+ 244, 61, 111, 164, 214, 65, 115, 168, 218, 70,
+ 120, 173, 223, 74, 124, 177, 227, 79, 129, 182,
+ 232, 83, 133, 186, 236, 88, 138, 191, 241, 92,
+ 142, 195, 245
+};
+
+static Word16 sort_1425[285] = {
+ 0, 4, 6, 101, 159, 220, 278, 7, 5, 3,
+ 47, 48, 49, 50, 51, 166, 167, 168, 169, 170,
+ 102, 160, 221, 279, 107, 165, 226, 284, 104, 162,
+ 223, 281, 105, 163, 224, 282, 108, 227, 106, 164,
+ 225, 283, 103, 161, 222, 280, 52, 2, 1, 109,
+ 228, 171, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 172, 31, 110, 229, 9, 33, 11, 111, 230, 54,
+ 173, 28, 27, 112, 231, 34, 35, 29, 46, 32,
+ 30, 55, 174, 37, 36, 39, 38, 40, 113, 232,
+ 41, 42, 43, 44, 45, 56, 114, 175, 233, 62,
+ 120, 181, 239, 75, 133, 194, 252, 57, 115, 176,
+ 234, 63, 121, 182, 240, 70, 128, 189, 247, 76,
+ 134, 195, 253, 83, 141, 202, 260, 92, 150, 211,
+ 269, 84, 142, 203, 261, 93, 151, 212, 270, 85,
+ 143, 204, 262, 94, 152, 213, 271, 86, 144, 205,
+ 263, 95, 153, 214, 272, 64, 122, 183, 241, 77,
+ 135, 196, 254, 65, 123, 184, 242, 78, 136, 197,
+ 255, 87, 145, 206, 264, 96, 154, 215, 273, 58,
+ 116, 177, 235, 66, 124, 185, 243, 71, 129, 190,
+ 248, 79, 137, 198, 256, 88, 146, 207, 265, 97,
+ 155, 216, 274, 59, 117, 178, 236, 67, 125, 186,
+ 244, 72, 130, 191, 249, 80, 138, 199, 257, 89,
+ 147, 208, 266, 98, 156, 217, 275, 60, 118, 179,
+ 237, 68, 126, 187, 245, 73, 131, 192, 250, 81,
+ 139, 200, 258, 90, 148, 209, 267, 99, 157, 218,
+ 276, 61, 119, 180, 238, 69, 127, 188, 246, 74,
+ 132, 193, 251, 82, 140, 201, 259, 91, 149, 210,
+ 268, 100, 158, 219, 277
+};
+
+static Word16 sort_1585[317] = {
+ 0, 4, 6, 109, 175, 244, 310, 7, 5, 3,
+ 47, 48, 49, 50, 51, 182, 183, 184, 185, 186,
+ 110, 176, 245, 311, 115, 181, 250, 316, 112, 178,
+ 247, 313, 113, 179, 248, 314, 116, 251, 114, 180,
+ 249, 315, 111, 177, 246, 312, 52, 2, 1, 117,
+ 252, 187, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 188, 31, 118, 253, 9, 33, 11, 119, 254, 54,
+ 189, 28, 27, 120, 255, 34, 35, 29, 46, 32,
+ 30, 55, 190, 37, 36, 39, 38, 40, 121, 256,
+ 41, 42, 43, 44, 45, 56, 122, 191, 257, 63,
+ 129, 198, 264, 76, 142, 211, 277, 89, 155, 224,
+ 290, 102, 168, 237, 303, 57, 123, 192, 258, 70,
+ 136, 205, 271, 83, 149, 218, 284, 96, 162, 231,
+ 297, 62, 128, 197, 263, 75, 141, 210, 276, 88,
+ 154, 223, 289, 101, 167, 236, 302, 58, 124, 193,
+ 259, 71, 137, 206, 272, 84, 150, 219, 285, 97,
+ 163, 232, 298, 59, 125, 194, 260, 64, 130, 199,
+ 265, 67, 133, 202, 268, 72, 138, 207, 273, 77,
+ 143, 212, 278, 80, 146, 215, 281, 85, 151, 220,
+ 286, 90, 156, 225, 291, 93, 159, 228, 294, 98,
+ 164, 233, 299, 103, 169, 238, 304, 106, 172, 241,
+ 307, 60, 126, 195, 261, 65, 131, 200, 266, 68,
+ 134, 203, 269, 73, 139, 208, 274, 78, 144, 213,
+ 279, 81, 147, 216, 282, 86, 152, 221, 287, 91,
+ 157, 226, 292, 94, 160, 229, 295, 99, 165, 234,
+ 300, 104, 170, 239, 305, 107, 173, 242, 308, 61,
+ 127, 196, 262, 66, 132, 201, 267, 69, 135, 204,
+ 270, 74, 140, 209, 275, 79, 145, 214, 280, 82,
+ 148, 217, 283, 87, 153, 222, 288, 92, 158, 227,
+ 293, 95, 161, 230, 296, 100, 166, 235, 301, 105,
+ 171, 240, 306, 108, 174, 243, 309
+};
+
+static Word16 sort_1825[365] = {
+ 0, 4, 6, 121, 199, 280, 358, 7, 5, 3,
+ 47, 48, 49, 50, 51, 206, 207, 208, 209, 210,
+ 122, 200, 281, 359, 127, 205, 286, 364, 124, 202,
+ 283, 361, 125, 203, 284, 362, 128, 287, 126, 204,
+ 285, 363, 123, 201, 282, 360, 52, 2, 1, 129,
+ 288, 211, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 212, 31, 130, 289, 9, 33, 11, 131, 290, 54,
+ 213, 28, 27, 132, 291, 34, 35, 29, 46, 32,
+ 30, 55, 214, 37, 36, 39, 38, 40, 133, 292,
+ 41, 42, 43, 44, 45, 56, 134, 215, 293, 198,
+ 299, 136, 120, 138, 60, 279, 58, 62, 357, 139,
+ 140, 295, 156, 57, 219, 297, 63, 217, 137, 170,
+ 300, 222, 64, 106, 61, 78, 294, 92, 142, 141,
+ 135, 221, 296, 301, 343, 59, 298, 184, 329, 315,
+ 220, 216, 265, 251, 218, 237, 352, 223, 157, 86,
+ 171, 87, 164, 351, 111, 302, 65, 178, 115, 323,
+ 72, 192, 101, 179, 93, 73, 193, 151, 337, 309,
+ 143, 274, 69, 324, 165, 150, 97, 338, 110, 310,
+ 330, 273, 68, 107, 175, 245, 114, 79, 113, 189,
+ 246, 259, 174, 71, 185, 96, 344, 100, 322, 83,
+ 334, 316, 333, 252, 161, 348, 147, 82, 269, 232,
+ 260, 308, 353, 347, 163, 231, 306, 320, 188, 270,
+ 146, 177, 266, 350, 256, 85, 149, 116, 191, 160,
+ 238, 258, 336, 305, 255, 88, 224, 99, 339, 230,
+ 228, 227, 272, 242, 241, 319, 233, 311, 102, 74,
+ 180, 275, 66, 194, 152, 325, 172, 247, 244, 261,
+ 117, 158, 166, 354, 75, 144, 108, 312, 94, 186,
+ 303, 80, 234, 89, 195, 112, 340, 181, 345, 317,
+ 326, 276, 239, 167, 118, 313, 70, 355, 327, 253,
+ 190, 176, 271, 104, 98, 153, 103, 90, 76, 267,
+ 277, 248, 225, 262, 182, 84, 154, 235, 335, 168,
+ 331, 196, 341, 249, 162, 307, 148, 349, 263, 321,
+ 257, 243, 229, 356, 159, 119, 67, 187, 173, 145,
+ 240, 77, 304, 332, 314, 342, 109, 254, 81, 278,
+ 105, 91, 346, 318, 183, 250, 197, 328, 95, 155,
+ 169, 268, 226, 236, 264
+};
+
+static Word16 sort_1985[397] = {
+ 0, 4, 6, 129, 215, 304, 390, 7, 5, 3,
+ 47, 48, 49, 50, 51, 222, 223, 224, 225, 226,
+ 130, 216, 305, 391, 135, 221, 310, 396, 132, 218,
+ 307, 393, 133, 219, 308, 394, 136, 311, 134, 220,
+ 309, 395, 131, 217, 306, 392, 52, 2, 1, 137,
+ 312, 227, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 228, 31, 138, 313, 9, 33, 11, 139, 314, 54,
+ 229, 28, 27, 140, 315, 34, 35, 29, 46, 32,
+ 30, 55, 230, 37, 36, 39, 38, 40, 141, 316,
+ 41, 42, 43, 44, 45, 56, 142, 231, 317, 63,
+ 73, 92, 340, 82, 324, 149, 353, 159, 334, 165,
+ 338, 178, 163, 254, 77, 168, 257, 153, 343, 57,
+ 248, 238, 79, 252, 166, 67, 80, 201, 101, 267,
+ 143, 164, 341, 255, 339, 187, 376, 318, 78, 328,
+ 362, 115, 232, 242, 253, 290, 276, 62, 58, 158,
+ 68, 93, 179, 319, 148, 169, 154, 72, 385, 329,
+ 333, 344, 102, 83, 144, 233, 323, 124, 243, 192,
+ 354, 237, 64, 247, 202, 209, 150, 116, 335, 268,
+ 239, 299, 188, 196, 298, 94, 195, 258, 123, 363,
+ 384, 109, 325, 371, 170, 370, 84, 110, 295, 180,
+ 74, 210, 191, 106, 291, 205, 367, 381, 377, 206,
+ 355, 122, 119, 120, 383, 160, 105, 108, 277, 380,
+ 294, 284, 285, 345, 208, 269, 249, 366, 386, 300,
+ 297, 259, 125, 369, 197, 97, 194, 286, 211, 281,
+ 280, 183, 372, 87, 155, 283, 59, 348, 327, 184,
+ 76, 111, 330, 203, 349, 69, 98, 152, 145, 189,
+ 66, 320, 337, 173, 358, 251, 198, 174, 263, 262,
+ 126, 241, 193, 88, 388, 117, 95, 387, 112, 359,
+ 287, 244, 103, 272, 301, 171, 162, 234, 273, 127,
+ 373, 181, 292, 85, 378, 302, 121, 107, 364, 346,
+ 356, 212, 278, 213, 65, 382, 288, 207, 113, 175,
+ 99, 296, 374, 368, 199, 260, 185, 336, 331, 161,
+ 270, 264, 250, 240, 75, 350, 151, 60, 89, 321,
+ 156, 274, 360, 326, 70, 282, 167, 146, 352, 81,
+ 91, 389, 266, 245, 177, 235, 190, 256, 204, 342,
+ 128, 118, 303, 104, 379, 182, 114, 375, 200, 96,
+ 293, 172, 214, 365, 279, 86, 289, 351, 347, 357,
+ 261, 186, 176, 271, 90, 100, 147, 322, 275, 361,
+ 71, 332, 61, 265, 157, 246, 236
+};
+
+static Word16 sort_2305[461] = {
+ 0, 4, 6, 145, 247, 352, 454, 7, 5, 3,
+ 47, 48, 49, 50, 51, 254, 255, 256, 257, 258,
+ 146, 248, 353, 455, 151, 253, 358, 460, 148, 250,
+ 355, 457, 149, 251, 356, 458, 152, 359, 150, 252,
+ 357, 459, 147, 249, 354, 456, 52, 2, 1, 153,
+ 360, 259, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 260, 31, 154, 361, 9, 33, 11, 155, 362, 54,
+ 261, 28, 27, 156, 363, 34, 35, 29, 46, 32,
+ 30, 55, 262, 37, 36, 39, 38, 40, 157, 364,
+ 41, 42, 43, 44, 45, 56, 158, 263, 365, 181,
+ 192, 170, 79, 57, 399, 90, 159, 297, 377, 366,
+ 275, 68, 183, 388, 286, 194, 299, 92 , 70, 182,
+ 401, 172, 59, 91, 58, 400, 368, 161, 81, 160,
+ 264, 171, 80, 389, 390, 378, 379, 193, 298, 69,
+ 266, 265, 367, 277, 288, 276, 287, 184, 60, 195,
+ 82, 93, 71, 369, 402, 173, 162, 444, 300, 391,
+ 98, 76, 278, 61, 267, 374, 135, 411, 167, 102,
+ 380, 200, 87, 178, 65, 94, 204, 124, 72, 342,
+ 189, 305, 381, 396, 433, 301, 226, 407, 289, 237,
+ 113, 215, 185, 128, 309, 403, 116, 320, 196, 331,
+ 370, 422, 174, 64, 392, 83, 425, 219, 134, 188,
+ 432, 112, 427, 139, 279, 163, 436, 208, 447, 218,
+ 236, 229, 97, 294, 385, 230, 166, 268, 177, 443,
+ 225, 426, 101, 272, 138, 127, 290, 117, 347, 199,
+ 414, 95, 140, 240, 410, 395, 209, 129, 283, 346,
+ 105, 241, 437, 86, 308, 448, 203, 345, 186, 107,
+ 220, 415, 334, 319, 106, 313, 118, 123, 73, 207,
+ 421, 214, 384, 373, 438, 62, 371, 341, 75, 449,
+ 168, 323, 164, 242, 416, 324, 304, 197, 335, 404,
+ 271, 63, 191, 325, 96, 169, 231, 280, 312, 187,
+ 406, 84, 201, 100, 67, 382, 175, 336, 202, 330,
+ 269, 393, 376, 383, 293, 307, 409, 179, 285, 314,
+ 302, 372, 398, 190, 180, 89, 99, 103, 232, 78,
+ 88, 77, 136, 387, 165, 198, 394, 125, 176, 428,
+ 74, 375, 238, 227, 66, 273, 282, 141, 306, 412,
+ 114, 85, 130, 348, 119, 291, 296, 386, 233, 397,
+ 303, 405, 284, 445, 423, 221, 210, 205, 450, 108,
+ 274, 434, 216, 343, 337, 142, 243, 321, 408, 451,
+ 310, 292, 120, 109, 281, 439, 270, 429, 332, 295,
+ 418, 211, 315, 222, 326, 131, 430, 244, 327, 349,
+ 417, 316, 143, 338, 440, 234, 110, 212, 452, 245,
+ 121, 419, 350, 223, 132, 441, 328, 413, 317, 339,
+ 126, 104, 137, 446, 344, 239, 435, 115, 333, 206,
+ 322, 217, 228, 424, 453, 311, 351, 111, 442, 224,
+ 213, 122, 431, 340, 235, 246, 133, 144, 420, 329,
+ 318
+};
+
+static Word16 sort_2385[477] = {
+ 0, 4, 6, 145, 251, 360, 466, 7, 5, 3,
+ 47, 48, 49, 50, 51, 262, 263, 264, 265, 266,
+ 146, 252, 361, 467, 151, 257, 366, 472, 148, 254,
+ 363, 469, 149, 255, 364, 470, 156, 371, 150, 256,
+ 365, 471, 147, 253, 362, 468, 52, 2, 1, 157,
+ 372, 267, 19, 21, 12, 17, 18, 20, 16, 25,
+ 13, 10, 14, 24, 23, 22, 26, 8, 15, 53,
+ 268, 31, 152, 153, 154, 155, 258, 259, 260, 261,
+ 367, 368, 369, 370, 473, 474, 475, 476, 158, 373,
+ 9, 33, 11, 159, 374, 54, 269, 28, 27, 160,
+ 375, 34, 35, 29, 46, 32, 30, 55, 270, 37,
+ 36, 39, 38, 40, 161, 376, 41, 42, 43, 44,
+ 45, 56, 162, 271, 377, 185, 196, 174, 79, 57,
+ 411, 90, 163, 305, 389, 378, 283, 68, 187, 400,
+ 294, 198, 307, 92, 70, 186, 413, 176, 59, 91,
+ 58, 412, 380, 165, 81, 164, 272, 175, 80, 401,
+ 402, 390, 391, 197, 306, 69, 274, 273, 379, 285,
+ 296, 284, 295, 188, 60, 199, 82, 93, 71, 381,
+ 414, 177, 166, 456, 308, 403, 98, 76, 286, 61,
+ 275, 386, 135, 423, 171, 102, 392, 204, 87, 182,
+ 65, 94, 208, 124, 72, 350, 193, 313, 393, 408,
+ 445, 309, 230, 419, 297, 241, 113, 219, 189, 128,
+ 317, 415, 116, 328, 200, 339, 382, 434, 178, 64,
+ 404, 83, 437, 223, 134, 192, 444, 112, 439, 139,
+ 287, 167, 448, 212, 459, 222, 240, 233, 97, 302,
+ 397, 234, 170, 276, 181, 455, 229, 438, 101, 280,
+ 138, 127, 298, 117, 355, 203, 426, 95, 140, 244,
+ 422, 407, 213, 129, 291, 354, 105, 245, 449, 86,
+ 316, 460, 207, 353, 190, 107, 224, 427, 342, 327,
+ 106, 321, 118, 123, 73, 211, 433, 218, 396, 385,
+ 450, 62, 383, 349, 75, 461, 172, 331, 168, 246,
+ 428, 332, 312, 201, 343, 416, 279, 63, 195, 333,
+ 96, 173, 235, 288, 320, 191, 418, 84, 205, 100,
+ 67, 394, 179, 344, 206, 338, 277, 405, 388, 395,
+ 301, 315, 421, 183, 293, 322, 310, 384, 410, 194,
+ 184, 89, 99, 103, 236, 78, 88, 77, 136, 399,
+ 169, 202, 406, 125, 180, 440, 74, 387, 242, 231,
+ 66, 281, 290, 141, 314, 424, 114, 85, 130, 356,
+ 119, 299, 304, 398, 237, 409, 311, 417, 292, 457,
+ 435, 225, 214, 209, 462, 108, 282, 446, 220, 351,
+ 345, 142, 247, 329, 420, 463, 318, 300, 120, 109,
+ 289, 451, 278, 441, 340, 303, 430, 215, 323, 226,
+ 334, 131, 442, 248, 335, 357, 429, 324, 143, 346,
+ 452, 238, 110, 216, 464, 249, 121, 431, 358, 227,
+ 132, 453, 336, 425, 325, 347, 126, 104, 137, 458,
+ 352, 243, 447, 115, 341, 210, 330, 221, 232, 436,
+ 465, 319, 359, 111, 454, 228, 217, 122, 443, 348,
+ 239, 250, 133, 144, 432, 337, 326
+};
+
+static Word16 sort_SID[35] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34
+};
+
+/* pointer table for bit sorting tables */
+static Word16 *sort_ptr[16] = { sort_660, sort_885, sort_1265, sort_1425, sort_1585, sort_1825, sort_1985, sort_2305,
+ sort_2385, sort_SID, NULL, NULL, NULL, NULL, NULL, NULL};
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h b/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h
new file mode 100644
index 0000000..4159d84
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/oper_32b.h
@@ -0,0 +1,31 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/* Double precision operations */
+/* $Id$ */
+
+#ifndef __OPER_32B_H__
+#define __OPER_32B_H__
+
+void VO_L_Extract (Word32 L_32, Word16 *hi, Word16 *lo);
+Word32 L_Comp (Word16 hi, Word16 lo);
+Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2);
+Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n);
+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo);
+
+#endif //__OPER_32B_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h b/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h
new file mode 100644
index 0000000..27c4c7e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/p_med_o.h
@@ -0,0 +1,52 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+/*--------------------------------------------------------------------------*
+ * P_MED_O.H *
+ *--------------------------------------------------------------------------*
+ * Median open-loop lag search *
+ *--------------------------------------------------------------------------*/
+
+#ifndef __P_MED_O_H__
+#define __P_MED_O_H__
+
+Word16 Pitch_med_ol( /* output: open loop pitch lag */
+ Word16 wsp[], /* input : signal used to compute the open loop pitch */
+ /* wsp[-pit_max] to wsp[-1] should be known */
+ Word16 L_min, /* input : minimum pitch lag */
+ Word16 L_max, /* input : maximum pitch lag */
+ Word16 L_frame, /* input : length of frame to compute pitch */
+ Word16 L_0, /* input : old_ open-loop pitch */
+ Word16 * gain, /* output: normalize correlation of hp_wsp for the Lag */
+ Word16 * hp_wsp_mem, /* i:o : memory of the hypass filter for hp_wsp[] (lg=9) */
+ Word16 * old_hp_wsp, /* i:o : hypass wsp[] */
+ Word16 wght_flg /* input : is weighting function used */
+ );
+
+Word16 Med_olag( /* output : median of 5 previous open-loop lags */
+ Word16 prev_ol_lag, /* input : previous open-loop lag */
+ Word16 old_ol_lag[5]
+ );
+
+void Hp_wsp(
+ Word16 wsp[], /* i : wsp[] signal */
+ Word16 hp_wsp[], /* o : hypass wsp[] */
+ Word16 lg, /* i : lenght of signal */
+ Word16 mem[] /* i/o : filter memory [9] */
+ );
+
+#endif //__P_MED_O_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab b/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab
new file mode 100644
index 0000000..14bd1d5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/p_med_ol.tab
@@ -0,0 +1,47 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-----------------------------------------------------*
+ | Table for function Pitch_med_ol() |
+ *-----------------------------------------------------*/
+
+ static Word16 corrweight[199]= {
+
+ 10772, 10794, 10816, 10839, 10862, 10885, 10908, 10932, 10955, 10980,
+ 11004, 11029, 11054, 11079, 11105, 11131, 11157, 11183, 11210, 11238,
+ 11265, 11293, 11322, 11350, 11379, 11409, 11439, 11469, 11500, 11531,
+ 11563, 11595, 11628, 11661, 11694, 11728, 11763, 11798, 11834, 11870,
+ 11907, 11945, 11983, 12022, 12061, 12101, 12142, 12184, 12226, 12270,
+ 12314, 12358, 12404, 12451, 12498, 12547, 12596, 12647, 12699, 12751,
+ 12805, 12861, 12917, 12975, 13034, 13095, 13157, 13221, 13286, 13353,
+ 13422, 13493, 13566, 13641, 13719, 13798, 13880, 13965, 14053, 14143,
+ 14237, 14334, 14435, 14539, 14648, 14761, 14879, 15002, 15130, 15265,
+ 15406, 15554, 15710, 15874, 16056, 16384, 16384, 16384, 16384, 16384,
+ 16384, 16384, 16056, 15874, 15710, 15554, 15406, 15265, 15130, 15002,
+ 14879, 14761, 14648, 14539, 14435, 14334, 14237, 14143, 14053, 13965,
+ 13880, 13798, 13719, 13641, 13566, 13493, 13422, 13353, 13286, 13221,
+ 13157, 13095, 13034, 12975, 12917, 12861, 12805, 12751, 12699, 12647,
+ 12596, 12547, 12498, 12451, 12404, 12358, 12314, 12270, 12226, 12184,
+ 12142, 12101, 12061, 12022, 11983, 11945, 11907, 11870, 11834, 11798,
+ 11763, 11728, 11694, 11661, 11628, 11595, 11563, 11531, 11500, 11469,
+ 11439, 11409, 11379, 11350, 11322, 11293, 11265, 11238, 11210, 11183,
+ 11157, 11131, 11105, 11079, 11054, 11029, 11004, 10980, 10955, 10932,
+ 10908, 10885, 10862, 10839, 10816, 10794, 10772, 10750, 10728};
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab b/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab
new file mode 100644
index 0000000..1a0deee
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/q_gain2.tab
@@ -0,0 +1,228 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*------------------------------------------------------*
+ * Tables for function q_gain2() *
+ * *
+ * g_pitch(Q14), g_code(Q11) *
+ * *
+ * pitch gain are ordered in table to reduce complexity *
+ * during quantization of gains. *
+ *------------------------------------------------------*/
+
+#define nb_qua_gain6b 64 /* Number of quantization level */
+#define nb_qua_gain7b 128 /* Number of quantization level */
+
+
+static Word16 t_qua_gain6b[64*2] = {
+ 1566, 1332,
+ 1577, 3557,
+ 3071, 6490,
+ 4193, 10163,
+ 4496, 2534,
+ 5019, 4488,
+ 5586, 15614,
+ 5725, 1422,
+ 6453, 580,
+ 6724, 6831,
+ 7657, 3527,
+ 8072, 2099,
+ 8232, 5319,
+ 8827, 8775,
+ 9740, 2868,
+ 9856, 1465,
+ 10087, 12488,
+ 10241, 4453,
+ 10859, 6618,
+ 11321, 3587,
+ 11417, 1800,
+ 11643, 2428,
+ 11718, 988,
+ 12312, 5093,
+ 12523, 8413,
+ 12574, 26214,
+ 12601, 3396,
+ 13172, 1623,
+ 13285, 2423,
+ 13418, 6087,
+ 13459, 12810,
+ 13656, 3607,
+ 14111, 4521,
+ 14144, 1229,
+ 14425, 1871,
+ 14431, 7234,
+ 14445, 2834,
+ 14628, 10036,
+ 14860, 17496,
+ 15161, 3629,
+ 15209, 5819,
+ 15299, 2256,
+ 15518, 4722,
+ 15663, 1060,
+ 15759, 7972,
+ 15939, 11964,
+ 16020, 2996,
+ 16086, 1707,
+ 16521, 4254,
+ 16576, 6224,
+ 16894, 2380,
+ 16906, 681,
+ 17213, 8406,
+ 17610, 3418,
+ 17895, 5269,
+ 18168, 11748,
+ 18230, 1575,
+ 18607, 32767,
+ 18728, 21684,
+ 19137, 2543,
+ 19422, 6577,
+ 19446, 4097,
+ 19450, 9056,
+ 20371, 14885};
+
+static Word16 t_qua_gain7b[128*2] = {
+ 204, 441,
+ 464, 1977,
+ 869, 1077,
+ 1072, 3062,
+ 1281, 4759,
+ 1647, 1539,
+ 1845, 7020,
+ 1853, 634,
+ 1995, 2336,
+ 2351, 15400,
+ 2661, 1165,
+ 2702, 3900,
+ 2710, 10133,
+ 3195, 1752,
+ 3498, 2624,
+ 3663, 849,
+ 3984, 5697,
+ 4214, 3399,
+ 4415, 1304,
+ 4695, 2056,
+ 5376, 4558,
+ 5386, 676,
+ 5518, 23554,
+ 5567, 7794,
+ 5644, 3061,
+ 5672, 1513,
+ 5957, 2338,
+ 6533, 1060,
+ 6804, 5998,
+ 6820, 1767,
+ 6937, 3837,
+ 7277, 414,
+ 7305, 2665,
+ 7466, 11304,
+ 7942, 794,
+ 8007, 1982,
+ 8007, 1366,
+ 8326, 3105,
+ 8336, 4810,
+ 8708, 7954,
+ 8989, 2279,
+ 9031, 1055,
+ 9247, 3568,
+ 9283, 1631,
+ 9654, 6311,
+ 9811, 2605,
+ 10120, 683,
+ 10143, 4179,
+ 10245, 1946,
+ 10335, 1218,
+ 10468, 9960,
+ 10651, 3000,
+ 10951, 1530,
+ 10969, 5290,
+ 11203, 2305,
+ 11325, 3562,
+ 11771, 6754,
+ 11839, 1849,
+ 11941, 4495,
+ 11954, 1298,
+ 11975, 15223,
+ 11977, 883,
+ 11986, 2842,
+ 12438, 2141,
+ 12593, 3665,
+ 12636, 8367,
+ 12658, 1594,
+ 12886, 2628,
+ 12984, 4942,
+ 13146, 1115,
+ 13224, 524,
+ 13341, 3163,
+ 13399, 1923,
+ 13549, 5961,
+ 13606, 1401,
+ 13655, 2399,
+ 13782, 3909,
+ 13868, 10923,
+ 14226, 1723,
+ 14232, 2939,
+ 14278, 7528,
+ 14439, 4598,
+ 14451, 984,
+ 14458, 2265,
+ 14792, 1403,
+ 14818, 3445,
+ 14899, 5709,
+ 15017, 15362,
+ 15048, 1946,
+ 15069, 2655,
+ 15405, 9591,
+ 15405, 4079,
+ 15570, 7183,
+ 15687, 2286,
+ 15691, 1624,
+ 15699, 3068,
+ 15772, 5149,
+ 15868, 1205,
+ 15970, 696,
+ 16249, 3584,
+ 16338, 1917,
+ 16424, 2560,
+ 16483, 4438,
+ 16529, 6410,
+ 16620, 11966,
+ 16839, 8780,
+ 17030, 3050,
+ 17033, 18325,
+ 17092, 1568,
+ 17123, 5197,
+ 17351, 2113,
+ 17374, 980,
+ 17566, 26214,
+ 17609, 3912,
+ 17639, 32767,
+ 18151, 7871,
+ 18197, 2516,
+ 18202, 5649,
+ 18679, 3283,
+ 18930, 1370,
+ 19271, 13757,
+ 19317, 4120,
+ 19460, 1973,
+ 19654, 10018,
+ 19764, 6792,
+ 19912, 5135,
+ 20040, 2841,
+ 21234, 19833};
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h b/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h
new file mode 100644
index 0000000..baf5525
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/q_pulse.h
@@ -0,0 +1,66 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*--------------------------------------------------------------------------*
+ * Q_PULSE.H *
+ *--------------------------------------------------------------------------*
+ * Coding and decoding of algebraic codebook *
+ *--------------------------------------------------------------------------*/
+
+#ifndef __Q_PULSE_H__
+#define __Q_PULSE_H__
+
+#include "typedef.h"
+
+Word32 quant_1p_N1( /* (o) return (N+1) bits */
+ Word16 pos, /* (i) position of the pulse */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_2p_2N1( /* (o) return (2*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_3p_3N1( /* (o) return (3*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_4p_4N1( /* (o) return (4*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 pos4, /* (i) position of the pulse 4 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_4p_4N( /* (o) return 4*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..4 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_5p_5N( /* (o) return 5*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..5 */
+ Word16 N); /* (i) number of bits for position */
+
+Word32 quant_6p_6N_2( /* (o) return (6*N)-2 bits */
+ Word16 pos[], /* (i) position of the pulse 1..6 */
+ Word16 N); /* (i) number of bits for position */
+
+
+#endif //__Q_PULSE_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab b/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab
new file mode 100644
index 0000000..52f0daf
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/qisf_ns.tab
@@ -0,0 +1,347 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-------------------------------------------------------------------*
+ * qisf_ns.h
+ *-------------------------------------------------------------------*
+ * Quantization tables for split by 5 VQ of ISFs for a background noise database
+ * Version whith no prediction
+ *-------------------------------------------------------------------*/
+
+#define ORDER 16 /* order of linear prediction filter */
+#define ISF_GAP 128
+
+#define SIZE_BK_NOISE1 64
+#define SIZE_BK_NOISE2 64
+#define SIZE_BK_NOISE3 64
+#define SIZE_BK_NOISE4 32
+#define SIZE_BK_NOISE5 32
+
+
+/* means of ISFs */
+ static Word16 mean_isf_noise[ORDER] = {
+
+ 478, 1100, 2213, 3267, 4219, 5222, 6198, 7240,
+ 8229, 9153, 10098, 11108, 12144, 13184, 14165, 3803};
+
+
+/* 28 bits */
+/*-------------------------------------------------------------------*
+ * isf codebooks: split-by-5 VQ *
+ * *
+ * codebook vector dimension number of vectors *
+ * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ *
+ * 1 2 64 *
+ * 2 3 64 *
+ * 3 3 64 *
+ * 4 4 32 *
+ * 5 4 32 *
+ *-------------------------------------------------------------------*/
+
+/*------------------------------------------------*
+ * 1st split: isf0 to isf1
+ *------------------------------------------------*/
+
+
+ static Word16 dico1_isf_noise[SIZE_BK_NOISE1*2] = {
+
+ -269, -673,
+ -222, -537,
+ -233, -430,
+ -138, -451,
+ -212, -331,
+ -192, -241,
+ -87, -231,
+ -191, -128,
+ -70, -106,
+ -164, -6,
+ 74, -179,
+ 27, -33,
+ -102, 74,
+ -162, 115,
+ -94, 172,
+ -6, 130,
+ -143, 234,
+ 14, 218,
+ -65, 270,
+ 88, 182,
+ -124, 341,
+ -44, 381,
+ 38, 335,
+ 117, 274,
+ -112, 454,
+ 74, 431,
+ -5, 488,
+ 175, 384,
+ -83, 561,
+ 122, 529,
+ 21, 601,
+ 229, 481,
+ 231, 303,
+ 226, 608,
+ 300, 372,
+ 210, 187,
+ 306, 265,
+ 328, 473,
+ 382, 331,
+ 371, 132,
+ 139, 58,
+ 365, 21,
+ 250, -82,
+ 443, 218,
+ 483, 110,
+ 426, 415,
+ 579, 222,
+ 518, 333,
+ 573, 448,
+ 455, 529,
+ 685, 329,
+ 332, 580,
+ 595, 593,
+ 468, 645,
+ 762, 517,
+ 326, 709,
+ 485, 793,
+ 130, 684,
+ 671, 737,
+ 354, 876,
+ 88, 806,
+ -65, 706,
+ -35, 1016,
+ 266, 1123};
+
+
+/*------------------------------------------------*
+ * 2nd split: isf2 to isf4
+ *------------------------------------------------*/
+
+ static Word16 dico2_isf_noise[SIZE_BK_NOISE2*3] = {
+
+ -824, -884, -949,
+ -805, -456, -418,
+ -442, -438, -541,
+ -217, -578, -793,
+ -168, -444, -582,
+ -287, -492, -274,
+ -552, -297, -300,
+ -163, -333, -358,
+ -370, -232, -232,
+ -175, -358, -159,
+ -381, -21, -357,
+ -184, -159, -162,
+ -53, -191, -280,
+ 18, -267, -215,
+ -138, 61, -283,
+ 71, -95, -294,
+ 13, -156, -546,
+ 0, -83, -79,
+ 44, 97, -316,
+ 178, -52, -213,
+ 222, -261, -422,
+ 237, -118, -44,
+ 141, 145, -132,
+ 363, 81, -287,
+ 213, 65, 34,
+ -107, 94, -5,
+ 91, -29, 126,
+ -355, 51, -41,
+ -219, -76, 145,
+ -63, 100, 244,
+ -719, 44, 27,
+ -572, -124, 155,
+ -423, 133, 315,
+ -917, 71, 224,
+ -268, 318, 131,
+ -93, -190, 420,
+ -97, 122, 491,
+ -79, 317, 355,
+ 130, 100, 325,
+ 86, -293, 210,
+ 133, 258, 161,
+ 176, -73, 465,
+ 195, 300, 384,
+ 348, 22, 221,
+ 376, 183, 409,
+ 377, 286, 202,
+ 242, 213, 659,
+ 257, 565, 248,
+ 344, 408, -76,
+ 405, 440, 509,
+ 612, 385, 379,
+ 536, 607, 216,
+ -56, 582, 192,
+ 100, 517, 567,
+ -365, 448, 445,
+ 728, 347, 10,
+ 505, 357, 759,
+ 636, 582, 658,
+ 335, 517, 852,
+ 378, 809, 572,
+ -195, 878, 829,
+ 529, 707, 987,
+ 918, 726, 392,
+ 1250, 997, 1063};
+
+/*------------------------------------------------*
+ * 3rd split: isf5 to isf7
+ *------------------------------------------------*/
+
+ static Word16 dico3_isf_noise[SIZE_BK_NOISE3*3] = {
+
+ -805, -838, -774,
+ -522, -627, -828,
+ -477, -486, -603,
+ -295, -481, -634,
+ -366, -384, -393,
+ -186, -414, -396,
+ -237, -394, -106,
+ -252, -202, -275,
+ -61, -177, -442,
+ -84, -198, -199,
+ -179, -125, -31,
+ -72, -47, -163,
+ -298, -220, 215,
+ -64, -168, 251,
+ -133, 156, -59,
+ -30, -2, 127,
+ 54, 66, -61,
+ -233, 21, 251,
+ 209, -50, 32,
+ 33, 194, 136,
+ -117, -18, 475,
+ 202, 46, 309,
+ 256, 185, 53,
+ 35, 200, 390,
+ 200, 263, 242,
+ -216, 302, 294,
+ 128, 358, 0,
+ 19, 431, 287,
+ 224, 447, 280,
+ 367, 165, 213,
+ 397, 314, 319,
+ 383, 379, 75,
+ 277, 325, 462,
+ 394, 505, 334,
+ 251, 98, -213,
+ 450, 153, 448,
+ 565, 226, 76,
+ 470, 383, 502,
+ 635, 390, 278,
+ 237, 135, 620,
+ 342, 401, 649,
+ 331, 551, 518,
+ 130, 418, 592,
+ 531, 306, 737,
+ 729, 389, 580,
+ 497, 557, 699,
+ 296, 383, 874,
+ 283, 624, 759,
+ 126, 622, 476,
+ 559, 595, 472,
+ 382, 770, 616,
+ 719, 613, 745,
+ 540, 639, 928,
+ 517, 826, 801,
+ 684, 811, 604,
+ 752, 786, 857,
+ 933, 661, 350,
+ 694, 450, 1061,
+ 562, 911, 1051,
+ 824, 813, 1104,
+ 758, 1047, 882,
+ 1140, 917, 889,
+ 1039, 1246, 1426,
+ 1483, 1666, 1876};
+
+/*------------------------------------------------*
+ * 4th split: isf8 to isf11
+ *------------------------------------------------*/
+
+ static Word16 dico4_isf_noise[SIZE_BK_NOISE4*4] = {
+
+ -776, -854, -891, -920,
+ -552, -610, -663, -741,
+ -321, -370, -476, -565,
+ 274, -160, -456, 201,
+ 265, 67, -160, -306,
+ -8, -210, 79, 272,
+ 163, 236, 307, 308,
+ 578, 317, 64, 298,
+ -9, 197, 342, 620,
+ 343, 232, 314, 622,
+ 173, 149, 548, 527,
+ 356, 370, 481, 376,
+ 135, 444, 488, 556,
+ 391, 471, 487, 653,
+ 228, 424, 576, 835,
+ 422, 372, 722, 682,
+ 295, 673, 693, 635,
+ 539, 596, 590, 449,
+ 475, 618, 659, 818,
+ 735, 517, 491, 673,
+ 602, 346, 257, 877,
+ 625, 635, 849, 720,
+ 727, 818, 698, 595,
+ 653, 481, 690, 1139,
+ 814, 762, 704, 908,
+ 507, 747, 898, 936,
+ 848, 855, 924, 785,
+ 646, 1037, 882, 795,
+ 772, 845, 1024, 1151,
+ 1133, 983, 818, 921,
+ 940, 1068, 1252, 1302,
+ 1588, 1767, 1718, 1513};
+
+/*------------------------------------------------*
+ * 5th split: isf12 to isf15
+ *------------------------------------------------*/
+
+ static Word16 dico5_isf_noise[SIZE_BK_NOISE5*4] = {
+ -810, -879, -945, -254,
+ 248, 184, 671, 128,
+ 288, 703, 918, 99,
+ 658, 558, 662, 219,
+ 552, 585, 910, 208,
+ 559, 804, 759, 119,
+ 606, 774, 921, -139,
+ 782, 761, 748, 208,
+ 756, 708, 983, 56,
+ 544, 864, 1010, 152,
+ 737, 698, 987, 299,
+ 771, 924, 879, 103,
+ 536, 785, 961, 405,
+ 667, 916, 801, 328,
+ 738, 705, 773, 439,
+ 823, 871, 992, 355,
+ 640, 1004, 1052, 369,
+ 724, 822, 949, 597,
+ 415, 655, 729, 482,
+ 1009, 896, 793, 363,
+ 908, 803, 687, -25,
+ 1016, 838, 1011, 189,
+ 947, 1112, 942, 222,
+ 914, 1049, 981, 527,
+ 956, 987, 1011, -120,
+ 781, 1049, 1121, 92,
+ 1178, 1053, 884, 47,
+ 1123, 1059, 1182, 118,
+ 933, 972, 1277, 357,
+ 1109, 918, 1101, 503,
+ 1039, 1286, 1220, 317,
+ 1351, 1207, 1010, 326};
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab b/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab
new file mode 100644
index 0000000..4d869a4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/qpisf_2s.tab
@@ -0,0 +1,1360 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-------------------------------------------------------------------*
+ * qpisf_2s.h
+ *-------------------------------------------------------------------*
+ * Quantization tables for two-stage of ISFs (split by 2 in 1st stage)
+ * Version whith prediction MU = 0.25
+ *-------------------------------------------------------------------*/
+
+#define ORDER 16 /* order of linear prediction filter */
+#define ISF_GAP 128 /* 50 Hz */
+#define N_SURV 4
+
+#define SIZE_BK1 256
+#define SIZE_BK2 256
+#define SIZE_BK21 64
+#define SIZE_BK22 128
+#define SIZE_BK23 128
+#define SIZE_BK24 32
+#define SIZE_BK25 32
+
+#define SIZE_BK21_36b 128
+#define SIZE_BK22_36b 128
+#define SIZE_BK23_36b 64
+
+/* means of ISFs */
+static Word16 mean_isf[ORDER] = {
+
+ 738, 1326, 2336, 3578, 4596, 5662, 6711, 7730,
+ 8750, 9753, 10705, 11728, 12833, 13971, 15043, 4037};
+
+/* 46 bits */
+/*-------------------------------------------------------------------*
+ * isf codebooks: two-stage VQ with split-by-5 in 2nd stage *
+ * *
+ * codebook vector dimension number of vectors *
+ * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ *
+ * 1_1 9 256 *
+ * 1_2 7 256 *
+ * 2_1 3 64 *
+ * 2_2 3 128 *
+ * 2_3 3 128 *
+ * 2_4 3 32 *
+ * 2_5 4 32 *
+ *-------------------------------------------------------------------*/
+
+/*------------------------------------------------*
+ * 1st stage codebook; 1st split: isf0 to isf8
+ *------------------------------------------------*/
+
+static Word16 dico1_isf[SIZE_BK1*9] = {
+
+ 579, 1081, 1035, 390, 3, -263, -198, -82, 38,
+ 18, -68, -12, 313, 761, 405, 249, 111, -76,
+ 740, 1263, 1292, 1006, 997, 1019, 1017, 976, 923,
+ -91, 827, 948, 648, 613, 535, 522, 490, 421,
+ 41, -44, -281, -472, 652, 534, 193, 135, -90,
+ 41, -121, -356, -60, 663, 307, 61, -48, -344,
+ 557, 946, 1049, 867, 846, 990, 1112, 1262, 1241,
+ -118, -204, 328, 512, 870, 793, 610, 402, 186,
+ 156, 293, 74, -338, -475, -897, -594, -161, -497,
+ 226, 131, -138, 307, 169, -271, -164, -387, -624,
+ 62, -32, -61, -252, -541, -828, -1027, -523, -662,
+ 102, -61, 141, 112, -270, -251, -541, 25, -150,
+ 6, -132, -356, -686, -96, -322, -522, -31, -326,
+ -36, -209, -521, -229, 307, -132, -5, -99, -384,
+ 60, -51, -237, -668, -973, -407, -708, -75, -172,
+ 26, -138, -266, 111, -302, 43, -278, -356, -359,
+ 570, 822, 496, -154, -312, -92, 137, 279, 371,
+ -146, 368, 409, 68, 6, 77, 167, 202, 162,
+ 633, 898, 996, 756, 662, 683, 783, 909, 996,
+ -103, 294, 607, 415, 483, 462, 480, 431, 408,
+ -120, -338, -612, -524, 584, 331, 92, 433, 276,
+ -178, -293, -154, -41, 269, 100, -9, 213, 160,
+ 830, 736, 278, 820, 1254, 686, 712, 1039, 473,
+ -218, -304, 463, 454, 397, 273, 202, 286, 273,
+ -232, 7, 6, -388, -472, -427, -378, -167, -100,
+ -294, -183, 134, -47, 101, -88, -84, -117, -3,
+ 57, 17, -202, -634, -989, -1119, -533, 176, -36,
+ 120, -28, 23, 111, -319, 318, -22, -77, 266,
+ -271, -464, -434, -658, -640, -385, -385, -99, -69,
+ -198, -259, -266, -44, -39, -139, -137, 171, 66,
+ 9, -145, -377, -846, -1000, -111, -325, 342, 135,
+ -81, -286, -380, 192, -57, 307, 76, -24, -140,
+ 677, 702, 247, 56, 249, 141, -105, -236, -99,
+ 36, -39, -69, 348, 198, -93, 322, 91, -72,
+ 503, 885, 1508, 1307, 1282, 1172, 1119, 1209, 1061,
+ 416, 719, 989, 1227, 1001, 1052, 954, 741, 1044,
+ -127, -376, -657, 139, 623, 223, 501, 306, 220,
+ -113, -384, -796, 504, 438, 85, 213, -83, -194,
+ 585, 1132, 1233, 1091, 1247, 1433, 1512, 1448, 1314,
+ -174, -422, 7, 1155, 1089, 1182, 1003, 945, 806,
+ 8, -126, -317, -103, -351, -695, -98, -268, -537,
+ 33, -103, -290, 167, -39, -407, 44, -208, -375,
+ 104, -23, -64, -291, -637, -851, -1084, -61, -112,
+ -75, -306, -434, 218, -148, -354, -680, -133, -216,
+ -121, -377, -718, -97, -130, -361, -156, -379, -599,
+ -56, -254, -586, 235, 157, -214, 11, -260, -149,
+ -124, -267, -397, -580, -593, -527, -805, -385, 346,
+ -193, -440, -708, -351, -141, -255, -499, -147, -185,
+ 448, 660, 494, 208, 509, 461, 338, 291, 149,
+ -223, 88, 335, 159, 212, 191, 286, 308, 205,
+ -31, 469, 803, 659, 619, 658, 843, 987, 1113,
+ -171, -242, 514, 362, 295, 524, 552, 694, 585,
+ -64, -308, -448, -21, 284, 786, 446, 289, 92,
+ -218, -390, -7, 169, 206, 330, 352, 408, 358,
+ -36, 702, 959, 859, 861, 1115, 1269, 1357, 1305,
+ -133, -341, -65, 678, 417, 440, 486, 518, 780,
+ 33, -44, -191, -344, -461, -755, -201, 217, -31,
+ -353, -547, -44, 123, -61, -68, -79, 29, 60,
+ 73, -57, -406, -766, -1243, -1203, 240, 400, 165,
+ -73, -282, -601, -213, -171, -375, 332, 35, -103,
+ -29, -207, -553, -476, -638, -908, 172, -22, -135,
+ -192, -239, -164, -103, -111, -47, 153, 125, 110,
+ -1, -203, -570, -1030, -1424, -535, 155, 1, 147,
+ -333, -653, -865, -197, -158, -21, -44, 95, 108,
+ 389, 588, 490, 33, -237, -524, -628, -136, -260,
+ 40, -177, -462, 453, 862, 380, 131, -130, -405,
+ 842, 1678, 1841, 1549, 1474, 1256, 1082, 905, 742,
+ 370, 1216, 1768, 1633, 1212, 636, 22, -330, 71,
+ -76, -281, -741, -742, 898, 619, 277, 71, -222,
+ -32, -265, -556, -25, 994, 682, 305, 126, -165,
+ 73, 738, 893, 968, 993, 1768, 2273, 1840, 1391,
+ -69, -349, -585, 234, 1158, 903, 626, 510, 251,
+ -1, -99, -272, -210, -603, -351, -540, -811, -383,
+ -16, -230, -504, 410, 149, -205, -343, -651, -639,
+ 103, -9, -227, -205, -562, -781, -1079, -1208, -156,
+ 143, 63, -135, -67, -317, -602, -784, -1154, -640,
+ -144, -391, -674, -622, -200, -254, -660, -947, -395,
+ -40, -250, -625, 27, 543, 94, -131, -386, -673,
+ -123, -371, -757, -451, -564, -614, -415, -711, -35,
+ -116, -309, -593, -268, 239, -33, -338, -650, -135,
+ 94, 251, 554, 57, -312, -423, -154, -57, 235,
+ -268, -71, 381, 114, -44, -87, 125, 173, 133,
+ 1513, 1714, 1238, 534, 276, 315, 461, 459, 508,
+ -131, -19, 1149, 670, 486, 356, 309, 369, 296,
+ -223, -501, -899, -722, -70, 6, 131, 310, 394,
+ -99, -303, -517, 249, 64, -53, 135, -11, 453,
+ -147, -399, -730, -401, 817, 738, 802, 749, 575,
+ -154, -435, -739, 800, 593, 366, 529, 318, 326,
+ -224, 45, -39, -387, -515, -518, -608, -384, -321,
+ -315, -377, 143, -101, -113, -377, -177, -144, -12,
+ 117, 40, -239, -651, -1051, -581, -737, -990, -328,
+ 26, -50, -157, -23, -453, -283, -531, -546, 192,
+ -252, -501, -743, -589, -627, -499, -328, -118, -72,
+ -324, -494, -244, -306, -144, -177, -262, -135, -78,
+ -36, -234, -519, -961, -1290, -314, -479, -371, -45,
+ -95, -292, -535, -8, -300, 112, -164, -277, 198,
+ -99, -128, 880, 836, 579, 351, 23, -95, -217,
+ -27, -258, 124, 1011, 597, 425, 144, 7, -73,
+ 421, 1293, 1640, 1623, 1742, 1617, 1499, 1284, 1006,
+ -95, 752, 1680, 1569, 1618, 1436, 1200, 980, 712,
+ -69, -300, -683, -435, 1132, 899, 504, 332, 109,
+ -74, -323, -637, 563, 1074, 608, 371, 105, -49,
+ -78, 831, 1194, 1110, 1378, 1481, 1492, 1365, 1217,
+ -259, -121, 1440, 1334, 1628, 1490, 1438, 1223, 933,
+ -82, -306, -613, -222, -378, -675, -545, -671, -845,
+ 53, -124, -347, 422, 52, -125, -270, -529, 9,
+ 79, -89, -320, -662, -999, -1199, -1243, -676, -297,
+ -68, -273, -611, 137, -146, -397, -627, -845, -220,
+ -112, -346, -797, -826, 234, -132, -188, -278, -522,
+ -159, -405, -734, -419, 293, 74, -167, -167, 184,
+ -153, -437, -833, -1080, -336, -472, -561, -340, -253,
+ -169, -423, -820, -904, -131, -19, -346, -604, 31,
+ 33, -31, 312, 62, -148, 49, -59, 564, 486,
+ -306, -333, 194, -44, 67, 72, 147, 205, 243,
+ -207, -49, 1360, 983, 969, 991, 1014, 1110, 973,
+ -211, -172, 883, 627, 711, 674, 705, 798, 746,
+ -88, -325, -763, -974, 687, 908, 514, 382, 172,
+ -292, -612, -805, 63, 131, 270, 259, 352, 348,
+ -235, -84, 955, 818, 1120, 1289, 1559, 1480, 1285,
+ -180, -461, -614, 657, 691, 745, 854, 783, 713,
+ -97, -309, -477, -614, -777, -734, -768, -526, -472,
+ -344, -476, -35, -169, 49, -77, -150, -240, -141,
+ -52, -268, -639, -919, -1278, -1113, -342, -333, -151,
+ -68, -242, -585, -73, -209, -478, -159, -429, 133,
+ -197, -499, -1005, -1268, -272, -224, -105, -67, 17,
+ -363, -618, -414, -116, -62, 20, 10, 116, 108,
+ -195, -475, -906, -1260, -891, -441, -277, -142, -28,
+ -226, -519, -950, -700, -275, -266, -116, -105, 82,
+ 404, 511, 520, 327, 17, -194, -333, -536, -586,
+ -114, -130, 276, 237, 204, 342, 135, -16, -111,
+ 670, 1208, 1168, 860, 742, 601, 528, 403, 309,
+ 397, 621, 966, 752, 579, 398, 400, 329, 252,
+ 191, 180, -137, -467, 272, 106, -95, 17, -192,
+ -80, -290, -626, 194, 598, 196, 21, -281, 77,
+ 510, 864, 1108, 807, 939, 902, 925, 717, 481,
+ 137, 367, 534, 764, 670, 382, 296, 153, 84,
+ 303, 497, 144, -85, -125, -539, -482, -464, -764,
+ 233, 347, 68, -147, 169, -210, -242, -226, -482,
+ 307, 422, 154, -175, -386, -722, -724, -904, -1015,
+ 309, 308, 160, -60, -470, -420, -598, -791, -219,
+ 68, 121, -137, -560, -146, -446, -515, -494, -729,
+ 130, 53, -227, 46, 474, 32, -161, -192, -490,
+ 213, 164, -71, -465, -876, -161, -456, -587, -48,
+ 218, 117, 39, 177, -194, -88, -226, -418, 50,
+ 210, 547, 569, 279, 121, -44, -50, 10, -84,
+ 58, 140, 182, -5, 267, 117, 106, 211, 198,
+ 539, 835, 913, 719, 617, 544, 591, 565, 642,
+ 153, 559, 872, 460, 222, 108, 188, 180, 183,
+ 158, 119, 284, -153, -271, 229, 87, 110, -57,
+ -183, 82, 118, 21, 13, 40, 118, 191, 185,
+ 162, 889, 654, 108, -34, 244, 488, 561, 532,
+ 163, 56, 609, 341, 50, 329, 68, 266, 218,
+ 100, 206, 18, -304, -107, -436, -487, -65, -306,
+ -86, 154, 134, -30, -45, -73, -104, -80, -96,
+ 245, 330, 10, -440, -849, -1082, 79, 40, -265,
+ 196, 372, 272, -181, -493, -389, 275, 80, -59,
+ 2, -12, -246, -505, -100, -436, 21, -187, -431,
+ -221, -48, 36, -271, -186, -147, -109, 26, 71,
+ 213, 140, 72, -351, -620, -84, -363, 69, 46,
+ 91, 167, -3, -95, -99, -105, -48, 114, 147,
+ 259, 249, 172, 607, 406, 52, 59, -189, -320,
+ 115, -85, -54, 574, 128, 226, -59, -253, 130,
+ -62, 1033, 1308, 1035, 1127, 1098, 1029, 961, 823,
+ 39, 364, 757, 940, 728, 660, 659, 583, 770,
+ -115, -338, -760, -471, 394, 37, 441, 178, 6,
+ -57, -305, -525, 796, 453, 188, -4, -114, 248,
+ 71, 444, 797, 731, 1096, 1157, 1222, 1029, 811,
+ 135, 359, 551, 425, 749, 815, 874, 704, 502,
+ 132, 247, 0, -206, -449, -750, -258, -514, -633,
+ 248, 249, 91, 121, -195, -499, -90, -282, -435,
+ 78, 20, -277, -623, -983, -1224, -415, -458, -639,
+ 347, 509, 208, -179, -464, -728, -76, -237, -486,
+ -103, -343, -756, -713, -265, -609, -191, -398, -636,
+ -121, -383, -749, 567, 252, -36, -354, -417, -50,
+ 204, 100, -149, -650, -1081, -47, -7, -263, 111,
+ -46, -180, -267, -324, -562, -394, -692, 398, 292,
+ 482, 670, 683, 624, 442, 165, 116, 36, -149,
+ 108, 247, 291, 247, 355, 122, 109, 224, 296,
+ -14, 945, 990, 801, 755, 815, 847, 913, 892,
+ 292, 349, 725, 482, 388, 329, 429, 620, 667,
+ -34, 197, 213, -127, 84, 494, 620, 575, 375,
+ 126, 207, 172, 167, 362, 202, 296, 395, 455,
+ -6, 250, 539, 467, 636, 801, 1149, 1287, 1118,
+ 27, 240, 369, 280, 440, 411, 634, 892, 953,
+ 159, 170, -58, -395, -797, -690, 77, -211, -334,
+ -5, -28, -13, -74, -335, -603, 300, 88, -205,
+ 82, -33, -364, -698, -1203, -1153, 110, -146, -289,
+ 113, 1, -243, -588, -994, -496, 414, 160, 42,
+ -56, -247, -440, -693, -996, -479, 11, -178, -357,
+ -151, -353, -327, -211, -340, 141, 65, 425, 453,
+ 34, -169, -455, -932, -1215, 138, 499, 256, 324,
+ 68, 139, -15, -547, -478, 17, 306, 502, 481,
+ -32, -134, 445, 129, -143, -244, -503, -507, -599,
+ 61, -140, -345, 496, 458, -2, 20, -227, -514,
+ 394, 1765, 1666, 1339, 1117, 806, 642, 479, 380,
+ 215, 519, 920, 1053, 1090, 791, 528, 290, 155,
+ -54, -233, -647, -602, 639, 294, -2, -167, -442,
+ -78, -315, -791, -113, 820, 403, 158, -116, -356,
+ 529, 1851, 2003, 1228, 622, -41, -416, 344, 819,
+ -105, -379, -236, 1224, 893, 749, 568, 356, 214,
+ -17, -199, -144, 50, -283, -247, -578, -846, -1087,
+ 69, -11, -381, -206, 209, -284, -387, -416, -716,
+ 39, -5, -145, -374, -682, -909, -1074, -1169, -1066,
+ 287, 226, 67, -221, -662, -171, -421, -642, -707,
+ -132, -348, -538, -448, -20, -4, -354, -748, -933,
+ 4, -75, -289, -598, 317, 52, -208, -297, -559,
+ -88, -264, -358, -589, -631, -248, -523, -822, -1071,
+ 70, -8, 54, -314, -515, 92, -146, -274, -493,
+ 199, 62, 391, 158, -141, 71, -219, -203, -207,
+ 152, 40, 329, 162, -29, 48, -149, 108, 127,
+ 635, 1058, 883, 492, 372, 312, 317, 274, 241,
+ 267, 722, 1256, 882, 625, 248, 8, -81, -60,
+ -58, -138, -291, -600, -12, -2, -39, 147, 117,
+ -107, -345, -513, 459, 76, 92, -272, 388, 262,
+ 362, 516, 203, -409, -716, -831, -331, 185, 209,
+ -117, -391, -298, 671, 292, 538, 257, 166, -38,
+ -102, -319, -194, -283, -573, -262, -579, -219, -444,
+ -235, 78, 11, -168, -101, -229, -263, -321, -123,
+ 70, 50, -170, -599, -996, -588, -263, -516, -455,
+ 394, 363, 229, -136, -538, 21, -183, -348, -201,
+ -124, -368, -640, -879, -847, -209, -409, -494, -515,
+ -127, -341, -541, -425, -510, -10, -252, -473, -291,
+ 84, -69, -201, -676, -868, 103, -311, -132, -320,
+ 5, -173, -188, -297, -628, 197, -57, 7, -11,
+ 49, -160, 56, 558, 111, 33, -311, -440, -463,
+ -1, -246, -307, 862, 453, 139, -170, -355, -232,
+ 279, 966, 1642, 1478, 1463, 1123, 795, 525, 339,
+ -197, -38, 1702, 1331, 1252, 950, 692, 504, 426,
+ -108, -344, -861, -1172, 444, 354, 88, -46, -220,
+ -53, -321, -494, 1113, 744, 364, 198, -34, -75,
+ 457, 955, 1177, 1214, 1427, 1457, 1345, 917, 539,
+ -69, 199, 897, 1140, 1343, 1183, 977, 742, 522,
+ 122, 44, -269, 27, -155, -562, -307, -590, -773,
+ 154, 42, -160, 252, -129, -305, -471, -733, -371,
+ 135, 185, -82, -416, -722, -913, -504, -743, -880,
+ 149, 214, -84, -329, -680, -835, -426, -661, -81,
+ -128, -380, -735, -998, -337, 17, -182, -467, -697,
+ -84, -290, -510, -592, 13, 440, 154, -38, -279,
+ 70, -61, -246, -727, -1047, -80, -381, -535, -704,
+ 178, -2, -146, -670, -938, 482, 138, 63, 65,
+ -11, 15, 772, 443, 142, -20, -209, -126, -161,
+ -32, -249, 95, 552, 124, 30, -343, 82, -86,
+ 148, 751, 1515, 1105, 867, 606, 474, 448, 399,
+ -163, -257, 899, 1097, 906, 751, 502, 390, 294,
+ -51, -258, -447, -806, -368, 763, 464, 364, 183,
+ -166, -374, -367, 87, 35, 399, 418, 856, 833,
+ -205, -310, 588, 778, 785, 1065, 1118, 1245, 1157,
+ -173, -312, 107, 345, 400, 790, 870, 1113, 1001,
+ -7, -120, -387, -410, -614, -943, -226, -384, -491,
+ -203, -288, -51, -331, -90, -178, -408, -573, -338,
+ 56, -29, -273, -627, -1041, -798, -247, -467, 148,
+ 66, -2, -205, -205, -575, -349, -57, -352, -58,
+ -45, -225, -471, -924, -497, 77, -32, 44, -135,
+ -277, -491, -497, -502, -424, -202, -137, 77, 96,
+ 26, -179, -469, -1008, -1260, 262, -35, -132, -259,
+ -66, -232, -447, -533, -789, -191, -100, -267, 364};
+
+/*------------------------------------------------*
+ * 1st stage codebook; 2nd split: isf9 to isf15
+ *------------------------------------------------*/
+
+static Word16 dico2_isf[SIZE_BK2*7] = {
+
+ 1357, 1313, 1136, 784, 438, 181, 145,
+ 636, 648, 667, 568, 442, 217, 362,
+ 427, 440, 674, 524, 332, 117, -417,
+ 121, 295, 468, 465, 230, 44, -221,
+ -147, -240, 149, 80, 390, 278, 106,
+ -418, -556, 552, 511, 235, 144, -95,
+ 43, 193, 274, 150, 67, 34, -273,
+ -43, -126, 171, 416, 282, 63, -354,
+ -372, -86, -344, -108, -94, -182, -89,
+ -600, -840, -200, 465, 258, -11, -253,
+ -48, 329, 97, -290, -543, -795, -354,
+ -570, -117, 187, 10, -133, -416, -76,
+ -618, -129, -247, -371, 45, -76, 277,
+ -1022, -1079, 126, 474, 254, 127, 52,
+ -281, 76, -167, -361, -283, -551, -283,
+ -119, -52, -1, 134, -32, -204, -415,
+ 1064, 827, 637, 684, 464, 209, 12,
+ 482, 416, 449, 371, 335, 294, 194,
+ 719, 576, 365, 135, 113, 91, -199,
+ 298, 176, 493, 366, 194, 163, 36,
+ -35, -236, -259, -36, -4, 99, 152,
+ -98, -306, -27, 228, 90, 111, -86,
+ 91, 13, -211, -258, -106, 86, -64,
+ 73, -35, -57, -31, 162, 35, -192,
+ -109, -335, -629, -66, -61, -128, 322,
+ -495, -669, -728, 193, 31, -220, 122,
+ 324, 95, -89, -91, -409, -710, -154,
+ 0, -234, 92, 33, -343, -609, -220,
+ -343, -408, -476, -655, -153, 82, 222,
+ -490, -745, -255, 49, -48, 135, -127,
+ 119, -67, -328, -390, -272, -545, -56,
+ -57, -130, -10, -7, -164, -47, -22,
+ 984, 1064, 961, 568, 210, -27, 16,
+ 811, 691, 754, 514, 224, -35, 166,
+ 662, 704, 618, 386, 57, -211, -257,
+ 510, 359, 418, 393, 91, -144, -18,
+ -193, -31, -27, 223, 89, -143, 24,
+ -112, -98, 471, 319, 185, 3, 175,
+ 252, 146, -47, 272, 48, -211, -234,
+ 146, 69, 203, 364, 68, -52, 51,
+ -259, -478, -697, -349, -758, -501, 63,
+ -501, -769, -289, 79, -311, -497, -106,
+ 251, 53, -235, -469, -895, -884, 145,
+ -416, -551, 140, -133, -523, -775, 44,
+ -326, -423, -713, -497, -86, -431, 99,
+ -757, -772, -160, -76, -46, -32, 379,
+ 85, -35, -200, -401, -663, -1040, -247,
+ -180, -330, -92, -376, 27, -183, -110,
+ 1279, 1086, 781, 502, 324, 164, 157,
+ 682, 466, 449, 277, 146, 28, 409,
+ 635, 472, 390, 107, -232, -538, -139,
+ 196, 396, 332, 213, 209, -29, -81,
+ 150, -95, -312, 76, -77, -320, -50,
+ 46, 9, 47, 175, 139, 30, 384,
+ 218, 206, -24, -250, -96, -276, -183,
+ 26, 119, 38, 14, -4, -133, -52,
+ -477, -614, -987, -715, -631, -813, 200,
+ -744, -1009, -1065, -745, -631, -171, 18,
+ -137, -251, -483, -613, -980, -1203, 12,
+ -605, -767, -562, -686, -1088, -515, 58,
+ -202, -428, -782, -1072, -96, -234, -179,
+ -480, -709, -1070, -897, -131, -92, 321,
+ -145, -193, -512, -729, -572, -765, -210,
+ -331, -585, -525, -631, -281, -208, -303,
+ 1165, 1104, 939, 828, 716, 426, 155,
+ 6, -109, 820, 778, 415, 113, -27,
+ 381, 339, 314, 265, 121, -9, -474,
+ -373, 47, 584, 442, 99, -231, -113,
+ -496, -38, -285, 262, 305, 170, 4,
+ -587, -556, 69, 66, 471, 354, 13,
+ -138, 70, -18, 106, 67, 167, -302,
+ -445, -141, 185, 191, 151, 83, -133,
+ -257, -521, -720, -198, 134, -46, -182,
+ -819, -1168, -777, 512, 359, 95, -113,
+ 137, -2, -74, -138, -401, -114, -371,
+ -242, -466, 204, 223, -31, -212, -192,
+ -532, -637, -466, -686, 256, 277, -139,
+ -1141, -1244, -381, -75, -54, 14, 88,
+ -311, 115, -143, -499, -343, 124, -416,
+ -616, -147, -135, 43, -4, 121, -369,
+ 835, 783, 641, 390, 355, 350, 64,
+ 72, 194, 443, 467, 436, 219, 372,
+ 464, 369, 192, 4, -156, -72, -226,
+ 57, 206, 303, 205, 188, 101, 265,
+ -40, -205, -488, -184, 276, 64, -26,
+ -217, -433, -297, 137, 328, 308, -289,
+ 378, 81, -308, -465, 57, -37, 227,
+ -100, 24, -36, -151, 199, 8, 143,
+ -426, -697, -1059, -133, 388, 161, 321,
+ -644, -1023, -1271, 39, 66, -123, 70,
+ 372, 177, -173, -556, -553, -304, -189,
+ -117, -369, -425, -122, -462, -152, -73,
+ -649, -850, -1189, -767, 497, 360, 222,
+ -798, -1139, -1455, -190, 430, 234, 179,
+ 42, -94, -405, -692, 38, -202, -246,
+ -169, -366, -290, -88, -64, 32, -292,
+ 1010, 923, 938, 710, 465, 230, 342,
+ 217, 300, 1054, 675, 68, -458, -179,
+ 78, 453, 316, 18, -237, -496, -243,
+ 167, 21, 424, 215, -91, -303, -170,
+ -290, -81, -70, -67, 40, 54, -59,
+ -353, -427, -90, 53, 94, 9, 54,
+ -28, 318, 283, 15, -240, -58, 79,
+ -75, -121, 229, 35, 58, 6, -133,
+ -351, -514, -744, -834, -705, -137, 164,
+ -1124, -1388, -1055, -230, -73, 40, 36,
+ -163, -233, -532, -785, -1170, -697, 96,
+ -788, -959, -246, -430, -624, -165, -8,
+ -856, -540, -630, -907, -337, -70, 76,
+ -937, -1042, -659, -733, -208, 199, -26,
+ -523, 78, -98, -501, -869, -890, -81,
+ -624, -703, -45, -348, -25, 87, -186,
+ 1005, 823, 546, 249, 90, -22, 207,
+ 298, 397, 381, 319, 200, 62, 303,
+ 473, 379, 133, -247, -632, -441, 75,
+ 284, 208, 391, 115, -25, 44, 95,
+ -72, 79, -95, -63, -129, -293, 203,
+ -164, -349, 115, 122, 69, -1, 378,
+ 348, 170, 99, 58, -179, -302, 188,
+ -190, -2, 150, 23, -51, -11, 216,
+ -615, -863, -1090, -1427, -802, -48, -6,
+ -961, -1276, -1548, -727, -58, 56, 223,
+ -124, -255, -561, -988, -1277, -148, -82,
+ -480, -660, -891, -1191, -1339, -325, 20,
+ -621, -917, -1296, -1350, 264, 289, 50,
+ -844, -1022, -1345, -1329, -293, 46, 278,
+ -260, -468, -829, -1176, -533, -560, -78,
+ -215, -484, -822, -1233, -791, 15, -138,
+ 1301, 1317, 1262, 1048, 716, 357, -64,
+ 578, 824, 925, 802, 630, 362, 102,
+ 470, 925, 767, 514, 327, 190, -112,
+ 225, 492, 495, 437, 598, 384, -45,
+ 43, 82, -42, 175, 519, 342, -64,
+ -304, -154, 159, 576, 403, 221, 327,
+ 214, 244, 122, -62, 312, 92, -160,
+ 218, 208, 310, 268, 306, 323, -199,
+ -285, -269, -79, -124, -143, -153, 236,
+ -205, -384, -426, 344, 59, -185, -184,
+ -272, 247, 126, -210, -518, -468, 78,
+ -99, -120, 502, 160, -280, -557, 304,
+ -423, -17, -283, -443, 215, 212, -140,
+ -564, -684, -228, 510, 361, 130, 323,
+ -428, 335, 98, -65, 36, -215, -246,
+ -362, 51, 364, -16, -234, 150, -165,
+ 914, 883, 751, 653, 676, 464, -153,
+ 631, 545, 535, 720, 596, 360, -81,
+ 783, 712, 512, 439, 341, 251, -391,
+ 497, 417, 249, 372, 295, 173, -193,
+ 128, -110, -385, 93, 39, 173, -231,
+ 216, -59, -253, 462, 389, 154, 69,
+ 455, 270, -4, -337, -49, 233, -322,
+ 307, 143, 53, 218, 128, 236, -156,
+ -37, -186, -240, -411, -110, 9, 399,
+ -140, -365, -628, 258, 380, 214, 277,
+ 131, 454, 177, -285, -520, 108, -214,
+ 77, -141, 201, -123, -490, -131, 60,
+ -14, -194, -521, -741, 273, 362, -33,
+ -362, -566, -287, -228, 161, 237, 317,
+ -269, 195, -75, -375, -204, 11, 77,
+ -128, -264, -156, -223, -475, 265, 27,
+ 1238, 1147, 916, 689, 432, 210, -280,
+ 800, 664, 879, 726, 411, 160, -164,
+ 454, 686, 536, 275, 147, 46, 111,
+ 303, 486, 512, 355, 241, 181, -69,
+ 79, 92, 29, 147, 233, 52, 17,
+ -171, 289, 131, 439, 271, 3, -10,
+ 413, 241, 144, 174, 155, -2, 14,
+ 58, 217, 247, 219, 149, 175, -18,
+ 228, -8, -240, -206, -513, -191, 202,
+ -96, -272, -454, 33, -300, -575, 46,
+ -10, -108, -246, -347, -770, -535, 9,
+ -326, -430, -61, -321, -704, -299, 201,
+ -1, -280, -603, -419, -185, 18, -36,
+ -516, -522, -379, -291, -181, -97, 27,
+ -159, -313, -525, -224, -510, -831, -197,
+ -292, -459, -59, -310, -562, -143, -351,
+ 1066, 912, 631, 389, 207, 86, -224,
+ 596, 512, 596, 505, 314, 122, -48,
+ 787, 861, 441, -93, -303, 33, -190,
+ 257, 469, 337, 51, 15, 298, -93,
+ 295, 73, -119, 25, 36, 23, 108,
+ -28, -3, -32, 114, 21, 185, 107,
+ 482, 305, 15, -279, -319, 52, 96,
+ 226, 46, 115, 72, -136, 133, -125,
+ 18, -207, -559, -590, -503, -482, 321,
+ -571, -789, -951, -172, -441, -538, 113,
+ 181, 14, -310, -641, -1001, -202, 159,
+ -136, -393, -433, -513, -911, -144, -22,
+ 72, -265, -706, -954, -159, 53, 332,
+ -338, -591, -852, -383, -395, 56, 44,
+ 43, -158, -464, -897, -631, -157, -294,
+ -161, -128, -328, -573, -483, -125, 11,
+ 1017, 906, 1051, 1005, 679, 341, -102,
+ 359, 334, 1567, 1314, 723, 105, 10,
+ -65, 726, 529, 301, 220, 43, -273,
+ -510, 436, 719, 566, 358, 179, 114,
+ -560, 298, 133, -120, 342, 225, 14,
+ -899, -101, 217, 617, 400, 146, -58,
+ -41, 352, 82, -196, 39, 121, -167,
+ -212, 59, 447, 284, 423, 250, -169,
+ -371, -484, -596, 30, -41, 249, 22,
+ -372, -650, -794, 477, 445, 216, -79,
+ -352, 275, 17, -443, -929, 92, 19,
+ -699, -696, 431, 264, -49, -310, 182,
+ -978, -217, -430, -400, 101, 261, 72,
+ -929, -889, -357, -13, 463, 378, 236,
+ -826, 56, 30, -299, -360, -128, -51,
+ -878, -299, -111, 75, 65, 36, 3,
+ 817, 368, -25, 354, 697, 591, -173,
+ 309, 212, 222, 751, 484, 140, -56,
+ 593, 379, 70, -8, 258, 180, 110,
+ 165, -46, 255, 297, 219, 273, 105,
+ 160, -70, -358, -181, 379, 330, 319,
+ -238, -369, -198, 740, 580, 319, -143,
+ 201, 109, -202, -456, 328, 276, -141,
+ 203, 170, 111, 42, 207, 360, 188,
+ -345, -399, -513, -233, 650, 422, 81,
+ -635, -961, -1220, 463, 539, 204, 209,
+ 202, -25, -194, -498, -787, 193, -143,
+ -449, -538, 195, -106, -331, 68, 62,
+ -228, -477, -840, -576, 317, 128, 283,
+ -671, -937, -807, -114, 391, 335, -62,
+ 246, 2, -314, -679, -303, 180, -88,
+ -107, -272, 90, -198, -28, 290, -112,
+ 885, 1149, 1021, 712, 496, 281, -83,
+ 269, 492, 787, 643, 347, 70, 124,
+ 336, 636, 499, 92, -229, -179, 191,
+ 26, 402, 564, 340, 149, -11, 135,
+ -440, 561, 470, 204, -72, -186, 140,
+ -720, 14, 355, 229, 68, -133, 465,
+ 110, 310, 103, 12, 106, 29, 158,
+ -178, 113, 161, 142, 121, 115, 27,
+ -651, -414, -645, -152, -164, -13, -429,
+ -639, -944, -681, -104, -81, 52, -189,
+ -663, -164, -316, -683, -954, -205, -83,
+ -609, -669, -172, -517, -694, 283, -80,
+ -646, -152, -383, -678, -246, -40, -143,
+ -747, -796, -745, -390, -98, 43, 275,
+ -599, -199, -398, -433, -436, -538, 31,
+ -1107, -568, -376, -265, -126, -21, 1,
+ 847, 573, 308, 392, 305, 101, 55,
+ 273, 293, 201, 267, 346, 201, 123,
+ 727, 480, 226, 2, -65, -138, 164,
+ 273, 208, 173, 292, 12, 253, 174,
+ 340, 207, 180, 88, 116, 46, 475,
+ -460, -166, -30, 13, 110, 173, 396,
+ 137, 88, 43, -137, -94, 34, 284,
+ 96, -14, 226, 40, 63, 70, 130,
+ -467, -735, -1012, -1174, -307, 305, -67,
+ -612, -920, -1146, -567, -8, 92, -25,
+ -182, -271, -492, -754, -857, 287, -75,
+ -494, -787, -689, -683, -709, 137, -326,
+ -288, -550, -903, -1105, 334, 321, -62,
+ -354, -653, -834, -445, 1, 377, -152,
+ -162, -306, -608, -937, -297, 247, -192,
+ -234, -477, -244, -488, -266, 342, -332};
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 1st split: isf2_0 to isf2_2
+ *---------------------------------------------------*/
+
+
+static Word16 dico21_isf[SIZE_BK21*3] = {
+
+ 329, 409, 249,
+ -33, 505, 160,
+ -29, -14, 582,
+ -262, 127, 354,
+ 145, 237, 175,
+ -152, 245, 122,
+ 27, 42, 340,
+ -84, -93, 311,
+ 285, 222, -156,
+ 47, -43, -504,
+ 234, 121, 385,
+ 104, -317, 45,
+ 176, 195, 8,
+ 104, -59, -94,
+ 177, 53, 192,
+ -34, -127, 152,
+ 570, 277, -34,
+ -67, -329, -639,
+ -157, -272, 462,
+ -177, -462, 198,
+ 322, 179, 115,
+ -386, 171, 19,
+ 19, -12, 195,
+ -120, -252, 201,
+ 304, 36, -336,
+ -128, -221, -380,
+ 171, -185, 296,
+ -242, -312, 23,
+ 198, 39, 16,
+ -3, -177, -111,
+ 111, -93, 76,
+ -92, -223, 4,
+ 177, 406, -44,
+ -168, 380, -149,
+ -4, 273, 331,
+ -420, 513, 277,
+ 21, 247, 47,
+ -58, 131, -2,
+ -3, 134, 180,
+ -145, 40, 175,
+ 189, 74, -145,
+ -27, -45, -325,
+ 370, -114, -21,
+ -83, -415, -173,
+ 77, 95, -51,
+ -40, -30, -67,
+ 71, 88, 86,
+ -35, -98, 14,
+ 69, 197, -334,
+ -196, 79, -231,
+ -348, -137, 218,
+ -352, -89, -85,
+ 47, 201, -130,
+ -165, 37, -15,
+ -43, 3, 86,
+ -161, -108, 79,
+ 83, 21, -237,
+ -81, -149, -238,
+ 150, -186, -251,
+ -186, -249, -162,
+ -19, 66, -139,
+ -26, -50, -181,
+ 24, 11, 0,
+ -130, -105, -98};
+
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 2nd split: isf2_3 to isf2_5
+ *---------------------------------------------------*/
+
+
+static Word16 dico22_isf[SIZE_BK22*3] = {
+
+ -127, 310, 42,
+ -242, 197, 5,
+ -151, 84, -17,
+ -214, 127, -149,
+ -247, -131, 159,
+ -268, -267, -95,
+ -217, 1, -79,
+ -271, -80, -185,
+ -45, 436, 159,
+ 165, 199, 391,
+ -33, 81, 187,
+ -66, -42, 355,
+ -298, -57, 343,
+ -108, -537, 226,
+ -144, -23, 193,
+ 176, -402, 87,
+ 53, 296, 25,
+ -84, 253, -104,
+ -58, 105, -126,
+ -169, 174, -314,
+ -48, 44, -294,
+ -164, -417, -242,
+ -139, 3, -194,
+ -155, -207, -211,
+ 119, 322, 213,
+ 333, 50, 380,
+ 237, 247, -2,
+ 466, -16, 201,
+ 238, -255, -107,
+ 67, -440, -149,
+ 122, -88, -139,
+ 88, -247, -73,
+ -41, 231, 167,
+ -62, 155, 16,
+ -65, 16, 77,
+ -68, -2, -63,
+ -151, -300, 160,
+ -18, -333, 54,
+ -56, -94, 5,
+ 2, -190, 14,
+ 92, 148, 209,
+ 108, 9, 272,
+ 108, 35, 110,
+ 142, -85, 145,
+ 47, -157, 279,
+ 3, -320, 246,
+ 43, -72, 68,
+ 86, -217, 135,
+ 36, 140, 79,
+ 56, 175, -49,
+ 26, 45, 3,
+ 73, 55, -101,
+ 109, -183, -242,
+ -4, -283, -242,
+ 48, -68, -48,
+ -6, -153, -122,
+ 161, 196, 96,
+ 232, 80, 190,
+ 165, 97, 11,
+ 258, -31, 71,
+ 267, -77, -91,
+ 311, -209, 87,
+ 152, -14, -22,
+ 150, -149, 9,
+ -324, 557, 187,
+ -384, 307, 46,
+ -251, 27, 77,
+ -365, 77, -52,
+ -482, -84, 160,
+ -424, -515, -64,
+ -294, -120, -4,
+ -476, -116, -109,
+ -97, 318, 365,
+ 106, 627, 445,
+ -190, 120, 287,
+ -146, 65, 619,
+ -427, 242, 363,
+ -361, -371, 432,
+ -347, 102, 168,
+ -629, 195, -14,
+ -65, 476, -47,
+ -297, 320, -168,
+ -55, 356, -264,
+ -391, 82, -286,
+ -51, -31, -556,
+ -178, -399, -586,
+ -205, -49, -360,
+ -343, -238, -337,
+ 220, 457, 58,
+ 561, 467, 259,
+ 340, 270, -168,
+ 450, 77, -280,
+ 60, 167, -413,
+ 133, -252, -492,
+ 216, 157, -290,
+ 282, 0, -495,
+ -226, 293, 183,
+ -157, 135, 122,
+ -158, -59, 39,
+ -133, -118, -97,
+ -332, -309, 113,
+ -160, -425, -6,
+ -149, -211, 24,
+ -80, -277, -90,
+ -11, 125, 338,
+ 130, -71, 465,
+ 5, -45, 184,
+ 237, -95, 253,
+ -139, -197, 297,
+ -19, -300, 511,
+ -63, -152, 139,
+ 250, -289, 336,
+ 124, 339, -150,
+ 34, 176, -208,
+ 171, 166, -116,
+ 94, 38, -229,
+ 75, -65, -339,
+ -78, -205, -385,
+ 0, -30, -163,
+ -56, -110, -242,
+ 321, 244, 194,
+ 505, 238, -1,
+ 317, 116, 65,
+ 309, 88, -74,
+ 452, -51, -50,
+ 334, -217, -290,
+ 211, 41, -152,
+ 238, -55, -260};
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 3rd split: isf2_6 to isf2_8
+ *---------------------------------------------------*/
+
+
+static Word16 dico23_isf[SIZE_BK23*3] = {
+
+ -10, 151, 359,
+ 136, 298, 223,
+ 255, -104, 290,
+ 423, 6, 183,
+ -270, -269, -98,
+ -52, -82, 13,
+ -82, -274, -97,
+ 90, -246, -72,
+ -299, -70, 421,
+ -88, 365, 430,
+ 187, -318, 381,
+ 380, 37, 488,
+ -373, -316, 79,
+ -308, -101, 5,
+ -135, -451, 8,
+ 72, -421, -154,
+ 180, 170, -121,
+ 62, 177, -40,
+ 326, 80, -105,
+ 248, 263, -5,
+ -168, -181, -221,
+ -2, -23, -158,
+ -14, -149, -121,
+ 119, -91, -147,
+ 119, 332, -153,
+ 49, 303, 34,
+ 442, -55, -69,
+ 217, 454, 58,
+ -359, -187, -375,
+ -42, 50, -274,
+ -8, -267, -249,
+ 85, -86, -346,
+ -77, -40, 345,
+ 89, 134, 219,
+ 156, -80, 160,
+ 108, 40, 116,
+ -158, -206, 29,
+ 5, -32, 175,
+ -65, -158, 146,
+ 55, -78, 73,
+ -114, -222, 353,
+ -47, 81, 211,
+ 49, -151, 268,
+ 105, 4, 302,
+ -263, -132, 183,
+ -151, -28, 201,
+ -177, -307, 166,
+ 101, -221, 130,
+ 74, 58, -98,
+ 32, 44, 13,
+ 194, 30, -142,
+ 170, 96, 8,
+ -136, -119, -91,
+ -65, 8, -55,
+ 3, -188, 12,
+ 45, -63, -49,
+ 149, -21, -19,
+ 24, 144, 95,
+ 254, -22, 60,
+ 161, 196, 96,
+ -158, -61, 48,
+ -70, 33, 82,
+ -23, -321, 58,
+ 155, -147, 5,
+ -364, 328, 77,
+ -21, 453, 173,
+ -108, 82, 630,
+ 367, 263, 208,
+ -300, -62, -176,
+ -205, 143, -158,
+ -169, -410, -264,
+ 257, -269, -100,
+ -636, 289, -2,
+ -292, 627, 173,
+ -382, -363, 387,
+ 248, 524, 447,
+ -521, -111, -107,
+ -395, 118, -274,
+ -343, -680, -125,
+ -172, -447, -663,
+ 75, 148, -367,
+ -79, 263, -94,
+ 249, 148, -286,
+ 380, 271, -162,
+ -142, -4, -186,
+ -57, 111, -125,
+ -35, -108, -254,
+ 100, 29, -242,
+ -80, 303, -264,
+ -78, 464, -57,
+ 248, -22, -494,
+ 661, 662, 44,
+ -193, -40, -330,
+ -178, 145, -337,
+ -90, -199, -400,
+ -40, -23, -498,
+ -192, 114, 315,
+ -41, 244, 190,
+ 88, -97, 485,
+ 241, 80, 212,
+ -246, 40, 87,
+ -156, 147, 134,
+ -2, -334, 239,
+ 308, -203, 110,
+ -459, 251, 422,
+ -218, 310, 228,
+ -86, -346, 654,
+ 184, 175, 425,
+ -481, -63, 169,
+ -349, 117, 188,
+ -125, -560, 310,
+ 158, -416, 94,
+ 46, 171, -192,
+ -63, 157, 14,
+ 256, -35, -271,
+ 322, 123, 53,
+ -214, 4, -76,
+ -156, 86, -18,
+ 128, -197, -232,
+ 265, -90, -98,
+ -308, 332, -145,
+ -131, 308, 58,
+ 509, 59, -339,
+ 562, 196, -14,
+ -378, 100, -47,
+ -234, 202, 1,
+ 104, -270, -493,
+ 319, -210, -325};
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 4th split: isf2_9 to isf2_11
+ *---------------------------------------------------*/
+
+static Word16 dico24_isf[SIZE_BK24*3] = {
+
+ -79, -89, -4,
+ -171, 77, -211,
+ 160, -193, 98,
+ 120, -103, 323,
+ 32, -22, -129,
+ 72, 78, -268,
+ 182, -76, -66,
+ 309, 99, -145,
+ -229, -157, -84,
+ -383, 98, -71,
+ -90, -352, 12,
+ -284, -178, 178,
+ -65, -125, -166,
+ -87, -175, -351,
+ 42, -198, -48,
+ 154, -140, -243,
+ -77, 18, 108,
+ -39, 355, 91,
+ 87, 8, 155,
+ -4, 158, 239,
+ 128, 95, -54,
+ 7, 246, -124,
+ 258, 15, 89,
+ 206, 216, 98,
+ -201, 9, 18,
+ -312, 233, 204,
+ -39, -174, 155,
+ -144, -9, 284,
+ -57, 70, -69,
+ -157, 187, 18,
+ 54, -30, 23,
+ 24, 135, 55};
+
+
+/*---------------------------------------------------*
+ * 2nd stage codebook; 5th split: isf2_12 to isf2_15
+ *---------------------------------------------------*/
+
+static Word16 dico25_isf[SIZE_BK25*4] = {
+
+ 169, 142, -119, 115,
+ 206, -20, 94, 226,
+ -106, 313, -21, 16,
+ -62, 161, 71, 255,
+ -89, 101, -185, 125,
+ 72, -30, -201, 344,
+ -258, 33, -8, 81,
+ -104, -154, 72, 296,
+ 144, -68, -268, -25,
+ 81, -78, -87, 106,
+ 22, 155, -186, -119,
+ -46, -28, 27, 91,
+ -114, -37, -175, -33,
+ -94, -222, -189, 122,
+ -132, -119, -191, -270,
+ -172, -173, 18, -43,
+ 279, 135, -42, -128,
+ 187, -86, 229, -138,
+ 159, 240, 140, 46,
+ 69, 25, 227, 77,
+ 21, 115, 13, 8,
+ 68, -248, 126, 81,
+ -150, 137, 207, -9,
+ -154, -133, 289, 67,
+ 143, -37, -86, -326,
+ 180, -32, 19, -23,
+ 26, 168, 116, -233,
+ -32, -26, 118, -78,
+ 3, -8, -45, -115,
+ 57, -215, -54, -83,
+ -209, 112, -22, -167,
+ -91, -151, 168, -262};
+
+
+
+ /* 36 bit */
+/*-------------------------------------------------------------------*
+ * isf codebooks: two-stage VQ with split-by-3 in 2nd stage *
+ * 1st stage is kept the same as the 46 bit quantizer *
+ * *
+ * codebook vector dimension number of vectors *
+ * ~~~~~~~~ ~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~ *
+ * 1_1 9 256 *
+ * 1_2 7 256 *
+ * 2_1 5 128 *
+ * 2_2 4 128 *
+ * 2_3 7 64 *
+ *-------------------------------------------------------------------*/
+
+static Word16 dico21_isf_36b[SIZE_BK21_36b*5] = {
+
+ -52, -96, 212, 315, -73,
+ 82, -204, 363, 136, -197,
+ -126, -331, 183, 218, 143,
+ -49, -41, 557, 230, 72,
+ 2, -73, 163, 377, 221,
+ 133, 111, 278, 215, -110,
+ -102, -20, 284, 113, 273,
+ 84, 319, 290, 18, 85,
+ -25, -5, 125, 132, -204,
+ -38, -5, 286, -9, -356,
+ -140, -256, 92, 117, -189,
+ -144, 191, 313, 51, -98,
+ 167, -10, 44, 247, 36,
+ 381, 197, 238, 74, 6,
+ 38, -408, 29, -3, -85,
+ 92, 266, 157, -25, -200,
+ 161, -121, 70, 84, -140,
+ -16, -86, 112, -94, -189,
+ -269, -270, 351, 107, -24,
+ -68, -67, 492, -103, -155,
+ -53, -131, 62, 122, 10,
+ 135, 84, 283, -55, -120,
+ -12, -219, 331, -81, 167,
+ 220, -136, 147, -172, -42,
+ 140, -95, -109, -88, -194,
+ 0, -2, -4, -33, -381,
+ -66, -217, 152, -186, -402,
+ 244, 108, 156, -140, -395,
+ 113, -136, -196, 110, -24,
+ 214, 118, 11, -64, -131,
+ -110, -286, -6, -332, 16,
+ 94, 97, 79, -291, -205,
+ -5, -39, -20, 252, -96,
+ 76, 174, 101, 163, 61,
+ -69, -239, -55, 399, 6,
+ -115, 319, 164, 275, 196,
+ -15, 36, -47, 331, 121,
+ 226, 209, 271, 325, 184,
+ 13, -80, -218, 471, 353,
+ 288, 378, 16, -51, 251,
+ 174, 116, 52, 149, -279,
+ 235, 276, 39, 120, -48,
+ 0, -108, -108, 241, -339,
+ -93, 534, 45, 33, -87,
+ 194, 149, -71, 405, -44,
+ 409, 370, 81, -186, -154,
+ 25, -102, -448, 124, -173,
+ 22, 408, -110, -310, -214,
+ -26, 23, -83, 114, 14,
+ -110, 164, 52, 223, -82,
+ 37, -25, -263, 306, -15,
+ -466, 415, 292, 165, -18,
+ 29, -19, -171, 155, 182,
+ 179, 144, -27, 231, 258,
+ -103, -247, -396, 238, 113,
+ 375, -154, -109, -4, 156,
+ 98, 85, -292, -5, -124,
+ 116, 139, -116, -98, -294,
+ -14, -83, -278, -117, -378,
+ 106, 33, -106, -344, -484,
+ 119, 17, -412, 138, 166,
+ 384, 101, -204, 88, -156,
+ -121, -284, -300, -1, -166,
+ 280, 33, -152, -313, -81,
+ -37, 22, 229, 153, 37,
+ -60, -83, 236, -8, -41,
+ -169, -228, 126, -20, 363,
+ -235, 17, 364, -156, 156,
+ -25, -30, 72, 144, 156,
+ 153, -26, 256, 97, 144,
+ -21, -37, 48, -65, 250,
+ 63, 77, 273, -128, 124,
+ -129, -26, 40, 9, -115,
+ -6, 82, 38, -90, -182,
+ -336, -13, 28, 158, 91,
+ -30, 241, 137, -170, -17,
+ 146, 14, -11, 33, 61,
+ 192, 197, 54, -84, 85,
+ 23, -200, -78, -29, 140,
+ 122, 237, 106, -341, 136,
+ -57, -142, -85, -16, -74,
+ -59, -90, -8, -187, -20,
+ -211, -267, 216, -179, -110,
+ -50, -7, 220, -267, -70,
+ -57, -42, -17, -15, 71,
+ 32, 21, 63, -137, 33,
+ -137, -175, 104, -68, 97,
+ -67, -43, 133, -301, 221,
+ -116, -200, -81, -92, -272,
+ -64, -41, -54, -244, -220,
+ -287, -242, -50, -87, -89,
+ -245, 236, 102, -166, -295,
+ 66, 24, -162, -71, 95,
+ 66, 136, -90, -220, -36,
+ -98, -161, -222, -188, 29,
+ -18, 18, -19, -415, 9,
+ 49, 61, 100, 39, -56,
+ -111, 82, 135, -31, 52,
+ -90, -153, -93, 189, 182,
+ -214, 295, 119, -74, 284,
+ 2, 137, 37, 47, 182,
+ 92, 117, 184, -53, 373,
+ -21, -14, -35, 136, 391,
+ 146, 129, -164, -28, 333,
+ 92, 80, -84, 100, -134,
+ -8, 217, -32, 3, -47,
+ -151, 251, -215, 142, 92,
+ -224, 310, -172, -275, 98,
+ 159, 155, -177, 112, 53,
+ 205, 27, 8, -240, 192,
+ 169, 120, -319, -201, 106,
+ 11, 36, -86, -237, 455,
+ -109, -154, -163, 174, -55,
+ -38, 32, -101, -78, -59,
+ -205, -321, -97, 69, 79,
+ -310, 44, 18, -185, 34,
+ -115, -20, -148, -39, 203,
+ -29, 154, -30, -158, 166,
+ -45, -131, -317, -24, 363,
+ -165, -205, -112, -222, 265,
+ -32, -44, -150, 54, -193,
+ -6, -38, -255, -169, -115,
+ -266, 87, -189, -36, -169,
+ -60, -87, -266, -436, -170,
+ -68, -81, -278, 24, 38,
+ -23, -19, -155, -256, 141,
+ -61, -226, -565, -175, 71,
+ 9, -29, -237, -515, 263};
+
+static Word16 dico22_isf_36b[SIZE_BK22_36b*4] = {
+
+ -298, -6, 95, 31,
+ -213, -87, -122, 261,
+ 4, -49, 208, 14,
+ -129, -110, 30, 118,
+ -214, 258, 110, -235,
+ -41, -18, -126, 120,
+ 103, 65, 127, -37,
+ 126, -36, -24, 25,
+ -138, -67, -278, -186,
+ -164, -194, -201, 78,
+ -211, -87, -51, -221,
+ -174, -79, -94, -39,
+ 23, -6, -157, -240,
+ 22, -110, -153, -68,
+ 148, -5, -2, -149,
+ -1, -135, -39, -179,
+ 68, 360, -117, -15,
+ 137, 47, -278, 146,
+ 136, 260, 135, 65,
+ 61, 116, -45, 97,
+ 231, 379, 87, -120,
+ 338, 177, -272, 3,
+ 266, 156, 28, -69,
+ 260, 84, -85, 86,
+ -266, 154, -256, -182,
+ -17, -65, -304, -6,
+ -40, 175, -151, -180,
+ -27, 27, -87, -63,
+ 121, 114, -166, -469,
+ 159, -66, -323, -231,
+ 214, 152, -141, -212,
+ 137, 36, -184, -51,
+ -282, -237, 40, 10,
+ -48, -235, -37, 251,
+ -54, -323, 136, 29,
+ -88, -174, 213, 198,
+ -390, 99, -63, -375,
+ 107, -169, -164, 424,
+ 69, -111, 141, -167,
+ 74, -129, 65, 144,
+ -353, -207, -205, -109,
+ -160, -386, -355, 98,
+ -176, -493, -20, -143,
+ -252, -432, -2, 216,
+ -90, -174, -168, -411,
+ 13, -284, -229, -160,
+ -87, -279, 34, -251,
+ -75, -263, -58, -42,
+ 420, 53, -211, -358,
+ 384, -35, -374, 396,
+ 68, -228, 323, -2,
+ 167, -307, 192, 194,
+ 459, 329, -5, -332,
+ 375, 79, -7, 313,
+ 282, -124, 200, -92,
+ 271, -162, -70, 180,
+ -157, -298, -514, -309,
+ 58, -163, -546, 18,
+ 124, -364, 167, -238,
+ 83, -411, -117, 96,
+ 140, -112, -388, -624,
+ 259, -133, -317, 41,
+ 163, -130, -64, -334,
+ 226, -165, -124, -110,
+ -466, -61, 6, 229,
+ -153, 205, -145, 242,
+ -159, 48, 195, 148,
+ -58, 28, 31, 279,
+ -303, 185, 279, -4,
+ -61, 197, 59, 86,
+ -114, 123, 168, -52,
+ 35, 36, 100, 126,
+ -407, 102, -77, -40,
+ -338, -1, -342, 156,
+ -179, 105, -34, -97,
+ -185, 84, -35, 108,
+ -133, 107, -91, -357,
+ -180, 54, -229, 24,
+ -44, 47, 47, -182,
+ -66, 13, 45, 4,
+ -339, 251, 64, 226,
+ -42, 101, -350, 275,
+ -99, 398, 142, 121,
+ 111, 12, -102, 260,
+ 0, 505, 260, -94,
+ 161, 285, -96, 224,
+ -4, 206, 314, 33,
+ 167, 139, 88, 204,
+ -235, 316, -60, -25,
+ -8, -150, -312, 201,
+ -36, 292, 61, -104,
+ -40, 174, -162, 42,
+ -21, 402, -29, -351,
+ 21, 152, -360, -93,
+ 57, 191, 212, -196,
+ 76, 158, -21, -69,
+ -328, -185, 331, 119,
+ -53, 285, 56, 337,
+ -107, -24, 405, 29,
+ -18, 137, 272, 277,
+ -255, 22, 173, -191,
+ 295, 322, 325, 302,
+ 21, -27, 332, -178,
+ 119, 13, 271, 129,
+ -455, -180, 116, -191,
+ -227, 62, -148, 524,
+ -176, -287, 282, -157,
+ -243, 13, 199, 430,
+ -59, -49, 115, -365,
+ 72, -172, -137, 93,
+ -138, -126, 141, -84,
+ 5, -124, 38, -20,
+ -258, 311, 601, 213,
+ 94, 130, -61, 502,
+ -1, -157, 485, 313,
+ 146, -74, 158, 345,
+ 276, 135, 280, -57,
+ 490, 252, 99, 43,
+ 267, -74, 429, 105,
+ 278, -23, 119, 94,
+ -542, 488, 257, -115,
+ -84, -244, -438, 478,
+ -113, -545, 387, 101,
+ -95, -306, 111, 498,
+ 95, 166, 22, -301,
+ 420, -15, -58, -78,
+ 270, 29, 122, -282,
+ 160, -240, 50, -38};
+
+static Word16 dico23_isf_36b[SIZE_BK23_36b*7] = {
+
+ 81, -18, 68, -27, -122, -280, -4,
+ 45, -177, 209, -30, -136, -74, 131,
+ -44, 101, -75, -88, -48, -137, -54,
+ -245, -28, 63, -18, -112, -103, 58,
+ -79, -6, 220, -65, 114, -35, -50,
+ 109, -65, 143, -114, 129, 76, 125,
+ 166, 90, -61, -242, 186, -74, -43,
+ -46, -92, 49, -227, 24, -155, 39,
+ 67, 85, 99, -42, 53, -184, -281,
+ 142, -122, 0, 21, -142, -15, -17,
+ 223, 92, -21, -48, -82, -14, -167,
+ 51, -37, -243, -30, -90, 18, -56,
+ 54, 105, 74, 86, 69, 13, -101,
+ 196, 72, -89, 43, 65, 19, 39,
+ 121, 34, 131, -82, 25, 213, -156,
+ 101, -102, -136, -21, 57, 214, 22,
+ 36, -124, 205, 204, 58, -156, -83,
+ 83, -117, 137, 137, 85, 116, 44,
+ -92, -148, -68, 11, -102, -197, -220,
+ -76, -185, -58, 132, -26, -183, 85,
+ -7, -31, -2, 23, 205, -151, 10,
+ -27, -37, -5, -18, 292, 131, 1,
+ 117, -168, 9, -93, 80, -59, -125,
+ -182, -244, 98, -24, 135, -22, 94,
+ 221, 97, 106, 42, 43, -160, 83,
+ 25, -64, -21, 6, 14, -15, 154,
+ 126, 15, -140, 150, -10, -207, -114,
+ 79, -63, -211, -70, -28, -217, 165,
+ 46, 38, -22, 281, 132, -62, 109,
+ 112, 54, -112, -93, 208, 27, 296,
+ 115, 10, -147, 41, 216, 42, -276,
+ 50, -115, -254, 167, 117, -2, 61,
+ 17, 144, 34, -72, -186, -150, 272,
+ -29, -66, -89, -95, -149, 129, 251,
+ 122, 0, -50, -234, -91, 36, 26,
+ -105, -102, -88, -121, -236, -7, -11,
+ -204, 109, 5, -191, 105, -15, 163,
+ -80, 32, -24, -209, 41, 294, 70,
+ -106, -94, -204, -118, 120, -50, -37,
+ -82, -241, 46, -131, -29, 150, -55,
+ 33, 155, 120, -89, -8, 7, 62,
+ 213, 82, 61, 18, -161, 144, 152,
+ 30, 131, 65, -87, -255, -17, -107,
+ -8, 85, -64, 51, -162, 223, -53,
+ -134, 261, 69, -56, 218, 72, -111,
+ 2, 155, -113, -87, 49, 85, -28,
+ -163, 42, -1, -196, 7, 39, -245,
+ 14, -137, -79, 11, -160, 202, -293,
+ -94, 33, 208, 100, 56, -44, 326,
+ -78, -41, 232, 13, -142, 227, 80,
+ -16, -87, 201, 33, -133, 15, -183,
+ -58, -192, -47, 184, -128, 133, 99,
+ -205, 11, -155, 78, 52, 72, 141,
+ -246, 26, 99, 151, 59, 115, -64,
+ -79, -47, -16, -14, 6, 47, -43,
+ -72, -178, -27, 162, 112, 43, -174,
+ -175, 238, 186, 71, -54, -188, -76,
+ -225, 233, 39, -39, -158, 122, 44,
+ -26, 43, 84, 130, -93, -51, 22,
+ 3, 92, -150, 136, -182, -57, 97,
+ -131, 179, -78, 80, 91, -165, 90,
+ -2, 148, 15, 130, 65, 175, 117,
+ -138, 114, -137, 132, 3, -10, -186,
+ 140, -4, -37, 254, -62, 92, -109};
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/stream.h b/media/libstagefright/codecs/amrwbenc/inc/stream.h
new file mode 100644
index 0000000..edbc13a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/stream.h
@@ -0,0 +1,47 @@
+
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: stream.h
+
+Contains: VOME API Buffer Operator Implement Header
+
+************************************************************************/
+#ifndef __STREAM_H__
+#define __STREAM_H__
+
+#include "voMem.h"
+#define Frame_Maxsize 1024 * 2 //Work Buffer 10K
+#define Frame_MaxByte 640 //AMR_WB Encoder one frame 320 samples = 640 Bytes
+#define MIN(a,b) ((a) < (b)? (a) : (b))
+
+typedef struct{
+ unsigned char *set_ptr;
+ unsigned char *frame_ptr;
+ unsigned char *frame_ptr_bk;
+ int set_len;
+ int framebuffer_len;
+ int frame_storelen;
+ int used_len;
+}FrameStream;
+
+void voAWB_UpdateFrameBuffer(FrameStream *stream, VO_MEM_OPERATOR *pMemOP);
+void voAWB_InitFrameBuffer(FrameStream *stream);
+void voAWB_FlushFrameBuffer(FrameStream *stream);
+#endif //__STREAM_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedef.h b/media/libstagefright/codecs/amrwbenc/inc/typedef.h
new file mode 100644
index 0000000..aa8c098
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/typedef.h
@@ -0,0 +1,65 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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 : typedef.c
+* Purpose : Basic types.
+*
+************************************************************************/
+
+#ifndef __TYPEDEF_H__
+#define __TYPEDEF_H__
+
+#undef ORIGINAL_TYPEDEF_H /* define to get "original" ETSI version
+ of typedef.h */
+
+#ifdef ORIGINAL_TYPEDEF_H
+/*
+ * this is the original code from the ETSI file typedef.h
+ */
+
+#if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__ZTC__)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__sun)
+typedef signed char Word8;
+typedef short Word16;
+typedef long Word32;
+typedef int Flag;
+
+#elif defined(__unix__) || defined(__unix)
+typedef signed char Word8;
+typedef short Word16;
+typedef int Word32;
+typedef int Flag;
+
+#endif
+#else /* not original typedef.h */
+
+/*
+ * use (improved) type definition file typdefs.h and add a "Flag" type
+ */
+#include "typedefs.h"
+typedef int Flag;
+
+#endif
+
+#endif //__TYPEDEF_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/typedefs.h b/media/libstagefright/codecs/amrwbenc/inc/typedefs.h
new file mode 100644
index 0000000..28b657e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/typedefs.h
@@ -0,0 +1,211 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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 : typedefs.h
+* Description : Definition of platform independent data
+* types and constants
+*
+*
+* The following platform independent data types and corresponding
+* preprocessor (#define) constants are defined:
+*
+* defined type meaning corresponding constants
+* ----------------------------------------------------------
+* Char character (none)
+* Bool boolean true, false
+* Word8 8-bit signed minWord8, maxWord8
+* UWord8 8-bit unsigned minUWord8, maxUWord8
+* Word16 16-bit signed minWord16, maxWord16
+* UWord16 16-bit unsigned minUWord16, maxUWord16
+* Word32 32-bit signed minWord32, maxWord32
+* UWord32 32-bit unsigned minUWord32, maxUWord32
+* Float floating point minFloat, maxFloat
+*
+*
+* The following compile switches are #defined:
+*
+* PLATFORM string indicating platform progam is compiled on
+* possible values: "OSF", "PC", "SUN"
+*
+* OSF only defined if the current platform is an Alpha
+* PC only defined if the current platform is a PC
+* SUN only defined if the current platform is a Sun
+*
+* LSBFIRST is defined if the byte order on this platform is
+* "least significant byte first" -> defined on DEC Alpha
+* and PC, undefined on Sun
+*
+********************************************************************************
+*/
+
+#ifndef __TYPEDEFS_H__
+#define __TYPEDEFS_H__
+
+/*
+********************************************************************************
+* INCLUDE FILES
+********************************************************************************
+*/
+#include <float.h>
+#include <limits.h>
+
+
+
+/*
+********************************************************************************
+* DEFINITION OF CONSTANTS
+********************************************************************************
+*/
+/*
+ ********* define char type
+ */
+typedef char Char;
+
+/*
+ ********* define 8 bit signed/unsigned types & constants
+ */
+#if SCHAR_MAX == 127
+typedef signed char Word8;
+#define minWord8 SCHAR_MIN
+#define maxWord8 SCHAR_MAX
+
+typedef unsigned char UWord8;
+#define minUWord8 0
+#define maxUWord8 UCHAR_MAX
+#else
+#error cannot find 8-bit type
+#endif
+
+
+/*
+ ********* define 16 bit signed/unsigned types & constants
+ */
+#if INT_MAX == 32767
+typedef int Word16;
+#define minWord16 INT_MIN
+#define maxWord16 INT_MAX
+typedef unsigned int UWord16;
+#define minUWord16 0
+#define maxUWord16 UINT_MAX
+#elif SHRT_MAX == 32767
+typedef short Word16;
+#define minWord16 SHRT_MIN
+#define maxWord16 SHRT_MAX
+typedef unsigned short UWord16;
+#define minUWord16 0
+#define maxUWord16 USHRT_MAX
+#else
+#error cannot find 16-bit type
+#endif
+
+
+/*
+ ********* define 32 bit signed/unsigned types & constants
+ */
+#if INT_MAX == 2147483647
+typedef int Word32;
+#define minWord32 INT_MIN
+#define maxWord32 INT_MAX
+typedef unsigned int UWord32;
+#define minUWord32 0
+#define maxUWord32 UINT_MAX
+#elif LONG_MAX == 2147483647
+typedef long Word32;
+#define minWord32 LONG_MIN
+#define maxWord32 LONG_MAX
+typedef unsigned long UWord32;
+#define minUWord32 0
+#define maxUWord32 ULONG_MAX
+#else
+#error cannot find 32-bit type
+#endif
+
+/*
+ ********* define floating point type & constants
+ */
+/* use "#if 0" below if Float should be double;
+ use "#if 1" below if Float should be float
+ */
+#if 0
+typedef float Float;
+#define maxFloat FLT_MAX
+#define minFloat FLT_MIN
+#else
+typedef double Float;
+#define maxFloat DBL_MAX
+#define minFloat DBL_MIN
+#endif
+
+/*
+ ********* define complex type
+ */
+typedef struct {
+ Float r; /* real part */
+ Float i; /* imaginary part */
+} CPX;
+
+/*
+ ********* define boolean type
+ */
+typedef int Bool;
+#define false 0
+#define true 1
+
+/* ******Avoid function multiple definition****** */
+#define Autocorr voAWB_Autocorr
+#define Convolve voAWB_Convolve
+#define cor_h_x voAWB_cor_h_x
+#define dtx_enc_init voAWB_dtx_enc_init
+#define dtx_enc_reset voAWB_dtx_enc_reset
+#define dtx_enc_exit voAWB_dtx_enc_exit
+#define dtx_enc voAWB_dtx_enc
+#define dtx_buffer voAWB_dtx_buffer
+#define tx_dtx_handler voAWB_tx_dtx_handler
+#define G_pitch voAWB_G_pitch
+#define Isp_Az voAWB_Isp_Az
+#define Lag_window voAWB_Lag_window
+#define Log2_norm voAWB_Log2_norm
+#define Log2 voAWB_Log2
+#define Pow2 voAWB_Pow2
+#define L_Comp voAWB_L_Comp
+#define Mpy_32 voAWB_Mpy_32
+#define Mpy_32_16 voAWB_Mpy_32_16
+#define Div_32 voAWB_Div_32
+#define Pit_shrp voAWB_Pit_shrp
+#define Qisf_ns voAWB_Qisf_ns
+#define Disf_ns voAWB_Disf_ns
+#define Residu voAWB_Residu
+#define Syn_filt voAWB_Syn_filt
+#define Set_zero voAWB_Set_zero
+#define Copy voAWB_Copy
+#define voice_factor voAWB_voice_factor
+#define Syn_filt_32 voAWB_Syn_filt_32
+#define Isf_isp voAWB_Isf_isp
+#define Levinson voAWB_Levinson
+#define median5 voAWB_median5
+#define Pred_lt4 voAWB_Pred_lt4
+#define Reorder_isf voAWB_Reorder_isf
+#define Dpisf_2s_36b voAWB_Dpisf_2s_36b
+#define Dpisf_2s_46b voAWB_Dpisf_2s_46b
+#define Dot_product12 voAWB_Dot_product12
+#define mem_malloc voAWB_mem_malloc
+#define mem_free voAWB_mem_free
+/******************************************************/
+
+#endif //#define __TYPEDEFS_H__
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h b/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h
new file mode 100644
index 0000000..b733afe
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/wb_vad.h
@@ -0,0 +1,78 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-------------------------------------------------------------------*
+ * WB_VAD.H *
+ *-------------------------------------------------------------------*
+ * Functions and static memory for Voice Activity Detection. *
+ *-------------------------------------------------------------------*/
+
+#ifndef __WB_VAD_H__
+#define __WB_VAD_H__
+
+/******************************************************************************
+ * INCLUDE FILES
+ ******************************************************************************/
+#include "typedef.h"
+#include "wb_vad_c.h"
+#include "voMem.h"
+
+/******************************************************************************
+ * DEFINITION OF DATA TYPES
+ ******************************************************************************/
+
+typedef struct
+{
+ Word16 bckr_est[COMPLEN]; /* background noise estimate */
+ Word16 ave_level[COMPLEN]; /* averaged input components for stationary */
+ /* estimation */
+ Word16 old_level[COMPLEN]; /* input levels of the previous frame */
+ Word16 sub_level[COMPLEN]; /* input levels calculated at the end of a frame (lookahead) */
+ Word16 a_data5[F_5TH_CNT][2]; /* memory for the filter bank */
+ Word16 a_data3[F_3TH_CNT]; /* memory for the filter bank */
+
+ Word16 burst_count; /* counts length of a speech burst */
+ Word16 hang_count; /* hangover counter */
+ Word16 stat_count; /* stationary counter */
+
+ /* Note that each of the following two variables holds 15 flags. Each flag reserves 1 bit of the
+ * variable. The newest flag is in the bit 15 (assuming that LSB is bit 1 and MSB is bit 16). */
+ Word16 vadreg; /* flags for intermediate VAD decisions */
+ Word16 tone_flag; /* tone detection flags */
+
+ Word16 sp_est_cnt; /* counter for speech level estimation */
+ Word16 sp_max; /* maximum level */
+ Word16 sp_max_cnt; /* counts frames that contains speech */
+ Word16 speech_level; /* estimated speech level */
+ Word32 prev_pow_sum; /* power of previous frame */
+
+} VadVars;
+
+/********************************************************************************
+ *
+ * DECLARATION OF PROTOTYPES
+ ********************************************************************************/
+
+Word16 wb_vad_init(VadVars ** st, VO_MEM_OPERATOR *pMemOP);
+Word16 wb_vad_reset(VadVars * st);
+void wb_vad_exit(VadVars ** st, VO_MEM_OPERATOR *pMemOP);
+void wb_vad_tone_detection(VadVars * st, Word16 p_gain);
+Word16 wb_vad(VadVars * st, Word16 in_buf[]);
+
+#endif //__WB_VAD_H__
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h b/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h
new file mode 100644
index 0000000..39ef506
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/inc/wb_vad_c.h
@@ -0,0 +1,109 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+
+/*-------------------------------------------------------------------*
+ * WB_VAD_C.H *
+ *-------------------------------------------------------------------*
+ * Constants for Voice Activity Detection. *
+ *-------------------------------------------------------------------*/
+
+#ifndef __WB_VAD_C_H__
+#define __WB_VAD_C_H__
+
+#define FRAME_LEN 256 /* Length (samples) of the input frame */
+#define COMPLEN 12 /* Number of sub-bands used by VAD */
+
+#define UNIRSHFT 7 /* = log2(MAX_16/UNITY), UNITY = 256 */
+#define SCALE 128 /* (UNITY*UNITY)/512 */
+
+#define TONE_THR (Word16)(0.65*MAX_16) /* Threshold for tone detection */
+
+/* constants for speech level estimation */
+#define SP_EST_COUNT 80
+#define SP_ACTIVITY_COUNT 25
+#define ALPHA_SP_UP (Word16)((1.0 - 0.85)*MAX_16)
+#define ALPHA_SP_DOWN (Word16)((1.0 - 0.85)*MAX_16)
+
+#define NOM_LEVEL 2050 /* about -26 dBov Q15 */
+#define SPEECH_LEVEL_INIT NOM_LEVEL /* initial speech level */
+#define MIN_SPEECH_LEVEL1 (Word16)(NOM_LEVEL * 0.063) /* NOM_LEVEL -24 dB */
+#define MIN_SPEECH_LEVEL2 (Word16)(NOM_LEVEL * 0.2) /* NOM_LEVEL -14 dB */
+#define MIN_SPEECH_SNR 4096 /* 0 dB, lowest SNR estimation, Q12 */
+
+/* Time constants for background spectrum update */
+#define ALPHA_UP1 (Word16)((1.0 - 0.95)*MAX_16) /* Normal update, upwards: */
+#define ALPHA_DOWN1 (Word16)((1.0 - 0.936)*MAX_16) /* Normal update, downwards */
+#define ALPHA_UP2 (Word16)((1.0 - 0.985)*MAX_16) /* Forced update, upwards */
+#define ALPHA_DOWN2 (Word16)((1.0 - 0.943)*MAX_16) /* Forced update, downwards */
+#define ALPHA3 (Word16)((1.0 - 0.95)*MAX_16) /* Update downwards */
+#define ALPHA4 (Word16)((1.0 - 0.9)*MAX_16) /* For stationary estimation */
+#define ALPHA5 (Word16)((1.0 - 0.5)*MAX_16) /* For stationary estimation */
+
+/* Constants for VAD threshold */
+#define THR_MIN (Word16)(1.6*SCALE) /* Minimum threshold */
+#define THR_HIGH (Word16)(6*SCALE) /* Highest threshold */
+#define THR_LOW (Word16)(1.7*SCALE) /* Lowest threshold */
+#define NO_P1 31744 /* ilog2(1), Noise level for highest threshold */
+#define NO_P2 19786 /* ilog2(0.1*MAX_16), Noise level for lowest threshold */
+#define NO_SLOPE (Word16)(MAX_16*(float)(THR_LOW-THR_HIGH)/(float)(NO_P2-NO_P1))
+
+#define SP_CH_MIN (Word16)(-0.75*SCALE)
+#define SP_CH_MAX (Word16)(0.75*SCALE)
+#define SP_P1 22527 /* ilog2(NOM_LEVEL/4) */
+#define SP_P2 17832 /* ilog2(NOM_LEVEL*4) */
+#define SP_SLOPE (Word16)(MAX_16*(float)(SP_CH_MAX-SP_CH_MIN)/(float)(SP_P2-SP_P1))
+
+/* Constants for hangover length */
+#define HANG_HIGH 12 /* longest hangover */
+#define HANG_LOW 2 /* shortest hangover */
+#define HANG_P1 THR_LOW /* threshold for longest hangover */
+#define HANG_P2 (Word16)(4*SCALE) /* threshold for shortest hangover */
+#define HANG_SLOPE (Word16)(MAX_16*(float)(HANG_LOW-HANG_HIGH)/(float)(HANG_P2-HANG_P1))
+
+/* Constants for burst length */
+#define BURST_HIGH 8 /* longest burst length */
+#define BURST_LOW 3 /* shortest burst length */
+#define BURST_P1 THR_HIGH /* threshold for longest burst */
+#define BURST_P2 THR_LOW /* threshold for shortest burst */
+#define BURST_SLOPE (Word16)(MAX_16*(float)(BURST_LOW-BURST_HIGH)/(float)(BURST_P2-BURST_P1))
+
+/* Parameters for background spectrum recovery function */
+#define STAT_COUNT 20 /* threshold of stationary detection counter */
+
+#define STAT_THR_LEVEL 184 /* Threshold level for stationarity detection */
+#define STAT_THR 1000 /* Threshold for stationarity detection */
+
+/* Limits for background noise estimate */
+#define NOISE_MIN 40 /* minimum */
+#define NOISE_MAX 20000 /* maximum */
+#define NOISE_INIT 150 /* initial */
+
+/* Thresholds for signal power (now calculated on 2 frames) */
+#define VAD_POW_LOW (Word32)30000L /* If input power is lower than this, VAD is set to 0 */
+#define POW_TONE_THR (Word32)686080L /* If input power is lower,tone detection flag is ignored */
+
+/* Constants for the filter bank */
+#define COEFF3 13363 /* coefficient for the 3rd order filter */
+#define COEFF5_1 21955 /* 1st coefficient the for 5th order filter */
+#define COEFF5_2 6390 /* 2nd coefficient the for 5th order filter */
+#define F_5TH_CNT 5 /* number of 5th order filters */
+#define F_3TH_CNT 6 /* number of 3th order filters */
+
+#endif //__WB_VAD_C_H__
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt b/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt
new file mode 100644
index 0000000..b4bf11d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/patent_disclaimer.txt
@@ -0,0 +1,9 @@
+
+THIS IS NOT A GRANT OF PATENT RIGHTS.
+
+Google makes no representation or warranty that the codecs for which
+source code is made available hereunder are unencumbered by
+third-party patents. Those intending to use this source code in
+hardware or software products are advised that implementations of
+these codecs, including in open source software or shareware, may
+require patent licenses from the relevant patent holders.
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s
new file mode 100644
index 0000000..0eb5e9f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Deemph_32_opt.s
@@ -0,0 +1,104 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+
+@void Deemph_32(
+@ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+@ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+@ Word16 y[], /* (o) : output signal (x16) */
+@ Word16 mu, /* (i) Q15 : deemphasis factor */
+@ Word16 L, /* (i) : vector size */
+@ Word16 * mem /* (i/o) : memory (y[-1]) */
+@ )
+
+@x_hi RN R0
+@x_lo RN R1
+@y[] RN R2
+@*mem RN R3
+
+ .section .text
+ .global Deemph_32_asm
+
+Deemph_32_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ MOV r4, #2 @i=0
+ LDRSH r6, [r0], #2 @load x_hi[0]
+ LDRSH r7, [r1], #2 @load x_lo[0]
+ LDR r5, =22282 @r5---mu
+ MOV r11, #0x8000
+
+ @y[0]
+ MOV r10, r6, LSL #16 @L_tmp = x_hi[0]<<16
+ MOV r8, r5, ASR #1 @fac = mu >> 1
+ LDR r5, [r3]
+ ADD r12, r10, r7, LSL #4 @L_tmp += x_lo[0] << 4
+ MOV r10, r12, LSL #3 @L_tmp <<= 3
+ MUL r9, r5, r8
+ LDRSH r6, [r0], #2 @load x_hi[1]
+ QDADD r10, r10, r9
+ LDRSH r7, [r1], #2 @load x_lo[1]
+ MOV r12, r10, LSL #1 @L_tmp = L_mac(L_tmp, *mem, fac)
+ QADD r10, r12, r11
+ MOV r14, r10, ASR #16 @y[0] = round(L_tmp)
+
+
+ MOV r10, r6, LSL #16
+ ADD r12, r10, r7, LSL #4
+ STRH r14, [r2], #2 @update y[0]
+ MOV r10, r12, LSL #3
+ MUL r9, r14, r8
+ QDADD r10, r10, r9
+ MOV r12, r10, LSL #1
+ QADD r10, r12, r11
+ MOV r14, r10, ASR #16 @y[1] = round(L_tmp)
+
+LOOP:
+ LDRSH r6, [r0], #2 @load x_hi[]
+ LDRSH r7, [r1], #2
+ STRH r14, [r2], #2
+ MOV r10, r6, LSL #16
+ ADD r12, r10, r7, LSL #4
+ MUL r9, r14, r8
+ MOV r10, r12, LSL #3
+ QDADD r10, r10, r9
+ LDRSH r6, [r0], #2 @load x_hi[]
+ MOV r12, r10, LSL #1
+ QADD r10, r12, r11
+ LDRSH r7, [r1], #2
+ MOV r14, r10, ASR #16
+
+ MOV r10, r6, LSL #16
+ ADD r12, r10, r7, LSL #4
+ STRH r14, [r2], #2
+ MUL r9, r14, r8
+ MOV r10, r12, LSL #3
+ QDADD r10, r10, r9
+ ADD r4, r4, #2
+ MOV r12, r10, LSL #1
+ QADD r10, r12, r11
+ CMP r4, #64
+ MOV r14, r10, ASR #16
+
+ BLT LOOP
+ STR r14, [r3]
+ STRH r14, [r2]
+
+ LDMFD r13!, {r4 - r12, r15}
+
+ @ENDP
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s
new file mode 100644
index 0000000..0383269
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Dot_p_opt.s
@@ -0,0 +1,80 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+@ Word16 x[], /* (i) 12bits: x vector */
+@ Word16 y[], /* (i) 12bits: y vector */
+@ Word16 lg, /* (i) : vector length */
+@ Word16 * exp /* (o) : exponent of result (0..+30) */
+@)
+@****************************************************************
+@ x[] --- r0
+@ y[] --- r1
+@ lg --- r2
+@ *exp --- r3
+
+ .section .text
+ .global Dot_product12_asm
+
+Dot_product12_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ MOV r4, #0 @ L_sum = 0
+ MOV r5, #0 @ i = 0
+
+LOOP:
+ LDR r6, [r0], #4
+ LDR r7, [r1], #4
+ LDR r8, [r0], #4
+ SMLABB r4, r6, r7, r4
+ LDR r9, [r1], #4
+ SMLATT r4, r6, r7, r4
+
+ LDR r6, [r0], #4
+ SMLABB r4, r8, r9, r4
+
+ LDR r7, [r1], #4
+ SMLATT r4, r8, r9, r4
+ LDR r8, [r0], #4
+
+ SMLABB r4, r6, r7, r4
+ LDR r9, [r1], #4
+ SMLATT r4, r6, r7, r4
+ ADD r5, r5, #8
+ SMLABB r4, r8, r9, r4
+ CMP r5, r2
+ SMLATT r4, r8, r9, r4
+ BLT LOOP
+
+ MOV r12, r4, LSL #1
+ ADD r12, r12, #1 @ L_sum = (L_sum << 1) + 1
+ MOV r4, r12
+
+ CMP r12, #0
+ RSBLT r4, r12, #0
+ CLZ r10, r4
+ SUB r10, r10, #1 @ sft = norm_l(L_sum)
+ MOV r0, r12, LSL r10 @ L_sum = L_sum << sft
+ RSB r11, r10, #30 @ *exp = 30 - sft
+ STRH r11, [r3]
+
+Dot_product12_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
new file mode 100644
index 0000000..e6ebd73
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Filt_6k_7k_opt.s
@@ -0,0 +1,185 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+
+@**********************************************************************/
+@void Filt_6k_7k(
+@ Word16 signal[], /* input: signal */
+@ Word16 lg, /* input: length of input */
+@ Word16 mem[] /* in/out: memory (size=30) */
+@)
+@******************************************************************
+@ r0 --- signal[]
+@ r1 --- lg
+@ r2 --- mem[]
+
+ .section .text
+ .global Filt_6k_7k_asm
+ .extern voAWB_Copy
+ .extern fir_6k_7k
+
+Filt_6k_7k_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r13, r13, #240 @ x[L_SUBFR16k + (L_FIR - 1)]
+ MOV r8, r0 @ copy signal[] address
+ MOV r4, r1 @ copy lg address
+ MOV r5, r2 @ copy mem[] address
+
+ MOV r1, r13
+ MOV r0, r2
+ MOV r2, #30 @ L_FIR - 1
+ BL voAWB_Copy @ memcpy(x, mem, (L_FIR - 1)<<1)
+
+ LDR r10, Lable1 @ get fir_7k address
+
+ MOV r14, #0
+ MOV r3, r8 @ change myMemCopy to Copy, due to Copy will change r3 content
+ ADD r6, r13, #60 @ get x[L_FIR - 1] address
+ MOV r7, r3 @ get signal[i]
+LOOP1:
+ LDRSH r8, [r7], #2
+ LDRSH r9, [r7], #2
+ MOV r8, r8, ASR #2
+ MOV r9, r9, ASR #2
+ LDRSH r11, [r7], #2
+ LDRSH r12, [r7], #2
+ MOV r11, r11, ASR #2
+ MOV r12, r12, ASR #2
+ STRH r8, [r6], #2
+ STRH r9, [r6], #2
+ STRH r11, [r6], #2
+ STRH r12, [r6], #2
+ LDRSH r8, [r7], #2
+ LDRSH r9, [r7], #2
+ MOV r8, r8, ASR #2
+ MOV r9, r9, ASR #2
+ LDRSH r11, [r7], #2
+ LDRSH r12, [r7], #2
+ MOV r11, r11, ASR #2
+ MOV r12, r12, ASR #2
+ STRH r8, [r6], #2
+ STRH r9, [r6], #2
+ STRH r11, [r6], #2
+ STRH r12, [r6], #2
+ ADD r14, r14, #8
+ CMP r14, #80
+ BLT LOOP1
+
+
+ STR r5, [sp, #-4] @ PUSH r5 to stack
+
+ @ not use registers: r4, r10, r12, r14, r5
+ MOV r4, r13
+ MOV r5, #0 @ i = 0
+LOOP2:
+ LDR r0, [r10]
+
+ LDRSH r1, [r4] @ load x[i]
+ LDRSH r2, [r4, #60] @ load x[i + 30]
+ LDRSH r6, [r4, #2] @ load x[i + 1]
+ LDRSH r7, [r4, #58] @ load x[i + 29]
+ ADD r1, r1, r2 @ x[i] + x[i + 30]
+ ADD r6, r6, r7 @ x[i + 1] + x[i + 29]
+ LDRSH r8, [r4, #4] @ load x[i + 2]
+ LDRSH r9, [r4, #56] @ load x[i + 28]
+
+ SMULBB r14, r1, r0 @ (x[i] + x[i + 30]) * fir_7k[0]
+ ADD r8, r8, r9 @ x[i + 2] + x[i + 28]
+ SMLABT r14, r6, r0, r14 @ (x[i + 1] + x[i + 29]) * fir_7k[1]
+
+ LDR r0, [r10, #4]
+ LDRSH r1, [r4, #6] @ load x[i+3]
+ LDRSH r2, [r4, #54] @ load x[i+27]
+ LDRSH r6, [r4, #8] @ load x[i+4]
+ LDRSH r7, [r4, #52] @ load x[i+26]
+ ADD r1, r1, r2 @ x[i+3] + x[i+27]
+ ADD r6, r6, r7 @ x[i+4] + x[i+26]
+ SMLABB r14, r8, r0, r14 @ (x[i + 2] + x[i + 28]) * fir_7k[2]
+ LDRSH r8, [r4, #10] @ load x[i+5]
+ LDRSH r9, [r4, #50] @ load x[i+25]
+ SMLABT r14, r1, r0, r14 @ (x[i+3] + x[i+27]) * fir_7k[3]
+ ADD r8, r8, r9 @ x[i+5] + x[i+25]
+
+ LDR r0, [r10, #8]
+ LDRSH r1, [r4, #12] @ x[i+6]
+ LDRSH r2, [r4, #48] @ x[i+24]
+ SMLABB r14, r6, r0, r14 @ (x[i+4] + x[i+26]) * fir_7k[4]
+ LDRSH r6, [r4, #14] @ x[i+7]
+ LDRSH r7, [r4, #46] @ x[i+23]
+ SMLABT r14, r8, r0, r14 @ (x[i+5] + x[i+25]) * fir_7k[5]
+ LDR r0, [r10, #12]
+ ADD r1, r1, r2 @ (x[i+6] + x[i+24])
+ ADD r6, r6, r7 @ (x[i+7] + x[i+23])
+ SMLABB r14, r1, r0, r14 @ (x[i+6] + x[i+24]) * fir_7k[6]
+ LDRSH r8, [r4, #16] @ x[i+8]
+ LDRSH r9, [r4, #44] @ x[i+22]
+ SMLABT r14, r6, r0, r14 @ (x[i+7] + x[i+23]) * fir_7k[7]
+ LDR r0, [r10, #16]
+ LDRSH r1, [r4, #18] @ x[i+9]
+ LDRSH r2, [r4, #42] @ x[i+21]
+ LDRSH r6, [r4, #20] @ x[i+10]
+ LDRSH r7, [r4, #40] @ x[i+20]
+ ADD r8, r8, r9 @ (x[i+8] + x[i+22])
+ ADD r1, r1, r2 @ (x[i+9] + x[i+21])
+ ADD r6, r6, r7 @ (x[i+10] + x[i+20])
+ SMLABB r14, r8, r0, r14 @ (x[i+8] + x[i+22]) * fir_7k[8]
+ LDRSH r8, [r4, #22] @ x[i+11]
+ LDRSH r9, [r4, #38] @ x[i+19]
+ SMLABT r14, r1, r0, r14 @ (x[i+9] + x[i+21]) * fir_7k[9]
+ LDR r0, [r10, #20]
+ LDRSH r1, [r4, #24] @ x[i+12]
+ LDRSH r2, [r4, #36] @ x[i+18]
+ SMLABB r14, r6, r0, r14 @ (x[i+10] + x[i+20]) * fir_7k[10]
+ LDRSH r6, [r4, #26] @ x[i+13]
+ ADD r8, r8, r9 @ (x[i+11] + x[i+19])
+ LDRSH r7, [r4, #34] @ x[i+17]
+ SMLABT r14, r8, r0, r14 @ (x[i+11] + x[i+19]) * fir_7k[11]
+ LDR r0, [r10, #24]
+ ADD r1, r1, r2 @ x[i+12] + x[i+18]
+ LDRSH r8, [r4, #28] @ x[i+14]
+ SMLABB r14, r1, r0, r14 @ (x[i+12] + x[i+18]) * fir_7k[12]
+ ADD r6, r6, r7 @ (x[i+13] + x[i+17])
+ LDRSH r9, [r4, #32] @ x[i+16]
+ SMLABT r14, r6, r0, r14 @ (x[i+13] + x[i+17]) * fir_7k[13]
+ LDR r0, [r10, #28]
+ ADD r8, r8, r9 @ (x[i+14] + x[i+16])
+ LDRSH r1, [r4, #30] @ x[i+15]
+ SMLABB r14, r8, r0, r14 @ (x[i+14] + x[i+16]) * fir_7k[14]
+ SMLABT r14, r1, r0, r14 @ x[i+15] * fir_7k[15]
+
+ ADD r5, r5, #1
+ ADD r14, r14, #0x4000
+ ADD r4, r4, #2
+ MOV r1, r14, ASR #15
+ CMP r5, #80
+ STRH r1, [r3], #2 @signal[i] = (L_tmp + 0x4000) >> 15
+ BLT LOOP2
+
+ LDR r1, [sp, #-4] @mem address
+ ADD r0, r13, #160 @x + lg
+ MOV r2, #30
+ BL voAWB_Copy
+
+Filt_6k_7k_end:
+ ADD r13, r13, #240
+ LDMFD r13!, {r4 - r12, r15}
+
+Lable1:
+ .word fir_6k_7k
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s
new file mode 100644
index 0000000..b440a31
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Norm_Corr_opt.s
@@ -0,0 +1,231 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+
+@static void Norm_Corr (Word16 exc[], /* (i) : excitation buffer */
+@ Word16 xn[], /* (i) : target vector */
+@ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+@ Word16 L_subfr, /* (i) : sub-frame length */
+@ Word16 t_min, /* (i) : minimum value of pitch lag. */
+@ Word16 t_max, /* (i) : maximum value of pitch lag. */
+@ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */
+@
+
+@ r0 --- exc[]
+@ r1 --- xn[]
+@ r2 --- h[]
+@ r3 --- L_subfr
+@ r4 --- t_min
+@ r5 --- t_max
+@ r6 --- corr_norm[]
+
+
+ .section .text
+ .global Norm_corr_asm
+ .extern Convolve_asm
+ .extern Isqrt_n
+@******************************
+@ constant
+@******************************
+.equ EXC , 0
+.equ XN , 4
+.equ H , 8
+.equ L_SUBFR , 12
+.equ voSTACK , 172
+.equ T_MIN , 212
+.equ T_MAX , 216
+.equ CORR_NORM , 220
+
+Norm_corr_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r13, r13, #voSTACK
+
+ ADD r8, r13, #20 @get the excf[L_SUBFR]
+ LDR r4, [r13, #T_MIN] @get t_min
+ RSB r11, r4, #0 @k = -t_min
+ ADD r5, r0, r11, LSL #1 @get the &exc[k]
+
+ @transfer Convolve function
+ STMFD sp!, {r0 - r3}
+ MOV r0, r5
+ MOV r1, r2
+ MOV r2, r8 @r2 --- excf[]
+ BL Convolve_asm
+ LDMFD sp!, {r0 - r3}
+
+ @ r8 --- excf[]
+
+ MOV r14, r1 @copy xn[] address
+ MOV r5, #64
+ MOV r6, #0 @L_tmp = 0
+ MOV r7, #1
+
+LOOP1:
+ LDR r9, [r14], #4
+ LDR r10, [r14], #4
+ LDR r11, [r14], #4
+ LDR r12, [r14], #4
+ SMLABB r6, r9, r9, r6 @L_tmp += (xn[i] * xn[i])
+ SMLATT r6, r9, r9, r6 @L_tmp += (xn[i+1] * xn[i+1])
+ SMLABB r6, r10, r10, r6
+ SMLATT r6, r10, r10, r6
+ SMLABB r6, r11, r11, r6
+ SMLATT r6, r11, r11, r6
+ SMLABB r6, r12, r12, r6
+ SMLATT r6, r12, r12, r6
+ SUBS r5, r5, #8
+ BNE LOOP1
+
+ ADD r9, r7, r6, LSL #1 @L_tmp = (L_tmp << 1) + 1
+ CLZ r7, r9
+ SUB r6, r7, #1 @exp = norm_l(L_tmp)
+ RSB r7, r6, #32 @exp = 32 - exp
+ MOV r6, r7, ASR #1
+ RSB r7, r6, #0 @scale = -(exp >> 1)
+
+ @loop for every possible period
+ @for(t = t_min@ t <= t_max@ t++)
+ @r7 --- scale r4 --- t_min r8 --- excf[]
+
+LOOPFOR:
+ MOV r5, #0 @L_tmp = 0
+ MOV r6, #0 @L_tmp1 = 0
+ MOV r9, #64
+ MOV r12, r1 @copy of xn[]
+ ADD r14, r13, #20 @copy of excf[]
+ MOV r8, #0x8000
+
+LOOPi:
+ LDR r11, [r14], #4 @load excf[i], excf[i+1]
+ LDR r10, [r12], #4 @load xn[i], xn[i+1]
+ SMLABB r6, r11, r11, r6 @L_tmp1 += excf[i] * excf[i]
+ SMLATT r6, r11, r11, r6 @L_tmp1 += excf[i+1] * excf[i+1]
+ SMLABB r5, r10, r11, r5 @L_tmp += xn[i] * excf[i]
+ SMLATT r5, r10, r11, r5 @L_tmp += xn[i+1] * excf[i+1]
+ LDR r11, [r14], #4 @load excf[i+2], excf[i+3]
+ LDR r10, [r12], #4 @load xn[i+2], xn[i+3]
+ SMLABB r6, r11, r11, r6
+ SMLATT r6, r11, r11, r6
+ SMLABB r5, r10, r11, r5
+ SMLATT r5, r10, r11, r5
+ SUBS r9, r9, #4
+ BNE LOOPi
+
+ @r5 --- L_tmp, r6 --- L_tmp1
+ MOV r10, #1
+ ADD r5, r10, r5, LSL #1 @L_tmp = (L_tmp << 1) + 1
+ ADD r6, r10, r6, LSL #1 @L_tmp1 = (L_tmp1 << 1) + 1
+
+ CLZ r10, r5
+ CMP r5, #0
+ RSBLT r11, r5, #0
+ CLZLT r10, r11
+ SUB r10, r10, #1 @exp = norm_l(L_tmp)
+
+ MOV r5, r5, LSL r10 @L_tmp = (L_tmp << exp)
+ RSB r10, r10, #30 @exp_corr = 30 - exp
+ MOV r11, r5, ASR #16 @corr = extract_h(L_tmp)
+
+ CLZ r5, r6
+ SUB r5, r5, #1
+ MOV r6, r6, LSL r5 @L_tmp = (L_tmp1 << exp)
+ RSB r5, r5, #30 @exp_norm = 30 - exp
+
+ @r10 --- exp_corr, r11 --- corr
+ @r6 --- L_tmp, r5 --- exp_norm
+
+ @Isqrt_n(&L_tmp, &exp_norm)
+
+ MOV r14, r0
+ MOV r12, r1
+
+ STMFD sp!, {r0 - r4, r7 - r12, r14}
+ ADD r1, sp, #4
+ ADD r0, sp, #0
+ STR r6, [sp]
+ STRH r5, [sp, #4]
+ BL Isqrt_n
+ LDR r6, [sp]
+ LDRSH r5, [sp, #4]
+ LDMFD sp!, {r0 - r4, r7 - r12, r14}
+ MOV r0, r14
+ MOV r1, r12
+
+
+ MOV r6, r6, ASR #16 @norm = extract_h(L_tmp)
+ MUL r12, r6, r11
+ ADD r12, r12, r12 @L_tmp = vo_L_mult(corr, norm)
+
+ ADD r6, r10, r5
+ ADD r6, r6, r7 @exp_corr + exp_norm + scale
+
+ CMP r6, #0
+ RSBLT r6, r6, #0
+ MOVLT r12, r12, ASR r6
+ MOVGT r12, r12, LSL r6 @L_tmp = L_shl(L_tmp, exp_corr + exp_norm + scale)
+
+ ADD r12, r12, r8
+ MOV r12, r12, ASR #16 @vo_round(L_tmp)
+
+ LDR r5, [r13, #CORR_NORM] @ get corr_norm address
+ LDR r6, [r13, #T_MAX] @ get t_max
+ ADD r10, r5, r4, LSL #1 @ get corr_norm[t] address
+ STRH r12, [r10] @ corr_norm[t] = vo_round(L_tmp)
+
+ CMP r4, r6
+ BEQ Norm_corr_asm_end
+
+ ADD r4, r4, #1 @ t_min ++
+
+ RSB r5, r4, #0 @ k
+
+ MOV r6, #63 @ i = 63
+ MOV r8, r0 @ exc[]
+ MOV r9, r2 @ h[]
+ ADD r10, r13, #20 @ excf[]
+
+ ADD r8, r8, r5, LSL #1 @ exc[k] address
+ ADD r9, r9, r6, LSL #1 @ h[i] address
+ ADD r10, r10, r6, LSL #1 @ excf[i] address
+ LDRSH r11, [r8] @ tmp = exc[k]
+
+LOOPK:
+ LDRSH r8, [r9], #-2 @ load h[i]
+ LDRSH r12, [r10, #-2] @ load excf[i - 1]
+ MUL r14, r11, r8
+ MOV r8, r14, ASR #15
+ ADD r14, r8, r12
+ STRH r14, [r10], #-2
+ SUBS r6, r6, #1
+ BGT LOOPK
+
+ LDRSH r8, [r9] @ load h[0]
+ MUL r14, r11, r8
+ LDR r6, [r13, #T_MAX] @ get t_max
+ MOV r8, r14, ASR #15
+ STRH r8, [r10]
+
+ CMP r4, r6
+ BLE LOOPFOR
+
+Norm_corr_asm_end:
+
+ ADD r13, r13, #voSTACK
+ LDMFD r13!, {r4 - r12, r15}
+
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s
new file mode 100644
index 0000000..6416634
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/Syn_filt_32_opt.s
@@ -0,0 +1,226 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Syn_filt_32(
+@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+@ Word16 m, /* (i) : order of LP filter */
+@ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+@ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+@ Word16 sig_hi[], /* (o) /16 : synthesis high */
+@ Word16 sig_lo[], /* (o) /16 : synthesis low */
+@ Word16 lg /* (i) : size of filtering */
+@)
+@***************************************************************
+@
+@ a[] --- r0
+@ m --- r1
+@ exc[] --- r2
+@ Qnew --- r3
+@ sig_hi[] --- r4
+@ sig_lo[] --- r5
+@ lg --- r6
+
+ .section .text
+ .global Syn_filt_32_asm
+
+Syn_filt_32_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ LDR r4, [r13, #40] @ get sig_hi[] address
+ LDR r5, [r13, #44] @ get sig_lo[] address
+
+ LDRSH r6, [r0] @ load Aq[0]
+ ADD r7, r3, #4 @ 4 + Q_new
+ MOV r3, r6, ASR r7 @ a0 = Aq[0] >> (4 + Q_new)
+
+ LDR r14, =0xffff
+ LDRSH r6, [r0, #2] @ load Aq[1]
+ LDRSH r7, [r0, #4] @ load Aq[2]
+ LDRSH r8, [r0, #6] @ load Aq[3]
+ LDRSH r9, [r0, #8] @ load Aq[4]
+ AND r6, r6, r14
+ AND r8, r8, r14
+ ORR r10, r6, r7, LSL #16 @ Aq[2] -- Aq[1]
+ ORR r11, r8, r9, LSL #16 @ Aq[4] -- Aq[3]
+ STR r10, [r13, #-4]
+ STR r11, [r13, #-8]
+
+ LDRSH r6, [r0, #10] @ load Aq[5]
+ LDRSH r7, [r0, #12] @ load Aq[6]
+ LDRSH r8, [r0, #14] @ load Aq[7]
+ LDRSH r9, [r0, #16] @ load Aq[8]
+ AND r6, r6, r14
+ AND r8, r8, r14
+ ORR r10, r6, r7, LSL #16 @ Aq[6] -- Aq[5]
+ ORR r11, r8, r9, LSL #16 @ Aq[8] -- Aq[7]
+ STR r10, [r13, #-12]
+ STR r11, [r13, #-16]
+
+ LDRSH r6, [r0, #18] @ load Aq[9]
+ LDRSH r7, [r0, #20] @ load Aq[10]
+ LDRSH r8, [r0, #22] @ load Aq[11]
+ LDRSH r9, [r0, #24] @ load Aq[12]
+ AND r6, r6, r14
+ AND r8, r8, r14
+ ORR r10, r6, r7, LSL #16 @ Aq[10] -- Aq[9]
+ ORR r11, r8, r9, LSL #16 @ Aq[12] -- Aq[11]
+ STR r10, [r13, #-20]
+ STR r11, [r13, #-24]
+
+ LDRSH r6, [r0, #26] @ load Aq[13]
+ LDRSH r7, [r0, #28] @ load Aq[14]
+ LDRSH r8, [r0, #30] @ load Aq[15]
+ LDRSH r9, [r0, #32] @ load Aq[16]
+ AND r6, r6, r14
+ AND r8, r8, r14
+ ORR r10, r6, r7, LSL #16 @ Aq[14] -- Aq[13]
+ ORR r11, r8, r9, LSL #16 @ Aq[16] -- Aq[15]
+ STR r10, [r13, #-28]
+ STR r11, [r13, #-32]
+
+ MOV r8, #0 @ i = 0
+
+LOOP:
+ LDRSH r6, [r5, #-2] @ load sig_lo[i-1]
+ LDRSH r7, [r5, #-4] @ load sig_lo[i-2]
+
+ LDR r11, [r13, #-4] @ Aq[2] -- Aq[1]
+ LDRSH r9, [r5, #-6] @ load sig_lo[i-3]
+ LDRSH r10, [r5, #-8] @ load sig_lo[i-4]
+
+ SMULBB r12, r6, r11 @ sig_lo[i-1] * Aq[1]
+
+ LDRSH r6, [r5, #-10] @ load sig_lo[i-5]
+ SMLABT r12, r7, r11, r12 @ sig_lo[i-2] * Aq[2]
+ LDR r11, [r13, #-8] @ Aq[4] -- Aq[3]
+ LDRSH r7, [r5, #-12] @ load sig_lo[i-6]
+ SMLABB r12, r9, r11, r12 @ sig_lo[i-3] * Aq[3]
+ LDRSH r9, [r5, #-14] @ load sig_lo[i-7]
+ SMLABT r12, r10, r11, r12 @ sig_lo[i-4] * Aq[4]
+ LDR r11, [r13, #-12] @ Aq[6] -- Aq[5]
+ LDRSH r10, [r5, #-16] @ load sig_lo[i-8]
+ SMLABB r12, r6, r11, r12 @ sig_lo[i-5] * Aq[5]
+ LDRSH r6, [r5, #-18] @ load sig_lo[i-9]
+ SMLABT r12, r7, r11, r12 @ sig_lo[i-6] * Aq[6]
+ LDR r11, [r13, #-16] @ Aq[8] -- Aq[7]
+ LDRSH r7, [r5, #-20] @ load sig_lo[i-10]
+ SMLABB r12, r9, r11, r12 @ sig_lo[i-7] * Aq[7]
+ LDRSH r9, [r5, #-22] @ load sig_lo[i-11]
+ SMLABT r12, r10, r11, r12 @ sig_lo[i-8] * Aq[8]
+ LDR r11, [r13, #-20] @ Aq[10] -- Aq[9]
+ LDRSH r10,[r5, #-24] @ load sig_lo[i-12]
+ SMLABB r12, r6, r11, r12 @ sig_lo[i-9] * Aq[9]
+ LDRSH r6, [r5, #-26] @ load sig_lo[i-13]
+ SMLABT r12, r7, r11, r12 @ sig_lo[i-10] * Aq[10]
+ LDR r11, [r13, #-24] @ Aq[12] -- Aq[11]
+ LDRSH r7, [r5, #-28] @ load sig_lo[i-14]
+ SMLABB r12, r9, r11, r12 @ sig_lo[i-11] * Aq[11]
+ LDRSH r9, [r5, #-30] @ load sig_lo[i-15]
+ SMLABT r12, r10, r11, r12 @ sig_lo[i-12] * Aq[12]
+
+ LDR r11, [r13, #-28] @ Aq[14] -- Aq[13]
+ LDRSH r10, [r5, #-32] @ load sig_lo[i-16]
+ SMLABB r12, r6, r11, r12 @ sig_lo[i-13] * Aq[13]
+ SMLABT r12, r7, r11, r12 @ sig_lo[i-14] * Aq[14]
+
+ LDR r11, [r13, #-32] @ Aq[16] -- Aq[15]
+ LDRSH r6, [r2],#2 @ load exc[i]
+ SMLABB r12, r9, r11, r12 @ sig_lo[i-15] * Aq[15]
+ SMLABT r12, r10, r11, r12 @ sig_lo[i-16] * Aq[16]
+ MUL r7, r6, r3 @ exc[i] * a0
+ RSB r14, r12, #0 @ L_tmp
+ MOV r14, r14, ASR #11 @ L_tmp >>= 11
+ ADD r14, r14, r7, LSL #1 @ L_tmp += (exc[i] * a0) << 1
+
+
+ LDRSH r6, [r4, #-2] @ load sig_hi[i-1]
+ LDRSH r7, [r4, #-4] @ load sig_hi[i-2]
+
+ LDR r11, [r13, #-4] @ Aq[2] -- Aq[1]
+ LDRSH r9, [r4, #-6] @ load sig_hi[i-3]
+ LDRSH r10, [r4, #-8] @ load sig_hi[i-4]
+ SMULBB r12, r6, r11 @ sig_hi[i-1] * Aq[1]
+ LDRSH r6, [r4, #-10] @ load sig_hi[i-5]
+ SMLABT r12, r7, r11, r12 @ sig_hi[i-2] * Aq[2]
+
+ LDR r11, [r13, #-8] @ Aq[4] -- Aq[3]
+ LDRSH r7, [r4, #-12] @ load sig_hi[i-6]
+
+ SMLABB r12, r9, r11, r12 @ sig_hi[i-3] * Aq[3]
+ LDRSH r9, [r4, #-14] @ load sig_hi[i-7]
+
+ SMLABT r12, r10, r11, r12 @ sig_hi[i-4] * Aq[4]
+
+ LDR r11, [r13, #-12] @ Aq[6] -- Aq[5]
+ LDRSH r10, [r4, #-16] @ load sig_hi[i-8]
+
+ SMLABB r12, r6, r11, r12 @ sig_hi[i-5] * Aq[5]
+
+ LDRSH r6, [r4, #-18] @ load sig_hi[i-9]
+ SMLABT r12, r7, r11, r12 @ sig_hi[i-6] * Aq[6]
+
+ LDR r11, [r13, #-16] @ Aq[8] -- Aq[7]
+ LDRSH r7, [r4, #-20] @ load sig_hi[i-10]
+
+ SMLABB r12, r9, r11, r12 @ sig_hi[i-7] * Aq[7]
+
+ LDRSH r9, [r4, #-22] @ load sig_hi[i-11]
+
+ SMLABT r12, r10, r11, r12 @ sig_hi[i-8] * Aq[8]
+
+ LDR r11, [r13, #-20] @ Aq[10] -- Aq[9]
+ LDRSH r10,[r4, #-24] @ load sig_hi[i-12]
+
+ SMLABB r12, r6, r11, r12 @ sig_hi[i-9] * Aq[9]
+ LDRSH r6, [r4, #-26] @ load sig_hi[i-13]
+ SMLABT r12, r7, r11, r12 @ sig_hi[i-10] * Aq[10]
+
+ LDR r11, [r13, #-24] @ Aq[12] -- Aq[11]
+ LDRSH r7, [r4, #-28] @ load sig_hi[i-14]
+ SMLABB r12, r9, r11, r12 @ sig_hi[i-11] * Aq[11]
+ LDRSH r9, [r4, #-30] @ load sig_hi[i-15]
+ SMLABT r12, r10, r11, r12 @ sig_hi[i-12] * Aq[12]
+
+ LDR r11, [r13, #-28] @ Aq[14] -- Aq[13]
+ LDRSH r10, [r4, #-32] @ load sig_hi[i-16]
+ SMLABB r12, r6, r11, r12 @ sig_hi[i-13] * Aq[13]
+ SMLABT r12, r7, r11, r12 @ sig_hi[i-14] * Aq[14]
+
+ LDR r11, [r13, #-32] @ Aq[16] -- Aq[15]
+ SMLABB r12, r9, r11, r12 @ sig_hi[i-15] * Aq[15]
+ SMLABT r12, r10, r11, r12 @ sig_hi[i-16] * Aq[16]
+ ADD r6, r12, r12 @ r12 << 1
+ SUB r14, r14, r6
+ MOV r14, r14, LSL #3 @ L_tmp <<=3
+
+ MOV r7, r14, ASR #16 @ L_tmp >> 16
+
+ MOV r14, r14, ASR #4 @ L_tmp >>=4
+ STRH r7, [r4], #2 @ sig_hi[i] = L_tmp >> 16
+ SUB r9, r14, r7, LSL #12 @ sig_lo[i] = L_tmp - (sig_hi[i] << 12)
+
+ ADD r8, r8, #1
+ STRH r9, [r5], #2
+ CMP r8, #64
+ BLT LOOP
+
+Syn_filt_32_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s
new file mode 100644
index 0000000..0228bda
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/convolve_opt.s
@@ -0,0 +1,186 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+
+
+@*void Convolve (
+@* Word16 x[], /* (i) : input vector */
+@* Word16 h[], /* (i) : impulse response */
+@* Word16 y[], /* (o) : output vector */
+@* Word16 L /* (i) : vector size */
+@*)
+@ r0 --- x[]
+@ r1 --- h[]
+@ r2 --- y[]
+@ r3 --- L
+
+ .section .text
+ .global Convolve_asm
+
+Convolve_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ MOV r3, #0 @ n
+ MOV r11, #0x8000
+
+LOOP:
+ ADD r4, r1, r3, LSL #1 @ tmpH address
+ ADD r5, r3, #1 @ i = n + 1
+ MOV r6, r0 @ tmpX = x
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ SUB r5, r5, #1
+ MUL r8, r9, r10
+
+LOOP1:
+ CMP r5, #0
+ BLE L1
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ MLA r8, r12, r14, r8
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ SUBS r5, r5, #4
+ MLA r8, r12, r14, r8
+
+ B LOOP1
+
+L1:
+
+ ADD r5, r11, r8, LSL #1
+ MOV r5, r5, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r5, [r2], #2 @y[n]
+
+
+ ADD r4, r1, r3, LSL #1 @tmpH address
+ ADD r5, r3, #1
+ MOV r6, r0
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2
+ LDRSH r12, [r6], #2
+ LDRSH r14, [r4], #-2
+
+ MUL r8, r9, r10
+ SUB r5, r5, #2
+ MLA r8, r12, r14, r8
+
+LOOP2:
+ CMP r5, #0
+ BLE L2
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ MLA r8, r12, r14, r8
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ SUBS r5, r5, #4
+ MLA r8, r12, r14, r8
+ B LOOP2
+
+L2:
+ ADD r8, r11, r8, LSL #1
+ MOV r8, r8, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r8, [r2], #2 @y[n]
+
+ ADD r4, r1, r3, LSL #1
+ ADD r5, r3, #1
+ MOV r6, r0
+ LDRSH r9, [r6], #2
+ LDRSH r10, [r4], #-2
+ LDRSH r12, [r6], #2
+ LDRSH r14, [r4], #-2
+ MUL r8, r9, r10
+ LDRSH r9, [r6], #2
+ LDRSH r10, [r4], #-2
+ MLA r8, r12, r14, r8
+ SUB r5, r5, #3
+ MLA r8, r9, r10, r8
+
+LOOP3:
+ CMP r5, #0
+ BLE L3
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ MLA r8, r12, r14, r8
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ SUBS r5, r5, #4
+ MLA r8, r12, r14, r8
+ B LOOP3
+
+L3:
+ ADD r8, r11, r8, LSL #1
+ MOV r8, r8, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r8, [r2], #2 @y[n]
+
+ ADD r5, r3, #1 @ i = n + 1
+ ADD r4, r1, r3, LSL #1 @ tmpH address
+ MOV r6, r0
+ MOV r8, #0
+
+LOOP4:
+ CMP r5, #0
+ BLE L4
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ MLA r8, r12, r14, r8
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2 @ *tmpH--
+ LDRSH r12, [r6], #2 @ *tmpX++
+ LDRSH r14, [r4], #-2 @ *tmpH--
+ MLA r8, r9, r10, r8
+ SUBS r5, r5, #4
+ MLA r8, r12, r14, r8
+ B LOOP4
+L4:
+ ADD r5, r11, r8, LSL #1
+ MOV r5, r5, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r5, [r2], #2 @y[n]
+
+ CMP r3, #64
+ BLT LOOP
+
+Convolve_asm_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s
new file mode 100644
index 0000000..441b984
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/cor_h_vec_opt.s
@@ -0,0 +1,151 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@static void cor_h_vec_012(
+@ Word16 h[], /* (i) scaled impulse response */
+@ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+@ Word16 track, /* (i) track to use */
+@ Word16 sign[], /* (i) sign vector */
+@ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+@ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+@ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+@)
+@r0 ---- h[]
+@r1 ---- vec[]
+@r2 ---- track
+@r3 ---- sign[]
+@r4 ---- rrixix[][NB_POS]
+@r5 ---- cor_1[]
+@r6 ---- cor_2[]
+
+
+ .section .text
+ .global cor_h_vec_012_asm
+
+cor_h_vec_012_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ LDR r4, [r13, #40] @load rrixix[][NB_POS]
+ ADD r7, r4, r2, LSL #5 @r7 --- p0 = rrixix[track]
+ MOV r4, #0 @i=0
+
+ @r0 --- h[], r1 --- vec[], r2 --- pos
+ @r3 --- sign[], r4 --- i, r7 --- p0
+LOOPi:
+ MOV r5, #0 @L_sum1 = 0
+ MOV r6, #0 @L_sum2 = 0
+ ADD r9, r1, r2, LSL #1 @p2 = &vec[pos]
+ MOV r10, r0 @p1 = h
+ RSB r11, r2, #62 @j=62-pos
+
+LOOPj1:
+ LDRSH r12, [r10], #2
+ LDRSH r8, [r9], #2
+ LDRSH r14, [r9]
+ SUBS r11, r11, #1
+ MLA r5, r12, r8, r5
+ MLA r6, r12, r14, r6
+ BGE LOOPj1
+
+ LDRSH r12, [r10], #2 @*p1++
+ MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2)
+ MLA r5, r12, r14, r5
+ MOV r14, #0x8000
+ MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2)
+ ADD r10, r6, r14
+ ADD r9, r5, r14
+ MOV r5, r9, ASR #16
+ MOV r6, r10, ASR #16
+ ADD r9, r3, r2, LSL #1 @address of sign[pos]
+ ADD r8, r7, #32
+ LDRSH r10, [r9], #2 @sign[pos]
+ LDRSH r11, [r9] @sign[pos + 1]
+ MUL r12, r5, r10
+ MUL r14, r6, r11
+ MOV r5, r12, ASR #15
+ MOV r6, r14, ASR #15
+ LDR r9, [r13, #44]
+ LDR r12, [r13, #48]
+ LDRSH r10, [r7], #2 @*p0++
+ LDRSH r11, [r8] @*p3++
+ ADD r9, r9, r4, LSL #1
+ ADD r12, r12, r4, LSL #1
+ ADD r5, r5, r10
+ ADD r6, r6, r11
+ STRH r5, [r9]
+ STRH r6, [r12]
+
+ ADD r2, r2, #4
+
+ MOV r5, #0 @L_sum1 = 0
+ MOV r6, #0 @L_sum2 = 0
+ ADD r9, r1, r2, LSL #1 @p2 = &vec[pos]
+ MOV r10, r0 @p1 = h
+ RSB r11, r2, #62 @j=62-pos
+ ADD r4, r4, #1 @i++
+
+LOOPj2:
+ LDRSH r12, [r10], #2
+ LDRSH r8, [r9], #2
+ LDRSH r14, [r9]
+ SUBS r11, r11, #1
+ MLA r5, r12, r8, r5
+ MLA r6, r12, r14, r6
+ BGE LOOPj2
+
+ LDRSH r12, [r10], #2 @*p1++
+ MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2)
+ MLA r5, r12, r14, r5
+ MOV r14, #0x8000
+ MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2)
+ ADD r10, r6, r14
+ ADD r9, r5, r14
+
+ MOV r5, r9, ASR #16
+ MOV r6, r10, ASR #16
+ ADD r9, r3, r2, LSL #1 @address of sign[pos]
+ ADD r8, r7, #32
+ LDRSH r10, [r9], #2 @sign[pos]
+ LDRSH r11, [r9] @sign[pos + 1]
+ MUL r12, r5, r10
+ MUL r14, r6, r11
+ MOV r5, r12, ASR #15
+ MOV r6, r14, ASR #15
+ LDR r9, [r13, #44]
+ LDR r12, [r13, #48]
+ LDRSH r10, [r7], #2 @*p0++
+ LDRSH r11, [r8] @*p3++
+ ADD r9, r9, r4, LSL #1
+ ADD r12, r12, r4, LSL #1
+ ADD r5, r5, r10
+ ADD r6, r6, r11
+ STRH r5, [r9]
+ STRH r6, [r12]
+ ADD r4, r4, #1 @i+1
+ ADD r2, r2, #4 @pos += STEP
+ CMP r4, #16
+
+ BLT LOOPi
+
+the_end:
+ LDMFD r13!, {r4 - r12, r15}
+
+ @ENDFUNC
+ .END
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
new file mode 100644
index 0000000..d5dd8f0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/pred_lt4_1_opt.s
@@ -0,0 +1,460 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Pred_lt4(
+@ Word16 exc[], /* in/out: excitation buffer */
+@ Word16 T0, /* input : integer pitch lag */
+@ Word16 frac, /* input : fraction of lag */
+@ Word16 L_subfr /* input : subframe size */
+@ )
+
+@******************************
+@ ARM Register
+@******************************
+@ r0 --- exc[]
+@ r1 --- T0
+@ r2 --- frac
+@ r3 --- L_subfr
+
+ .section .text
+ .global pred_lt4_asm
+ .extern inter4_2
+
+pred_lt4_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ RSB r4, r1, #0 @-T0
+ RSB r2, r2, #0 @frac = -frac
+ ADD r5, r0, r4, LSL #1 @x = exc - T0
+ CMP r2, #0
+ ADDLT r2, r2, #4 @frac += UP_SAMP
+ SUBLT r5, r5, #2 @x--
+ SUB r5, r5, #30 @x -= 15
+ RSB r4, r2, #3 @k = 3 - frac
+ LDR r6, Table
+ MOV r8, r4, LSL #6
+ @MOV r7, #0 @j = 0
+ ADD r8, r6, r8 @ptr2 = &(inter4_2[k][0])
+
+ MOV r1, r5
+ MOV r5, #0x8000
+ MOV r14, #21
+@ used register
+ @r0 --- exc[] r1 --- x r7 --- j r8 --- ptr2 r5 --- 0x8000
+THREE_LOOP:
+
+ @MOV r1, r5 @ptr1 = x
+ MOV r2, r8 @ptr = ptr2
+ LDR r3, [r2], #4 @h[0], h[1]
+ LDRSH r4, [r1], #2 @x[0]
+ LDRSH r6, [r1], #2 @x[1]
+ LDRSH r9, [r1], #2 @x[2]
+
+ SMULBB r10, r4, r3 @x[0] * h[0]
+ SMULBB r11, r6, r3 @x[1] * h[0]
+ SMULBB r12, r9, r3 @x[2] * h[0]
+
+ LDRSH r4, [r1], #2 @x[3]
+ SMLABT r10, r6, r3, r10 @x[1] * h[1]
+ SMLABT r11, r9, r3, r11 @x[2] * h[1]
+ SMLABT r12, r4, r3, r12 @x[3] * h[1]
+
+ LDR r3, [r2], #4 @h[2], h[3]
+ LDRSH r6, [r1], #2 @x[4]
+ SMLABB r10, r9, r3, r10 @x[2] * h[2]
+ SMLABB r11, r4, r3, r11 @x[3] * h[2]
+ SMLABB r12, r6, r3, r12 @x[4] * h[2]
+
+ LDRSH r9, [r1], #2 @x[5]
+ SMLABT r10, r4, r3, r10 @x[3] * h[3]
+ SMLABT r11, r6, r3, r11 @x[4] * h[3]
+ SMLABT r12, r9, r3, r12 @x[5] * h[3]
+
+ LDR r3, [r2], #4 @h[4], h[5]
+ LDRSH r4, [r1], #2 @x[6]
+ SMLABB r10, r6, r3, r10 @x[4] * h[4]
+ SMLABB r11, r9, r3, r11 @x[5] * h[4]
+ SMLABB r12, r4, r3, r12 @x[6] * h[4]
+
+ LDRSH r6, [r1], #2 @x[7]
+ SMLABT r10, r9, r3, r10 @x[5] * h[5]
+ SMLABT r11, r4, r3, r11 @x[6] * h[5]
+ SMLABT r12, r6, r3, r12 @x[7] * h[5]
+
+ LDR r3, [r2], #4 @h[6], h[7]
+ LDRSH r9, [r1], #2 @x[8]
+ SMLABB r10, r4, r3, r10 @x[6] * h[6]
+ SMLABB r11, r6, r3, r11 @x[7] * h[6]
+ SMLABB r12, r9, r3, r12 @x[8] * h[6]
+
+ LDRSH r4, [r1], #2 @x[9]
+ SMLABT r10, r6, r3, r10 @x[7] * h[7]
+ SMLABT r11, r9, r3, r11 @x[8] * h[7]
+ SMLABT r12, r4, r3, r12 @x[9] * h[7]
+
+ LDR r3, [r2], #4 @h[8], h[9]
+ LDRSH r6, [r1], #2 @x[10]
+ SMLABB r10, r9, r3, r10 @x[8] * h[8]
+ SMLABB r11, r4, r3, r11 @x[9] * h[8]
+ SMLABB r12, r6, r3, r12 @x[10] * h[8]
+
+ LDRSH r9, [r1], #2 @x[11]
+ SMLABT r10, r4, r3, r10 @x[9] * h[9]
+ SMLABT r11, r6, r3, r11 @x[10] * h[9]
+ SMLABT r12, r9, r3, r12 @x[11] * h[9]
+
+ LDR r3, [r2], #4 @h[10], h[11]
+ LDRSH r4, [r1], #2 @x[12]
+ SMLABB r10, r6, r3, r10 @x[10] * h[10]
+ SMLABB r11, r9, r3, r11 @x[11] * h[10]
+ SMLABB r12, r4, r3, r12 @x[12] * h[10]
+
+ LDRSH r6, [r1], #2 @x[13]
+ SMLABT r10, r9, r3, r10 @x[11] * h[11]
+ SMLABT r11, r4, r3, r11 @x[12] * h[11]
+ SMLABT r12, r6, r3, r12 @x[13] * h[11]
+
+ LDR r3, [r2], #4 @h[12], h[13]
+ LDRSH r9, [r1], #2 @x[14]
+ SMLABB r10, r4, r3, r10 @x[12] * h[12]
+ SMLABB r11, r6, r3, r11 @x[13] * h[12]
+ SMLABB r12, r9, r3, r12 @x[14] * h[12]
+
+ LDRSH r4, [r1], #2 @x[15]
+ SMLABT r10, r6, r3, r10 @x[13] * h[13]
+ SMLABT r11, r9, r3, r11 @x[14] * h[13]
+ SMLABT r12, r4, r3, r12 @x[15] * h[13]
+
+ LDR r3, [r2], #4 @h[14], h[15]
+ LDRSH r6, [r1], #2 @x[16]
+ SMLABB r10, r9, r3, r10 @x[14] * h[14]
+ SMLABB r11, r4, r3, r11 @x[15] * h[14]
+ SMLABB r12, r6, r3, r12 @x[16] * h[14]
+
+ LDRSH r9, [r1], #2 @x[17]
+ SMLABT r10, r4, r3, r10 @x[15] * h[15]
+ SMLABT r11, r6, r3, r11 @x[16] * h[15]
+ SMLABT r12, r9, r3, r12 @x[17] * h[15]
+
+ LDR r3, [r2], #4 @h[16], h[17]
+ LDRSH r4, [r1], #2 @x[18]
+ SMLABB r10, r6, r3, r10 @x[16] * h[16]
+ SMLABB r11, r9, r3, r11 @x[17] * h[16]
+ SMLABB r12, r4, r3, r12 @x[18] * h[16]
+
+ LDRSH r6, [r1], #2 @x[19]
+ SMLABT r10, r9, r3, r10 @x[17] * h[17]
+ SMLABT r11, r4, r3, r11 @x[18] * h[17]
+ SMLABT r12, r6, r3, r12 @x[19] * h[17]
+
+ LDR r3, [r2], #4 @h[18], h[19]
+ LDRSH r9, [r1], #2 @x[20]
+ SMLABB r10, r4, r3, r10 @x[18] * h[18]
+ SMLABB r11, r6, r3, r11 @x[19] * h[18]
+ SMLABB r12, r9, r3, r12 @x[20] * h[18]
+
+ LDRSH r4, [r1], #2 @x[21]
+ SMLABT r10, r6, r3, r10 @x[19] * h[19]
+ SMLABT r11, r9, r3, r11 @x[20] * h[19]
+ SMLABT r12, r4, r3, r12 @x[21] * h[19]
+
+ LDR r3, [r2], #4 @h[20], h[21]
+ LDRSH r6, [r1], #2 @x[22]
+ SMLABB r10, r9, r3, r10 @x[20] * h[20]
+ SMLABB r11, r4, r3, r11 @x[21] * h[20]
+ SMLABB r12, r6, r3, r12 @x[22] * h[20]
+
+ LDRSH r9, [r1], #2 @x[23]
+ SMLABT r10, r4, r3, r10 @x[21] * h[21]
+ SMLABT r11, r6, r3, r11 @x[22] * h[21]
+ SMLABT r12, r9, r3, r12 @x[23] * h[21]
+
+ LDR r3, [r2], #4 @h[22], h[23]
+ LDRSH r4, [r1], #2 @x[24]
+ SMLABB r10, r6, r3, r10 @x[22] * h[22]
+ SMLABB r11, r9, r3, r11 @x[23] * h[22]
+ SMLABB r12, r4, r3, r12 @x[24] * h[22]
+
+ LDRSH r6, [r1], #2 @x[25]
+ SMLABT r10, r9, r3, r10 @x[23] * h[23]
+ SMLABT r11, r4, r3, r11 @x[24] * h[23]
+ SMLABT r12, r6, r3, r12 @x[25] * h[23]
+
+ LDR r3, [r2], #4 @h[24], h[25]
+ LDRSH r9, [r1], #2 @x[26]
+ SMLABB r10, r4, r3, r10 @x[24] * h[24]
+ SMLABB r11, r6, r3, r11 @x[25] * h[24]
+ SMLABB r12, r9, r3, r12 @x[26] * h[24]
+
+ LDRSH r4, [r1], #2 @x[27]
+ SMLABT r10, r6, r3, r10 @x[25] * h[25]
+ SMLABT r11, r9, r3, r11 @x[26] * h[25]
+ SMLABT r12, r4, r3, r12 @x[27] * h[25]
+
+ LDR r3, [r2], #4 @h[26], h[27]
+ LDRSH r6, [r1], #2 @x[28]
+ SMLABB r10, r9, r3, r10 @x[26] * h[26]
+ SMLABB r11, r4, r3, r11 @x[27] * h[26]
+ SMLABB r12, r6, r3, r12 @x[28] * h[26]
+
+ LDRSH r9, [r1], #2 @x[29]
+ SMLABT r10, r4, r3, r10 @x[27] * h[27]
+ SMLABT r11, r6, r3, r11 @x[28] * h[27]
+ SMLABT r12, r9, r3, r12 @x[29] * h[27]
+
+ LDR r3, [r2], #4 @h[28], h[29]
+ LDRSH r4, [r1], #2 @x[30]
+ SMLABB r10, r6, r3, r10 @x[28] * h[28]
+ SMLABB r11, r9, r3, r11 @x[29] * h[28]
+ SMLABB r12, r4, r3, r12 @x[30] * h[28]
+
+ LDRSH r6, [r1], #2 @x[31]
+ SMLABT r10, r9, r3, r10 @x[29] * h[29]
+ SMLABT r11, r4, r3, r11 @x[30] * h[29]
+ SMLABT r12, r6, r3, r12 @x[31] * h[29]
+
+ LDR r3, [r2], #4 @h[30], h[31]
+ LDRSH r9, [r1], #2 @x[32]
+ SMLABB r10, r4, r3, r10 @x[30] * h[30]
+ SMLABB r11, r6, r3, r11 @x[31] * h[30]
+ SMLABB r12, r9, r3, r12 @x[32] * h[30]
+
+ LDRSH r4, [r1], #-60 @x[33]
+ SMLABT r10, r6, r3, r10 @x[31] * h[31]
+ SMLABT r11, r9, r3, r11 @x[32] * h[31]
+ SMLABT r12, r4, r3, r12 @x[33] * h[31]
+
+ @SSAT r10, #32, r10, LSL #2
+ @SSAT r11, #32, r11, LSL #2
+ @SSAT r12, #32, r12, LSL #2
+
+ MOV r10, r10, LSL #1
+ MOV r11, r11, LSL #1
+ MOV r12, r12, LSL #1
+
+ QADD r10, r10, r10
+ QADD r11, r11, r11
+ QADD r12, r12, r12
+
+ QADD r10, r10, r5
+ QADD r11, r11, r5
+ QADD r12, r12, r5
+
+ SUBS r14, r14, #1
+
+ MOV r10, r10, ASR #16
+ MOV r11, r11, ASR #16
+ MOV r12, r12, ASR #16
+
+ STRH r10, [r0], #2
+ STRH r11, [r0], #2
+ STRH r12, [r0], #2
+ BNE THREE_LOOP
+
+ MOV r2, r8 @ptr = ptr2
+
+Last2LOOP:
+
+ LDR r3, [r2], #4 @h[0], h[1]
+ LDRSH r4, [r1], #2 @x[0]
+ LDRSH r6, [r1], #2 @x[1]
+ LDRSH r9, [r1], #2 @x[2]
+
+ SMULBB r10, r4, r3 @x[0] * h[0]
+ SMULBB r11, r6, r3 @x[1] * h[0]
+
+ SMLABT r10, r6, r3, r10 @x[1] * h[1]
+ SMLABT r11, r9, r3, r11 @x[2] * h[1]
+
+ LDR r3, [r2], #4 @h[2], h[3]
+ LDRSH r4, [r1], #2 @x[3]
+ LDRSH r6, [r1], #2 @x[4]
+
+ SMLABB r10, r9, r3, r10 @x[2] * h[2]
+ SMLABB r11, r4, r3, r11 @x[3] * h[2]
+
+ SMLABT r10, r4, r3, r10 @x[3] * h[3]
+ SMLABT r11, r6, r3, r11 @x[4] * h[3]
+
+ LDR r3, [r2], #4 @h[4], h[5]
+ LDRSH r9, [r1], #2 @x[5]
+ LDRSH r4, [r1], #2 @x[6]
+
+ SMLABB r10, r6, r3, r10 @x[4] * h[4]
+ SMLABB r11, r9, r3, r11 @x[5] * h[4]
+
+ SMLABT r10, r9, r3, r10 @x[5] * h[5]
+ SMLABT r11, r4, r3, r11 @x[6] * h[5]
+
+ LDR r3, [r2], #4 @h[6], h[7]
+ LDRSH r6, [r1], #2 @x[7]
+ LDRSH r9, [r1], #2 @x[8]
+
+ SMLABB r10, r4, r3, r10 @x[6] * h[6]
+ SMLABB r11, r6, r3, r11 @x[7] * h[6]
+
+ SMLABT r10, r6, r3, r10 @x[7] * h[7]
+ SMLABT r11, r9, r3, r11 @x[8] * h[7]
+
+ LDR r3, [r2], #4 @h[8], h[9]
+ LDRSH r4, [r1], #2 @x[9]
+ LDRSH r6, [r1], #2 @x[10]
+
+ SMLABB r10, r9, r3, r10 @x[8] * h[8]
+ SMLABB r11, r4, r3, r11 @x[9] * h[8]
+
+ SMLABT r10, r4, r3, r10 @x[9] * h[9]
+ SMLABT r11, r6, r3, r11 @x[10] * h[9]
+
+ LDR r3, [r2], #4 @h[10], h[11]
+ LDRSH r9, [r1], #2 @x[11]
+ LDRSH r4, [r1], #2 @x[12]
+
+ SMLABB r10, r6, r3, r10 @x[10] * h[10]
+ SMLABB r11, r9, r3, r11 @x[11] * h[10]
+
+ SMLABT r10, r9, r3, r10 @x[11] * h[11]
+ SMLABT r11, r4, r3, r11 @x[12] * h[11]
+
+ LDR r3, [r2], #4 @h[12], h[13]
+ LDRSH r6, [r1], #2 @x[13]
+ LDRSH r9, [r1], #2 @x[14]
+
+ SMLABB r10, r4, r3, r10 @x[12] * h[12]
+ SMLABB r11, r6, r3, r11 @x[13] * h[12]
+
+ SMLABT r10, r6, r3, r10 @x[13] * h[13]
+ SMLABT r11, r9, r3, r11 @x[14] * h[13]
+
+ LDR r3, [r2], #4 @h[14], h[15]
+ LDRSH r4, [r1], #2 @x[15]
+ LDRSH r6, [r1], #2 @x[16]
+
+ SMLABB r10, r9, r3, r10 @x[14] * h[14]
+ SMLABB r11, r4, r3, r11 @x[15] * h[14]
+
+ SMLABT r10, r4, r3, r10 @x[15] * h[15]
+ SMLABT r11, r6, r3, r11 @x[16] * h[15]
+
+ LDR r3, [r2], #4 @h[16], h[17]
+ LDRSH r9, [r1], #2 @x[17]
+ LDRSH r4, [r1], #2 @x[18]
+
+ SMLABB r10, r6, r3, r10 @x[16] * h[16]
+ SMLABB r11, r9, r3, r11 @x[17] * h[16]
+
+ SMLABT r10, r9, r3, r10 @x[17] * h[17]
+ SMLABT r11, r4, r3, r11 @x[18] * h[17]
+
+ LDR r3, [r2], #4 @h[18], h[19]
+ LDRSH r6, [r1], #2 @x[19]
+ LDRSH r9, [r1], #2 @x[20]
+
+ SMLABB r10, r4, r3, r10 @x[18] * h[18]
+ SMLABB r11, r6, r3, r11 @x[19] * h[18]
+
+ SMLABT r10, r6, r3, r10 @x[19] * h[19]
+ SMLABT r11, r9, r3, r11 @x[20] * h[19]
+
+ LDR r3, [r2], #4 @h[20], h[21]
+ LDRSH r4, [r1], #2 @x[21]
+ LDRSH r6, [r1], #2 @x[22]
+
+ SMLABB r10, r9, r3, r10 @x[20] * h[20]
+ SMLABB r11, r4, r3, r11 @x[21] * h[20]
+
+ SMLABT r10, r4, r3, r10 @x[21] * h[21]
+ SMLABT r11, r6, r3, r11 @x[22] * h[21]
+
+ LDR r3, [r2], #4 @h[22], h[23]
+ LDRSH r9, [r1], #2 @x[23]
+ LDRSH r4, [r1], #2 @x[24]
+
+ SMLABB r10, r6, r3, r10 @x[22] * h[22]
+ SMLABB r11, r9, r3, r11 @x[23] * h[22]
+
+ SMLABT r10, r9, r3, r10 @x[23] * h[23]
+ SMLABT r11, r4, r3, r11 @x[24] * h[23]
+
+ LDR r3, [r2], #4 @h[24], h[25]
+ LDRSH r6, [r1], #2 @x[25]
+ LDRSH r9, [r1], #2 @x[26]
+
+ SMLABB r10, r4, r3, r10 @x[24] * h[24]
+ SMLABB r11, r6, r3, r11 @x[25] * h[24]
+
+ SMLABT r10, r6, r3, r10 @x[25] * h[25]
+ SMLABT r11, r9, r3, r11 @x[26] * h[25]
+
+ LDR r3, [r2], #4 @h[26], h[27]
+ LDRSH r4, [r1], #2 @x[27]
+ LDRSH r6, [r1], #2 @x[28]
+
+ SMLABB r10, r9, r3, r10 @x[26] * h[26]
+ SMLABB r11, r4, r3, r11 @x[27] * h[26]
+
+ SMLABT r10, r4, r3, r10 @x[27] * h[27]
+ SMLABT r11, r6, r3, r11 @x[28] * h[27]
+
+ LDR r3, [r2], #4 @h[28], h[29]
+ LDRSH r9, [r1], #2 @x[29]
+ LDRSH r4, [r1], #2 @x[30]
+
+ SMLABB r10, r6, r3, r10 @x[28] * h[28]
+ SMLABB r11, r9, r3, r11 @x[29] * h[28]
+
+ SMLABT r10, r9, r3, r10 @x[29] * h[29]
+ SMLABT r11, r4, r3, r11 @x[30] * h[29]
+
+ LDR r3, [r2], #4 @h[30], h[31]
+ LDRSH r6, [r1], #2 @x[31]
+ LDRSH r9, [r1], #2 @x[32]
+
+ SMLABB r10, r4, r3, r10 @x[30] * h[30]
+ SMLABB r11, r6, r3, r11 @x[31] * h[30]
+
+ SMLABT r10, r6, r3, r10 @x[31] * h[31]
+ SMLABT r11, r9, r3, r11 @x[32] * h[31]
+
+ @SSAT r10, #32, r10, LSL #2
+ @SSAT r11, #32, r11, LSL #2
+ MOV r10, r10, LSL #1
+ MOV r11, r11, LSL #1
+
+ QADD r10, r10, r10
+ QADD r11, r11, r11
+
+ QADD r10, r10, r5
+ QADD r11, r11, r5
+
+ MOV r10, r10, ASR #16
+ MOV r11, r11, ASR #16
+
+ STRH r10, [r0], #2
+ STRH r11, [r0], #2
+
+
+pred_lt4_end:
+ LDMFD r13!, {r4 - r12, r15}
+
+Table:
+ .word inter4_2
+ @ENDFUNC
+ .END
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s
new file mode 100644
index 0000000..060d9c7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/residu_asm_opt.s
@@ -0,0 +1,228 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Residu(
+@ Word16 a[], /* (i) Q12 : prediction coefficients */
+@ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */
+@ Word16 y[], /* (o) x2 : residual signal */
+@ Word16 lg /* (i) : size of filtering */
+@ )
+@a[] --- r0
+@x[] --- r1
+@y[] --- r2
+@lg --- r3
+
+ .section .text
+ .global Residu_opt
+
+Residu_opt:
+
+ STMFD r13!, {r4 - r12, r14}
+
+ LDRH r5, [r0], #2
+ LDRH r6, [r0], #2
+ ORR r5, r6, r5, LSL #16 @r5 --- a0, a1
+
+ LDRH r6, [r0], #2
+ LDRH r7, [r0], #2
+ ORR r6, r7, r6, LSL #16 @r6 --- a2, a3
+
+ LDRH r7, [r0], #2
+ LDRH r8, [r0], #2
+ ORR r7, r8, r7, LSL #16 @r7 --- a4, a5
+
+ LDRH r8, [r0], #2
+ LDRH r9, [r0], #2
+ ORR r8, r9, r8, LSL #16 @r8 --- a6, a7
+
+ LDRH r9, [r0], #2
+ LDRH r10, [r0], #2
+ ORR r9, r10, r9, LSL #16 @r9 --- a8, a9
+
+ LDRH r10, [r0], #2
+ LDRH r11, [r0], #2
+ ORR r10, r11, r10, LSL #16 @r10 --- a10, a11
+
+ LDRH r11, [r0], #2
+ LDRH r12, [r0], #2
+ ORR r11, r12, r11, LSL #16 @r11 --- a12, a13
+
+ LDRH r12, [r0], #2
+ LDRH r4, [r0], #2
+ ORR r12, r4, r12, LSL #16 @r12 --- a14, a15
+
+
+ STMFD r13!, {r8 - r12} @store r8-r12
+ LDRH r4, [r0], #2 @load a16
+ MOV r14, r3, ASR #2 @one loop get 4 outputs
+ ADD r1, r1, #4
+ MOV r0, r2
+ ORR r14, r4, r14, LSL #16 @r14 --- loopnum, a16
+
+residu_loop:
+
+ LDR r10, [r1], #-4 @r10 --- x[3], x[2]
+ LDR r2, [r1], #-4 @r2 --- x[1], x[0]
+
+ SMULTB r3, r5, r2 @i1(0) --- r3 = x[0] * a0
+ SMULTT r4, r5, r2 @i2(0) --- r4 = x[1] * a0
+ SMULTB r11, r5, r10 @i3(0) --- r11 = x[2] * a0
+ SMULTT r12, r5, r10 @i4(0) --- r12 = x[3] * a0
+
+ SMLABB r4, r5, r2, r4 @i2(1) --- r4 += x[0] * a1
+ SMLABT r11, r5, r2, r11 @i3(1) --- r11 += x[1] * a0
+ SMLABB r12, r5, r10, r12 @i4(1) --- r12 += x[2] * a1
+
+ SMLATB r11, r6, r2, r11 @i3(2) --- r11 += x[0] * a2
+ SMLATT r12, r6, r2, r12 @i4(2) --- r12 += x[1] * a2
+ SMLABB r12, r6, r2, r12 @i4(3) --- r12 += x[0] * a3
+
+ LDR r2, [r1], #-4 @r2 ---- x[-1], x[-2]
+
+ SMLABT r3, r5, r2, r3 @i1(1) --- r3 += x[-1] * a1
+ SMLATT r4, r6, r2, r4 @i2(2) --- r4 += x[-1] * a2
+ SMLABT r11, r6, r2, r11 @i3(3) --- r11 += x[-1] * a3
+ SMLATT r12, r7, r2, r12 @i4(4) --- r12 += x[-1] * a4
+ SMLATB r3, r6, r2, r3 @i1(2) --- r3 += x[-2] * a2
+
+ SMLABB r4, r6, r2, r4 @ i2 (3)
+ SMLATB r11,r7, r2, r11 @ i3 (4)
+ SMLABB r12,r7, r2, r12 @ i4 (5)
+
+ LDR r2,[r1],#-4
+ SMLABT r3, r6, r2, r3 @ i1 (3)
+ SMLATT r4, r7, r2, r4 @ i2 (4)
+ SMLABT r11,r7, r2, r11 @ i3 (5)
+ SMLATT r12,r8, r2, r12 @ i4 (6)
+ SMLATB r3, r7, r2, r3 @ i1 (4)
+ SMLABB r4, r7, r2, r4 @ i2 (5)
+ SMLATB r11,r8, r2, r11 @ i3 (6)
+ SMLABB r12,r8, r2, r12 @ i4 (7)
+
+ LDR r2,[r1],#-4
+ SMLABT r3, r7, r2, r3 @ i1 (5)
+ SMLATT r4, r8, r2, r4 @ i2 (6)
+ SMLABT r11,r8, r2, r11 @ i3 (7)
+ SMLATT r12,r9, r2, r12 @ i4 (8)
+ SMLATB r3, r8, r2, r3 @ i1 (6)
+ SMLABB r4, r8, r2, r4 @ i2 (7)
+ SMLATB r11,r9, r2, r11 @ i3 (8)
+ SMLABB r12,r9, r2, r12 @ i4 (9)
+ LDR r10, [r13, #8] @ [ a10 | a11]
+
+ LDR r2,[r1],#-4
+ SMLABT r3, r8, r2, r3 @ i1 (7)
+ SMLATT r4, r9, r2, r4 @ i2 (8)
+ SMLABT r11,r9, r2, r11 @ i3 (9)
+ SMLATT r12,r10, r2, r12 @ i4 (10)
+ SMLATB r3, r9, r2, r3 @ i1 (8)
+ SMLABB r4, r9, r2, r4 @ i2 (9)
+ SMLATB r11,r10, r2, r11 @ i3 (10)
+ SMLABB r12,r10, r2, r12 @ i4 (11)
+ LDR r8, [r13, #12] @ [ a12 | a13 ]
+
+ LDR r2,[r1],#-4
+ SMLABT r3, r9, r2, r3 @ i1 (9)
+ SMLATT r4, r10, r2, r4 @ i2 (10)
+ SMLABT r11,r10, r2, r11 @ i3 (11)
+ SMLATT r12,r8, r2, r12 @ i4 (12)
+ SMLATB r3, r10, r2, r3 @ i1 (10)
+ SMLABB r4, r10, r2, r4 @ i2 (11)
+ SMLATB r11,r8, r2, r11 @ i3 (12)
+ SMLABB r12,r8, r2, r12 @ i4 (13)
+ LDR r9, [r13, #16] @ [ a14 | a15 ]
+
+ LDR r2,[r1],#-4
+ SMLABT r3, r10, r2, r3 @ i1 (11)
+ SMLATT r4, r8, r2, r4 @ i2 (12)
+ SMLABT r11,r8, r2, r11 @ i3 (13)
+ SMLATT r12,r9, r2, r12 @ i4 (14)
+ SMLATB r3, r8, r2, r3 @ i1 (12)
+ SMLABB r4, r8, r2, r4 @ i2 (13)
+ SMLATB r11,r9, r2, r11 @ i3 (14)
+ SMLABB r12,r9, r2, r12 @ i4 (15)
+
+
+ LDR r2,[r1],#-4
+ SMLABT r3, r8, r2, r3 @ i1 (13)
+ SMLATT r4, r9, r2, r4 @ i2 (14)
+ SMLABT r11,r9, r2, r11 @ i3 (15)
+ SMLABT r12,r14, r2, r12 @ i4 (16)
+ SMLATB r3, r9, r2, r3 @ i1 (14)
+ SMLABB r4, r9, r2, r4 @ i2 (15)
+ SMLABB r11,r14, r2, r11 @ i3 (16)
+ LDR r8, [r13] @ [ a6 | a7 ]
+
+ LDR r2,[r1],#44 @ Change
+ SMLABT r3, r9, r2, r3
+ SMLABB r3, r14, r2, r3
+ SMLABT r4, r14, r2, r4
+ LDR r9, [r13, #4] @ [ a8 | a9 ]
+
+
+ QADD r3,r3,r3
+ QADD r4,r4,r4
+ QADD r11,r11,r11
+ QADD r12,r12,r12
+
+ QADD r3,r3,r3
+ QADD r4,r4,r4
+ QADD r11,r11,r11
+ QADD r12,r12,r12
+
+ QADD r3,r3,r3
+ QADD r4,r4,r4
+ QADD r11,r11,r11
+ QADD r12,r12,r12
+
+ QADD r3,r3,r3
+ QADD r4,r4,r4
+ QADD r11,r11,r11
+ QADD r12,r12,r12
+
+ MOV r2,#32768
+
+ QDADD r3,r2,r3
+ QDADD r4,r2,r4
+ QDADD r11,r2,r11
+ QDADD r12,r2,r12
+
+
+ MOV r3,r3,asr #16
+ MOV r4,r4,asr #16
+ MOV r11,r11,asr #16
+ MOV r12,r12,asr #16
+
+ STRH r3,[r0],#2
+ STRH r4,[r0],#2
+ STRH r11,[r0],#2
+ STRH r12,[r0],#2
+
+ MOV r2,r14,asr #16
+ SUB r14, r14, #0x10000
+ SUBS r2,r2,#1
+ BNE residu_loop
+end:
+ LDMFD r13!, {r8 -r12}
+ LDMFD r13!, {r4 -r12,pc}
+
+ @ENDFUNC
+ .END
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s
new file mode 100644
index 0000000..aa9f464
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/scale_sig_opt.s
@@ -0,0 +1,75 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Scale_sig(
+@ Word16 x[], /* (i/o) : signal to scale */
+@ Word16 lg, /* (i) : size of x[] */
+@ Word16 exp /* (i) : exponent: x = round(x << exp) */
+@ )
+@
+@r0 --- x[]
+@r1 --- lg
+@r2 --- exp
+
+ .section .text
+ .global Scale_sig_opt
+
+Scale_sig_opt:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r3, r1, #1 @i = lg - 1
+ CMP r2, #0 @Compare exp and 0
+ RSB r7, r2, #0 @exp = -exp
+ ADD r10, r2, #16 @16 + exp
+ ADD r4, r0, r3, LSL #1 @x[i] address
+ MOV r8, #0x7fffffff
+ MOV r9, #0x8000
+ BLE LOOP2
+
+LOOP1:
+
+ LDRSH r5, [r4] @load x[i]
+ MOV r12, r5, LSL r10
+ TEQ r5, r12, ASR r10
+ EORNE r12, r8, r5, ASR #31
+ SUBS r3, r3, #1
+ QADD r11, r12, r9
+ MOV r12, r11, ASR #16
+ STRH r12, [r4], #-2
+ BGE LOOP1
+ BL The_end
+
+LOOP2:
+
+ LDRSH r5, [r4] @load x[i]
+ MOV r6, r5, LSL #16 @L_tmp = x[i] << 16
+ MOV r5, r6, ASR r7 @L_tmp >>= exp
+ QADD r11, r5, r9
+ MOV r12, r11, ASR #16
+ SUBS r3, r3, #1
+ STRH r12, [r4], #-2
+ BGE LOOP2
+
+The_end:
+ LDMFD r13!, {r4 - r12, r15}
+
+ @ENDFUNC
+ .END
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s
new file mode 100644
index 0000000..e05e9e0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV5E/syn_filt_opt.s
@@ -0,0 +1,238 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@**********************************************************************/
+@void Syn_filt(
+@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+@ Word16 x[], /* (i) : input signal */
+@ Word16 y[], /* (o) : output signal */
+@ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+@)
+@***********************************************************************
+@ a[] --- r0
+@ x[] --- r1
+@ y[] --- r2
+@ mem[] --- r3
+@ m --- 16 lg --- 80 update --- 1
+
+ .section .text
+ .global Syn_filt_asm
+ .extern voAWB_Copy
+
+Syn_filt_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r13, r13, #700 @ y_buf[L_FRAME16k + M16k]
+
+ MOV r4, r3 @ copy mem[] address
+ MOV r5, r13 @ copy yy = y_buf address
+
+ @ for(i = 0@ i < m@ i++)
+ @{
+ @ *yy++ = mem[i]@
+ @}
+
+ LDRH r6, [r4], #2
+ LDRH r7, [r4], #2
+ LDRH r8, [r4], #2
+ LDRH r9, [r4], #2
+ LDRH r10, [r4], #2
+ LDRH r11, [r4], #2
+ LDRH r12, [r4], #2
+ LDRH r14, [r4], #2
+
+ STRH r6, [r5], #2
+ STRH r7, [r5], #2
+ STRH r8, [r5], #2
+ STRH r9, [r5], #2
+ STRH r10, [r5], #2
+ STRH r11, [r5], #2
+ STRH r12, [r5], #2
+ STRH r14, [r5], #2
+
+ LDRH r6, [r4], #2
+ LDRH r7, [r4], #2
+ LDRH r8, [r4], #2
+ LDRH r9, [r4], #2
+ LDRH r10, [r4], #2
+ LDRH r11, [r4], #2
+ LDRH r12, [r4], #2
+ LDRH r14, [r4], #2
+
+ STRH r6, [r5], #2
+ STRH r7, [r5], #2
+ STRH r8, [r5], #2
+ STRH r9, [r5], #2
+ STRH r10, [r5], #2
+ STRH r11, [r5], #2
+ STRH r12, [r5], #2
+ STRH r14, [r5], #2
+
+ LDRSH r5, [r0] @ load a[0]
+ MOV r8, #0 @ i = 0
+ MOV r5, r5, ASR #1 @ a0 = a[0] >> 1
+ @MOV r4, r13
+ @ load all a[]
+
+ LDR r14, =0xffff
+ LDRSH r6, [r0, #2] @ load a[1]
+ LDRSH r7, [r0, #4] @ load a[2]
+ LDRSH r9, [r0, #6] @ load a[3]
+ LDRSH r11,[r0, #8] @ load a[4]
+ AND r6, r6, r14
+ AND r9, r9, r14
+ ORR r10, r6, r7, LSL #16 @ -a[2] -- -a[1]
+ ORR r12, r9, r11, LSL #16 @ -a[4] -- -a[3]
+ STR r10, [r13, #-4]
+ STR r12, [r13, #-8]
+
+ LDRSH r6, [r0, #10] @ load a[5]
+ LDRSH r7, [r0, #12] @ load a[6]
+ LDRSH r9, [r0, #14] @ load a[7]
+ LDRSH r11,[r0, #16] @ load a[8]
+ AND r6, r6, r14
+ AND r9, r9, r14
+ ORR r10, r6, r7, LSL #16 @ -a[6] -- -a[5]
+ ORR r12, r9, r11, LSL #16 @ -a[8] -- -a[7]
+ STR r10, [r13, #-12]
+ STR r12, [r13, #-16]
+
+ LDRSH r6, [r0, #18] @ load a[9]
+ LDRSH r7, [r0, #20] @ load a[10]
+ LDRSH r9, [r0, #22] @ load a[11]
+ LDRSH r11,[r0, #24] @ load a[12]
+ AND r6, r6, r14
+ AND r9, r9, r14
+ ORR r10, r6, r7, LSL #16 @ -a[10] -- -a[9]
+ ORR r12, r9, r11, LSL #16 @ -a[12] -- -a[11]
+ STR r10, [r13, #-20]
+ STR r12, [r13, #-24]
+
+ LDRSH r6, [r0, #26] @ load a[13]
+ LDRSH r7, [r0, #28] @ load a[14]
+ LDRSH r9, [r0, #30] @ load a[15]
+ LDRSH r11,[r0, #32] @ load a[16]
+ AND r6, r6, r14
+ AND r9, r9, r14
+ ORR r10, r6, r7, LSL #16 @ -a[14] -- -a[13]
+ ORR r12, r9, r11, LSL #16 @ -a[16] -- -a[15]
+ STR r10, [r13, #-28]
+ STR r12, [r13, #-32]
+
+ ADD r4, r13, #32
+LOOP:
+ LDRSH r6, [r1], #2 @ load x[i]
+ ADD r10, r4, r8, LSL #1 @ temp_p = yy + i
+
+ MUL r0, r5, r6 @ L_tmp = x[i] * a0
+ @ for(j = 1@ j <= m, j+=8)
+ LDR r7, [r13, #-4] @ -a[2] -a[1]
+ LDRSH r9, [r10, #-2] @ *(temp_p - 1)
+ LDRSH r12, [r10, #-4] @ *(temp_p - 2)
+
+
+ SMULBB r14, r9, r7 @ -a[1] * (*(temp_p -1))
+
+ LDRSH r6, [r10, #-6] @ *(temp_p - 3)
+
+ SMLABT r14, r12, r7, r14 @ -a[2] * (*(temp_p - 2))
+
+ LDR r7, [r13, #-8] @ -a[4] -a[3]
+ LDRSH r11, [r10, #-8] @ *(temp_p - 4)
+
+ SMLABB r14, r6, r7, r14 @ -a[3] * (*(temp_p -3))
+
+ LDRSH r9, [r10, #-10] @ *(temp_p - 5)
+
+ SMLABT r14, r11, r7, r14 @ -a[4] * (*(temp_p -4))
+
+ LDR r7, [r13, #-12] @ -a[6] -a[5]
+ LDRSH r12, [r10, #-12] @ *(temp_p - 6)
+
+ SMLABB r14, r9, r7, r14 @ -a[5] * (*(temp_p -5))
+
+ LDRSH r6, [r10, #-14] @ *(temp_p - 7)
+
+ SMLABT r14, r12, r7, r14 @ -a[6] * (*(temp_p - 6))
+
+ LDR r7, [r13, #-16] @ -a[8] -a[7]
+ LDRSH r11, [r10, #-16] @ *(temp_p - 8)
+
+ SMLABB r14, r6, r7, r14 @ -a[7] * (*(temp_p -7))
+
+ LDRSH r9, [r10, #-18] @ *(temp_p - 9)
+
+ SMLABT r14, r11, r7, r14 @ -a[8] * (*(temp_p -8))
+
+ LDR r7, [r13, #-20] @ -a[10] -a[9]
+ LDRSH r12, [r10, #-20] @ *(temp_p - 10)
+
+ SMLABB r14, r9, r7, r14 @ -a[9] * (*(temp_p -9))
+
+ LDRSH r6, [r10, #-22] @ *(temp_p - 11)
+
+ SMLABT r14, r12, r7, r14 @ -a[10] * (*(temp_p - 10))
+
+ LDR r7, [r13, #-24] @ -a[12] -a[11]
+ LDRSH r11, [r10, #-24] @ *(temp_p - 12)
+
+ SMLABB r14, r6, r7, r14 @ -a[11] * (*(temp_p -11))
+
+ LDRSH r9, [r10, #-26] @ *(temp_p - 13)
+
+ SMLABT r14, r11, r7, r14 @ -a[12] * (*(temp_p -12))
+
+ LDR r7, [r13, #-28] @ -a[14] -a[13]
+ LDRSH r12, [r10, #-28] @ *(temp_p - 14)
+
+ SMLABB r14, r9, r7, r14 @ -a[13] * (*(temp_p -13))
+
+ LDRSH r6, [r10, #-30] @ *(temp_p - 15)
+
+ SMLABT r14, r12, r7, r14 @ -a[14] * (*(temp_p - 14))
+
+ LDR r7, [r13, #-32] @ -a[16] -a[15]
+ LDRSH r11, [r10, #-32] @ *(temp_p - 16)
+
+ SMLABB r14, r6, r7, r14 @ -a[15] * (*(temp_p -15))
+
+ SMLABT r14, r11, r7, r14 @ -a[16] * (*(temp_p -16))
+
+ RSB r14, r14, r0
+
+ MOV r7, r14, LSL #4 @ L_tmp <<=4
+ ADD r8, r8, #1
+ ADD r14, r7, #0x8000
+ MOV r7, r14, ASR #16 @ (L_tmp + 0x8000) >> 16
+ CMP r8, #80
+ STRH r7, [r10] @ yy[i]
+ STRH r7, [r2], #2 @ y[i]
+ BLT LOOP
+
+ @ update mem[]
+ ADD r5, r13, #160 @ yy[64] address
+ MOV r1, r3
+ MOV r0, r5
+ MOV r2, #16
+ BL voAWB_Copy
+
+Syn_filt_asm_end:
+
+ ADD r13, r13, #700
+ LDMFD r13!, {r4 - r12, r15}
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s
new file mode 100644
index 0000000..acb60c3
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Deemph_32_neon.s
@@ -0,0 +1,102 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Deemph_32(
+@ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+@ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+@ Word16 y[], /* (o) : output signal (x16) */
+@ Word16 mu, /* (i) Q15 : deemphasis factor */
+@ Word16 L, /* (i) : vector size */
+@ Word16 * mem /* (i/o) : memory (y[-1]) */
+@ )
+
+@x_hi RN R0
+@x_lo RN R1
+@y[] RN R2
+@*mem RN R3
+
+ .section .text
+ .global Deemph_32_asm
+
+Deemph_32_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ MOV r4, #2 @i=0
+ LDRSH r6, [r0], #2 @load x_hi[0]
+ LDRSH r7, [r1], #2 @load x_lo[0]
+ LDR r5, =22282 @r5---mu
+ MOV r11, #0x8000
+
+ @y[0]
+ MOV r10, r6, LSL #16 @L_tmp = x_hi[0]<<16
+ MOV r8, r5, ASR #1 @fac = mu >> 1
+ LDR r5, [r3]
+ ADD r12, r10, r7, LSL #4 @L_tmp += x_lo[0] << 4
+ MOV r10, r12, LSL #3 @L_tmp <<= 3
+ MUL r9, r5, r8
+ LDRSH r6, [r0], #2 @load x_hi[1]
+ QDADD r10, r10, r9
+ LDRSH r7, [r1], #2 @load x_lo[1]
+ MOV r12, r10, LSL #1 @L_tmp = L_mac(L_tmp, *mem, fac)
+ QADD r10, r12, r11
+ MOV r14, r10, ASR #16 @y[0] = round(L_tmp)
+
+
+ MOV r10, r6, LSL #16
+ ADD r12, r10, r7, LSL #4
+ STRH r14, [r2], #2 @update y[0]
+ MOV r10, r12, LSL #3
+ MUL r9, r14, r8
+ QDADD r10, r10, r9
+ MOV r12, r10, LSL #1
+ QADD r10, r12, r11
+ MOV r14, r10, ASR #16 @y[1] = round(L_tmp)
+
+LOOP:
+ LDRSH r6, [r0], #2 @load x_hi[]
+ LDRSH r7, [r1], #2
+ STRH r14, [r2], #2
+ MOV r10, r6, LSL #16
+ ADD r12, r10, r7, LSL #4
+ MUL r9, r14, r8
+ MOV r10, r12, LSL #3
+ QDADD r10, r10, r9
+ LDRSH r6, [r0], #2 @load x_hi[]
+ MOV r12, r10, LSL #1
+ QADD r10, r12, r11
+ LDRSH r7, [r1], #2
+ MOV r14, r10, ASR #16
+
+ MOV r10, r6, LSL #16
+ ADD r12, r10, r7, LSL #4
+ STRH r14, [r2], #2
+ MUL r9, r14, r8
+ MOV r10, r12, LSL #3
+ QDADD r10, r10, r9
+ ADD r4, r4, #2
+ MOV r12, r10, LSL #1
+ QADD r10, r12, r11
+ CMP r4, #64
+ MOV r14, r10, ASR #16
+
+ BLT LOOP
+ STR r14, [r3]
+ STRH r14, [r2]
+
+ LDMFD r13!, {r4 - r12, r15}
+
+ .END
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s
new file mode 100644
index 0000000..07ca344
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Dot_p_neon.s
@@ -0,0 +1,127 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@**********************************************************************/
+@Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+@ Word16 x[], /* (i) 12bits: x vector */
+@ Word16 y[], /* (i) 12bits: y vector */
+@ Word16 lg, /* (i) : vector length */
+@ Word16 * exp /* (o) : exponent of result (0..+30) */
+@)
+@************************************************************************
+@ x[] --- r0
+@ y[] --- r1
+@ lg --- r2
+@ *exp --- r3
+
+ .section .text
+ .global Dot_product12_asm
+
+Dot_product12_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ CMP r0, r1
+ BEQ LOOP_EQ
+
+ VLD1.S16 {Q0, Q1}, [r0]! @load 16 Word16 x[]
+ VLD1.S16 {Q2, Q3}, [r0]! @load 16 Word16 x[]
+ VLD1.S16 {Q4, Q5}, [r0]! @load 16 Word16 x[]
+ VLD1.S16 {Q6, Q7}, [r0]! @load 16 Word16 x[]
+ VLD1.S16 {Q8, Q9}, [r1]! @load 16 Word16 y[]
+ VLD1.S16 {Q10, Q11}, [r1]! @load 16 Word16 y[]
+ VLD1.S16 {Q12, Q13}, [r1]! @load 16 Word16 y[]
+
+ VMULL.S16 Q15, D16, D0
+ VMLAL.S16 Q15, D17, D1
+ VMLAL.S16 Q15, D18, D2
+ VMLAL.S16 Q15, D19, D3
+ VLD1.S16 {Q0, Q1}, [r1]! @load 16 Word16 y[]
+ VMLAL.S16 Q15, D20, D4
+ VMLAL.S16 Q15, D21, D5
+ VMLAL.S16 Q15, D22, D6
+ VMLAL.S16 Q15, D23, D7
+ VMLAL.S16 Q15, D24, D8
+ VMLAL.S16 Q15, D25, D9
+ VMLAL.S16 Q15, D26, D10
+ VMLAL.S16 Q15, D27, D11
+ VMLAL.S16 Q15, D0, D12
+ VMLAL.S16 Q15, D1, D13
+ VMLAL.S16 Q15, D2, D14
+ VMLAL.S16 Q15, D3, D15
+
+ CMP r2, #64
+ BEQ Lable1
+ VLD1.S16 {Q0, Q1}, [r0]! @load 16 Word16 x[]
+ VLD1.S16 {Q2, Q3}, [r1]!
+ VMLAL.S16 Q15, D4, D0
+ VMLAL.S16 Q15, D5, D1
+ VMLAL.S16 Q15, D6, D2
+ VMLAL.S16 Q15, D7, D3
+ BL Lable1
+
+LOOP_EQ:
+ VLD1.S16 {Q0, Q1}, [r0]!
+ VLD1.S16 {Q2, Q3}, [r0]!
+ VLD1.S16 {Q4, Q5}, [r0]!
+ VLD1.S16 {Q6, Q7}, [r0]!
+ VMULL.S16 Q15, D0, D0
+ VMLAL.S16 Q15, D1, D1
+ VMLAL.S16 Q15, D2, D2
+ VMLAL.S16 Q15, D3, D3
+ VMLAL.S16 Q15, D4, D4
+ VMLAL.S16 Q15, D5, D5
+ VMLAL.S16 Q15, D6, D6
+ VMLAL.S16 Q15, D7, D7
+ VMLAL.S16 Q15, D8, D8
+ VMLAL.S16 Q15, D9, D9
+ VMLAL.S16 Q15, D10, D10
+ VMLAL.S16 Q15, D11, D11
+ VMLAL.S16 Q15, D12, D12
+ VMLAL.S16 Q15, D13, D13
+ VMLAL.S16 Q15, D14, D14
+ VMLAL.S16 Q15, D15, D15
+
+ CMP r2, #64
+ BEQ Lable1
+ VLD1.S16 {Q0, Q1}, [r0]!
+ VMLAL.S16 Q15, D0, D0
+ VMLAL.S16 Q15, D1, D1
+ VMLAL.S16 Q15, D2, D2
+ VMLAL.S16 Q15, D3, D3
+
+Lable1:
+
+ VQADD.S32 D30, D30, D31
+ VPADD.S32 D30, D30, D30
+ VMOV.S32 r12, D30[0]
+
+ ADD r12, r12, r12
+ ADD r12, r12, #1 @ L_sum = (L_sum << 1) + 1
+ MOV r4, r12
+ CMP r12, #0
+ RSBLT r4, r12, #0
+ CLZ r10, r4
+ SUB r10, r10, #1 @ sft = norm_l(L_sum)
+ MOV r0, r12, LSL r10 @ L_sum = L_sum << sft
+ RSB r11, r10, #30 @ *exp = 30 - sft
+ STRH r11, [r3]
+
+Dot_product12_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+
+ .END
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
new file mode 100644
index 0000000..1880024
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Filt_6k_7k_neon.s
@@ -0,0 +1,228 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@**********************************************************************/
+@void Filt_6k_7k(
+@ Word16 signal[], /* input: signal */
+@ Word16 lg, /* input: length of input */
+@ Word16 mem[] /* in/out: memory (size=30) */
+@)
+@***********************************************************************
+@ r0 --- signal[]
+@ r1 --- lg
+@ r2 --- mem[]
+
+ .section .text
+ .global Filt_6k_7k_asm
+ .extern fir_6k_7k
+
+Filt_6k_7k_asm:
+
+ STMFD r13!, {r0 - r12, r14}
+ SUB r13, r13, #240 @ x[L_SUBFR16k + (L_FIR - 1)]
+ MOV r8, r0 @ copy signal[] address
+ MOV r5, r2 @ copy mem[] address
+
+ MOV r0, r2
+ MOV r1, r13
+
+ VLD1.S16 {D0, D1, D2, D3}, [r0]!
+ VLD1.S16 {D4, D5, D6, D7}, [r0]!
+
+ VST1.S16 {D0, D1, D2, D3}, [r1]!
+ VST1.S16 {D4, D5, D6}, [r1]!
+ VST1.S16 D7[0], [r1]!
+ VST1.S16 D7[1], [r1]!
+
+
+
+ LDR r10, Lable1 @ get fir_7k address
+ MOV r3, r8 @ change myMemCopy to Copy, due to Copy will change r3 content
+ ADD r6, r13, #60 @ get x[L_FIR - 1] address
+ MOV r7, r3 @ get signal[i]
+ @for (i = lg - 1@ i >= 0@ i--)
+ @{
+ @ x[i + L_FIR - 1] = signal[i] >> 2@
+ @}
+ VLD1.S16 {Q0, Q1}, [r7]! @ signal[0] ~ signal[15]
+ VLD1.S16 {Q2, Q3}, [r7]! @ signal[16] ~ signal[31]
+ VLD1.S16 {Q4, Q5}, [r7]! @ signal[32] ~ signal[47]
+ VLD1.S16 {Q6, Q7}, [r7]! @ signal[48] ~ signal[63]
+ VLD1.S16 {Q8, Q9}, [r7]! @ signal[64] ~ signal[79]
+ VSHR.S16 Q10, Q0, #2
+ VSHR.S16 Q11, Q1, #2
+ VSHR.S16 Q12, Q2, #2
+ VSHR.S16 Q13, Q3, #2
+ VST1.S16 {Q10, Q11}, [r6]!
+ VSHR.S16 Q0, Q4, #2
+ VSHR.S16 Q1, Q5, #2
+ VSHR.S16 Q10, Q6, #2
+ VSHR.S16 Q11, Q7, #2
+ VSHR.S16 Q2, Q8, #2
+ VSHR.S16 Q3, Q9, #2
+ VST1.S16 {Q12, Q13}, [r6]!
+ VST1.S16 {Q0, Q1}, [r6]!
+ VST1.S16 {Q10, Q11}, [r6]!
+ VST1.S16 {Q2, Q3}, [r6]!
+
+ MOV r12, r5
+ @STR r5, [sp, #-4] @ PUSH r5 to stack
+ @ not use registers: r4, r10, r12, r14, r5
+ MOV r4, r13
+ MOV r5, #0 @ i = 0
+
+ @ r4 --- x[i], r10 ---- fir_6k_7k
+ VLD1.S16 {Q0, Q1}, [r10]! @fir_6k_7k[0] ~ fir_6k_7k[15]
+ VLD1.S16 {Q2, Q3}, [r10]! @fir_6k_7k[16] ~ fir_6k_7k[31]
+ VMOV.S16 D7[3], r5 @set fir_6k_7K = 0
+
+ VLD1.S16 {Q4, Q5}, [r4]! @x[0] ~ x[15]
+ VLD1.S16 {Q6, Q7}, [r4]! @x[16] ~ X[31]
+ VLD1.S16 {Q8}, [r4]!
+ VMOV.S16 Q15, #0
+
+LOOP_6K7K:
+
+ VMULL.S16 Q9,D8,D0[0]
+ VMULL.S16 Q10,D9,D1[0]
+ VMULL.S16 Q11,D9,D0[0]
+ VMULL.S16 Q12,D10,D1[0]
+ VEXT.8 Q4,Q4,Q5,#2
+ VMLAL.S16 Q9,D10,D2[0]
+ VMLAL.S16 Q10,D11,D3[0]
+ VMLAL.S16 Q11,D11,D2[0]
+ VMLAL.S16 Q12,D12,D3[0]
+ VEXT.8 Q5,Q5,Q6,#2
+ VMLAL.S16 Q9,D12,D4[0]
+ VMLAL.S16 Q10,D13,D5[0]
+ VMLAL.S16 Q11,D13,D4[0]
+ VMLAL.S16 Q12,D14,D5[0]
+ VEXT.8 Q6,Q6,Q7,#2
+ VMLAL.S16 Q9,D14,D6[0]
+ VMLAL.S16 Q10,D15,D7[0]
+ VMLAL.S16 Q11,D15,D6[0]
+ VMLAL.S16 Q12,D16,D7[0]
+ VEXT.8 Q7,Q7,Q8,#2
+
+ VMLAL.S16 Q9,D8,D0[1]
+ VMLAL.S16 Q10,D9,D1[1]
+ VEXT.8 Q8,Q8,Q15,#2
+ VMLAL.S16 Q11,D9,D0[1]
+ VMLAL.S16 Q12,D10,D1[1]
+ VEXT.8 Q4,Q4,Q5,#2
+ VMLAL.S16 Q9,D10,D2[1]
+ VMLAL.S16 Q10,D11,D3[1]
+ VMLAL.S16 Q11,D11,D2[1]
+ VMLAL.S16 Q12,D12,D3[1]
+ VEXT.8 Q5,Q5,Q6,#2
+ VMLAL.S16 Q9,D12,D4[1]
+ VMLAL.S16 Q10,D13,D5[1]
+ VMLAL.S16 Q11,D13,D4[1]
+ VMLAL.S16 Q12,D14,D5[1]
+ VEXT.8 Q6,Q6,Q7,#2
+ VMLAL.S16 Q9,D14,D6[1]
+ VMLAL.S16 Q10,D15,D7[1]
+ VMLAL.S16 Q11,D15,D6[1]
+ VMLAL.S16 Q12,D16,D7[1]
+ VEXT.8 Q7,Q7,Q8,#2
+
+ VMLAL.S16 Q9,D8,D0[2]
+ VMLAL.S16 Q10,D9,D1[2]
+ VEXT.8 Q8,Q8,Q15,#2
+ VMLAL.S16 Q11,D9,D0[2]
+ VMLAL.S16 Q12,D10,D1[2]
+ VEXT.8 Q4,Q4,Q5,#2
+ VMLAL.S16 Q9,D10,D2[2]
+ VMLAL.S16 Q10,D11,D3[2]
+ VMLAL.S16 Q11,D11,D2[2]
+ VMLAL.S16 Q12,D12,D3[2]
+ VEXT.8 Q5,Q5,Q6,#2
+ VMLAL.S16 Q9,D12,D4[2]
+ VMLAL.S16 Q10,D13,D5[2]
+ VMLAL.S16 Q11,D13,D4[2]
+ VMLAL.S16 Q12,D14,D5[2]
+ VEXT.8 Q6,Q6,Q7,#2
+ VMLAL.S16 Q9,D14,D6[2]
+ VMLAL.S16 Q10,D15,D7[2]
+ VMLAL.S16 Q11,D15,D6[2]
+ VMLAL.S16 Q12,D16,D7[2]
+ VEXT.8 Q7,Q7,Q8,#2
+
+ VMLAL.S16 Q9,D8,D0[3]
+ VMLAL.S16 Q10,D9,D1[3]
+ VEXT.8 Q8,Q8,Q15,#2
+ VMLAL.S16 Q11,D9,D0[3]
+ VMLAL.S16 Q12,D10,D1[3]
+ VEXT.8 Q4,Q4,Q5,#2
+ VMLAL.S16 Q9,D10,D2[3]
+ VMLAL.S16 Q10,D11,D3[3]
+ VMLAL.S16 Q11,D11,D2[3]
+ VMLAL.S16 Q12,D12,D3[3]
+ VEXT.8 Q5,Q5,Q6,#2
+ VMLAL.S16 Q9,D12,D4[3]
+ VMLAL.S16 Q10,D13,D5[3]
+ VMLAL.S16 Q11,D13,D4[3]
+ VMLAL.S16 Q12,D14,D5[3]
+ VEXT.8 Q6,Q6,Q7,#2
+ VMLAL.S16 Q9,D14,D6[3]
+ VMLAL.S16 Q10,D15,D7[3]
+ VMLAL.S16 Q11,D15,D6[3]
+ VMLAL.S16 Q12,D16,D7[3]
+ VEXT.8 Q7,Q7,Q8,#2
+
+ VMOV.S16 D8,D9
+ VEXT.8 Q8,Q8,Q15,#2
+ VMOV.S16 D9,D10
+ VADD.S32 Q9,Q9,Q10
+ VMOV.S16 D10,D11
+ VMOV.S16 D11,D12
+ VADD.S32 Q11,Q11,Q12
+ VMOV.S16 D12,D13
+ VQRSHRN.S32 D28,Q9,#15
+ VMOV.S16 D13,D14
+ VMOV.S16 D14,D15
+ VQRSHRN.S32 D29,Q11,#15
+ VMOV.S16 D15,D16
+
+ VLD1.S16 {Q8},[r4]!
+ ADD r5, r5, #8
+ CMP r5, #80
+ VST1.S16 {D28,D29},[r3]!
+ BLT LOOP_6K7K
+
+ ADD r0, r13, #160 @x + lg
+ MOV r1, r12
+ @LDR r1, [sp, #-4] @mem address
+
+ VLD1.S16 {D0, D1, D2, D3}, [r0]!
+ VLD1.S16 {D4, D5, D6, D7}, [r0]!
+
+ VST1.S16 {D0, D1, D2, D3}, [r1]!
+ VST1.S16 {D4, D5, D6}, [r1]!
+ VST1.S16 D7[0], [r1]!
+ VST1.S16 D7[1], [r1]!
+
+Filt_6k_7k_end:
+
+ ADD r13, r13, #240
+ LDMFD r13!, {r0 - r12, r15}
+
+Lable1:
+ .word fir_6k_7k
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s
new file mode 100644
index 0000000..60e9ade
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Norm_Corr_neon.s
@@ -0,0 +1,270 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@static void Norm_Corr (Word16 exc[], /* (i) : excitation buffer */
+@ Word16 xn[], /* (i) : target vector */
+@ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+@ Word16 L_subfr, /* (i) : sub-frame length */
+@ Word16 t_min, /* (i) : minimum value of pitch lag. */
+@ Word16 t_max, /* (i) : maximum value of pitch lag. */
+@ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */
+@
+
+@ r0 --- exc[]
+@ r1 --- xn[]
+@ r2 --- h[]
+@ r3 --- L_subfr
+@ r4 --- t_min
+@ r5 --- t_max
+@ r6 --- corr_norm[]
+
+
+ .section .text
+ .global Norm_corr_asm
+ .extern Convolve_asm
+ .extern Isqrt_n
+@******************************
+@ constant
+@******************************
+.equ EXC , 0
+.equ XN , 4
+.equ H , 8
+.equ L_SUBFR , 12
+.equ voSTACK , 172
+.equ T_MIN , 212
+.equ T_MAX , 216
+.equ CORR_NORM , 220
+
+Norm_corr_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r13, r13, #voSTACK
+
+ ADD r8, r13, #20 @get the excf[L_SUBFR]
+ LDR r4, [r13, #T_MIN] @get t_min
+ RSB r11, r4, #0 @k = -t_min
+ ADD r5, r0, r11, LSL #1 @get the &exc[k]
+
+ @transfer Convolve function
+ STMFD sp!, {r0 - r3}
+ MOV r0, r5
+ MOV r1, r2
+ MOV r2, r8 @r2 --- excf[]
+ BL Convolve_asm
+ LDMFD sp!, {r0 - r3}
+
+ @ r8 --- excf[]
+
+ MOV r14, r1 @copy xn[] address
+ MOV r7, #1
+ VLD1.S16 {Q0, Q1}, [r14]!
+ VLD1.S16 {Q2, Q3}, [r14]!
+ VLD1.S16 {Q4, Q5}, [r14]!
+ VLD1.S16 {Q6, Q7}, [r14]!
+
+ VMULL.S16 Q10, D0, D0
+ VMLAL.S16 Q10, D1, D1
+ VMLAL.S16 Q10, D2, D2
+ VMLAL.S16 Q10, D3, D3
+ VMLAL.S16 Q10, D4, D4
+ VMLAL.S16 Q10, D5, D5
+ VMLAL.S16 Q10, D6, D6
+ VMLAL.S16 Q10, D7, D7
+ VMLAL.S16 Q10, D8, D8
+ VMLAL.S16 Q10, D9, D9
+ VMLAL.S16 Q10, D10, D10
+ VMLAL.S16 Q10, D11, D11
+ VMLAL.S16 Q10, D12, D12
+ VMLAL.S16 Q10, D13, D13
+ VMLAL.S16 Q10, D14, D14
+ VMLAL.S16 Q10, D15, D15
+
+ VQADD.S32 D20, D20, D21
+ VMOV.S32 r9, D20[0]
+ VMOV.S32 r10, D20[1]
+ QADD r6, r9, r10
+ QADD r6, r6, r6
+ QADD r9, r6, r7 @L_tmp = (L_tmp << 1) + 1;
+ CLZ r7, r9
+ SUB r6, r7, #1 @exp = norm_l(L_tmp)
+ RSB r7, r6, #32 @exp = 32 - exp
+ MOV r6, r7, ASR #1
+ RSB r7, r6, #0 @scale = -(exp >> 1)
+
+ @loop for every possible period
+ @for(t = t_min@ t <= t_max@ t++)
+ @r7 --- scale r4 --- t_min r8 --- excf[]
+
+LOOPFOR:
+ ADD r14, r13, #20 @copy of excf[]
+ MOV r12, r1 @copy of xn[]
+ MOV r8, #0x8000
+
+ VLD1.S16 {Q0, Q1}, [r14]! @ load 16 excf[]
+ VLD1.S16 {Q2, Q3}, [r14]! @ load 16 excf[]
+ VLD1.S16 {Q4, Q5}, [r12]! @ load 16 x[]
+ VLD1.S16 {Q6, Q7}, [r12]! @ load 16 x[]
+ VMULL.S16 Q10, D0, D0 @L_tmp1 += excf[] * excf[]
+ VMULL.S16 Q11, D0, D8 @L_tmp += x[] * excf[]
+ VMLAL.S16 Q10, D1, D1
+ VMLAL.S16 Q11, D1, D9
+ VMLAL.S16 Q10, D2, D2
+ VMLAL.S16 Q11, D2, D10
+ VMLAL.S16 Q10, D3, D3
+ VMLAL.S16 Q11, D3, D11
+ VMLAL.S16 Q10, D4, D4
+ VMLAL.S16 Q11, D4, D12
+ VMLAL.S16 Q10, D5, D5
+ VMLAL.S16 Q11, D5, D13
+ VMLAL.S16 Q10, D6, D6
+ VMLAL.S16 Q11, D6, D14
+ VMLAL.S16 Q10, D7, D7
+ VMLAL.S16 Q11, D7, D15
+
+ VLD1.S16 {Q0, Q1}, [r14]! @ load 16 excf[]
+ VLD1.S16 {Q2, Q3}, [r14]! @ load 16 excf[]
+ VLD1.S16 {Q4, Q5}, [r12]! @ load 16 x[]
+ VLD1.S16 {Q6, Q7}, [r12]! @ load 16 x[]
+ VMLAL.S16 Q10, D0, D0
+ VMLAL.S16 Q11, D0, D8
+ VMLAL.S16 Q10, D1, D1
+ VMLAL.S16 Q11, D1, D9
+ VMLAL.S16 Q10, D2, D2
+ VMLAL.S16 Q11, D2, D10
+ VMLAL.S16 Q10, D3, D3
+ VMLAL.S16 Q11, D3, D11
+ VMLAL.S16 Q10, D4, D4
+ VMLAL.S16 Q11, D4, D12
+ VMLAL.S16 Q10, D5, D5
+ VMLAL.S16 Q11, D5, D13
+ VMLAL.S16 Q10, D6, D6
+ VMLAL.S16 Q11, D6, D14
+ VMLAL.S16 Q10, D7, D7
+ VMLAL.S16 Q11, D7, D15
+
+ VQADD.S32 D20, D20, D21
+ VQADD.S32 D22, D22, D23
+
+ VPADD.S32 D20, D20, D20 @D20[0] --- L_tmp1 << 1
+ VPADD.S32 D22, D22, D22 @D22[0] --- L_tmp << 1
+
+ VMOV.S32 r6, D20[0]
+ VMOV.S32 r5, D22[0]
+
+ @r5 --- L_tmp, r6 --- L_tmp1
+ MOV r10, #1
+ ADD r5, r10, r5, LSL #1 @L_tmp = (L_tmp << 1) + 1
+ ADD r6, r10, r6, LSL #1 @L_tmp1 = (L_tmp1 << 1) + 1
+
+ CLZ r10, r5
+ CMP r5, #0
+ RSBLT r11, r5, #0
+ CLZLT r10, r11
+ SUB r10, r10, #1 @exp = norm_l(L_tmp)
+
+ MOV r5, r5, LSL r10 @L_tmp = (L_tmp << exp)
+ RSB r10, r10, #30 @exp_corr = 30 - exp
+ MOV r11, r5, ASR #16 @corr = extract_h(L_tmp)
+
+ CLZ r5, r6
+ SUB r5, r5, #1
+ MOV r6, r6, LSL r5 @L_tmp = (L_tmp1 << exp)
+ RSB r5, r5, #30 @exp_norm = 30 - exp
+
+ @r10 --- exp_corr, r11 --- corr
+ @r6 --- L_tmp, r5 --- exp_norm
+
+ @Isqrt_n(&L_tmp, &exp_norm)
+
+ MOV r14, r0
+ MOV r12, r1
+
+ STMFD sp!, {r0 - r4, r7 - r12, r14}
+ ADD r1, sp, #4
+ ADD r0, sp, #0
+ STR r6, [sp]
+ STRH r5, [sp, #4]
+ BL Isqrt_n
+ LDR r6, [sp]
+ LDRSH r5, [sp, #4]
+ LDMFD sp!, {r0 - r4, r7 - r12, r14}
+ MOV r0, r14
+ MOV r1, r12
+
+
+ MOV r6, r6, ASR #16 @norm = extract_h(L_tmp)
+ MUL r12, r6, r11
+ ADD r12, r12, r12 @L_tmp = vo_L_mult(corr, norm)
+
+ ADD r6, r10, r5
+ ADD r6, r6, r7 @exp_corr + exp_norm + scale
+
+ CMP r6, #0
+ RSBLT r6, r6, #0
+ MOVLT r12, r12, ASR r6
+ MOVGT r12, r12, LSL r6 @L_tmp = L_shl(L_tmp, exp_corr + exp_norm + scale)
+
+ ADD r12, r12, r8
+ MOV r12, r12, ASR #16 @vo_round(L_tmp)
+
+ LDR r5, [r13, #CORR_NORM] @ get corr_norm address
+ LDR r6, [r13, #T_MAX] @ get t_max
+ ADD r10, r5, r4, LSL #1 @ get corr_norm[t] address
+ STRH r12, [r10] @ corr_norm[t] = vo_round(L_tmp)
+
+ CMP r4, r6
+ BEQ Norm_corr_asm_end
+
+ ADD r4, r4, #1 @ t_min ++
+ RSB r5, r4, #0 @ k
+
+ MOV r6, #63 @ i = 63
+ MOV r8, r0 @ exc[]
+ MOV r9, r2 @ h[]
+ ADD r10, r13, #20 @ excf[]
+
+ ADD r8, r8, r5, LSL #1 @ exc[k] address
+ ADD r9, r9, r6, LSL #1 @ h[i] address
+ ADD r10, r10, r6, LSL #1 @ excf[i] address
+ LDRSH r11, [r8] @ tmp = exc[k]
+
+LOOPK:
+ LDRSH r8, [r9], #-2 @ load h[i]
+ LDRSH r12, [r10, #-2] @ load excf[i - 1]
+ MUL r14, r11, r8
+ MOV r8, r14, ASR #15
+ ADD r14, r8, r12
+ STRH r14, [r10], #-2
+ SUBS r6, r6, #1
+ BGT LOOPK
+
+ LDRSH r8, [r9] @ load h[0]
+ MUL r14, r11, r8
+ LDR r6, [r13, #T_MAX] @ get t_max
+ MOV r8, r14, ASR #15
+ STRH r8, [r10]
+
+ CMP r4, r6
+ BLE LOOPFOR
+
+Norm_corr_asm_end:
+
+ ADD r13, r13, #voSTACK
+ LDMFD r13!, {r4 - r12, r15}
+
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s
new file mode 100644
index 0000000..cb1764f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/Syn_filt_32_neon.s
@@ -0,0 +1,133 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@**********************************************************************/
+@void Syn_filt_32(
+@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+@ Word16 m, /* (i) : order of LP filter */
+@ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+@ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+@ Word16 sig_hi[], /* (o) /16 : synthesis high */
+@ Word16 sig_lo[], /* (o) /16 : synthesis low */
+@ Word16 lg /* (i) : size of filtering */
+@)
+@***********************************************************************
+@ a[] --- r0
+@ m --- r1
+@ exc[] --- r2
+@ Qnew --- r3
+@ sig_hi[] --- r4
+@ sig_lo[] --- r5
+@ lg --- r6
+
+ .section .text
+ .global Syn_filt_32_asm
+
+Syn_filt_32_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ LDR r4, [r13, #40] @ get sig_hi[] address
+ LDR r5, [r13, #44] @ get sig_lo[] address
+
+ LDRSH r6, [r0], #2 @ load Aq[0]
+ ADD r7, r3, #4 @ 4 + Q_new
+ MOV r3, r6, ASR r7 @ a0 = Aq[0] >> (4 + Q_new)
+
+ SUB r10, r4, #32 @ sig_hi[-16] address
+ SUB r11, r5, #32 @ sig_lo[-16] address
+
+ VLD1.S16 {D0, D1, D2, D3}, [r0]! @a[1] ~ a[16]
+
+ MOV r8, #0 @ i = 0
+
+ VLD1.S16 {D4, D5, D6, D7}, [r10]! @ sig_hi[-16] ~ sig_hi[-1]
+ VREV64.16 D0, D0
+ VREV64.16 D1, D1
+ VLD1.S16 {D8, D9, D10, D11}, [r11]! @ sig_lo[-16] ~ sig_lo[-1]
+ VREV64.16 D2, D2
+ VREV64.16 D3, D3
+ VDUP.S32 Q15, r8
+
+SYN_LOOP:
+
+ LDRSH r6, [r2], #2 @exc[i]
+ @L_tmp = L_msu(L_tmp, sig_lo[i - j], a[j])@
+ VMULL.S16 Q10, D8, D3
+ VEXT.8 D8, D8, D9, #2
+ VMLAL.S16 Q10, D9, D2
+ VMLAL.S16 Q10, D10, D1
+ VMLAL.S16 Q10, D11, D0
+
+ VEXT.8 D9, D9, D10, #2
+ VEXT.8 D10, D10, D11, #2
+
+ VPADD.S32 D28, D20, D21
+ MUL r12, r6, r3 @exc[i] * a0
+ VPADD.S32 D29, D28, D28
+ VDUP.S32 Q10, D29[0] @result1
+
+ VMULL.S16 Q11, D4, D3
+ VMLAL.S16 Q11, D5, D2
+ VSUB.S32 Q10, Q15, Q10
+ @L_tmp = L_msu(L_tmp, sig_hi[i - j], a[j])@
+
+ VMLAL.S16 Q11, D6, D1
+ VEXT.8 D4, D4, D5, #2
+ VMLAL.S16 Q11, D7, D0
+
+
+ VEXT.8 D5, D5, D6, #2
+ VEXT.8 D6, D6, D7, #2
+
+ VPADD.S32 D28, D22, D23
+ VPADD.S32 D29, D28, D28
+ MOV r14, r12, LSL #1 @exc[i] * a0 << 1
+ VDUP.S32 Q11, D29[0] @result2
+
+
+
+ VSHR.S32 Q10, Q10, #11 @result1 >>= 11
+ VSHL.S32 Q11, Q11, #1 @result2 <<= 1
+ VDUP.S32 Q12, r14
+ VADD.S32 Q12, Q12, Q10 @L_tmp = L_tmp - (result1 >>= 11) - (result2 <<= 1)
+ VSUB.S32 Q12, Q12, Q11
+
+ VSHL.S32 Q12, Q12, #3 @L_tmp <<= 3
+
+
+ VSHRN.S32 D20, Q12, #16 @sig_hi[i] = L_tmp >> 16@
+ VMOV.S16 r10, D20[0]
+ VSHR.S32 Q12, Q12, #4 @L_tmp >>= 4
+ VEXT.8 D7, D7, D20, #2
+ STRH r10, [r4], #2 @store sig_hi[i]
+ VMOV.S32 r11, D24[0] @r11 --- L_tmp >>= 4
+ ADD r8, r8, #1
+ SUB r12, r11, r10, LSL #12
+ @MOV r11, r12, ASR #16 @sig_lo[i]
+ VDUP.S16 D21, r12
+ VEXT.8 D11, D11, D21, #2
+ STRH r12, [r5], #2 @stroe sig_lo[i]
+
+ CMP r8, #64
+ BLT SYN_LOOP
+
+Syn_filt_32_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s
new file mode 100644
index 0000000..189e33b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/convolve_neon.s
@@ -0,0 +1,178 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@*void Convolve (
+@* Word16 x[], /* (i) : input vector */
+@* Word16 h[], /* (i) : impulse response */
+@* Word16 y[], /* (o) : output vector */
+@* Word16 L /* (i) : vector size */
+@*)
+@
+@ r0 --- x[]
+@ r1 --- h[]
+@ r2 --- y[]
+@ r3 --- L
+
+ .section .text
+ .global Convolve_asm
+
+Convolve_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ MOV r3, #0
+ MOV r11, #0x8000
+
+LOOP:
+ @MOV r8, #0 @ s = 0
+ ADD r4, r1, r3, LSL #1 @ tmpH address
+ ADD r5, r3, #1 @ i = n + 1
+ MOV r6, r0
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4] @ *tmpH--
+ SUB r5, r5, #1
+ VMOV.S32 Q10, #0
+ MUL r8, r9, r10
+
+LOOP1:
+ CMP r5, #0
+ BLE L1
+ SUB r4, r4, #8
+ MOV r9, r4
+ VLD1.S16 D0, [r6]!
+ VLD1.S16 D1, [r9]!
+ VREV64.16 D1, D1
+ SUBS r5, r5, #4
+ VMLAL.S16 Q10, D0, D1
+ B LOOP1
+L1:
+ VADD.S32 D20, D20, D21
+ VPADD.S32 D20, D20, D20
+ VMOV.S32 r5, D20[0]
+ ADD r5, r5, r8
+ ADD r5, r11, r5, LSL #1
+ MOV r5, r5, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r5, [r2], #2 @y[n]
+
+
+ @MOV r8, #0
+ ADD r4, r1, r3, LSL #1 @tmpH address
+ ADD r5, r3, #1
+ MOV r6, r0
+ LDRSH r9, [r6], #2 @ *tmpX++
+ LDRSH r10, [r4], #-2
+ LDRSH r12, [r6], #2
+ LDRSH r14, [r4]
+
+ MUL r8, r9, r10
+ SUB r5, r5, #2
+ MLA r8, r12, r14, r8
+
+ VMOV.S32 Q10, #0
+LOOP2:
+ CMP r5, #0
+ BLE L2
+ SUB r4, r4, #8
+ MOV r9, r4
+ VLD1.S16 D0, [r6]!
+ VLD1.S16 D1, [r9]!
+ SUBS r5, r5, #4
+ VREV64.16 D1, D1
+ VMLAL.S16 Q10, D0, D1
+ B LOOP2
+L2:
+ VADD.S32 D20, D20, D21
+ VPADD.S32 D20, D20, D20
+ VMOV.S32 r5, D20[0]
+ ADD r8, r8, r5
+ ADD r8, r11, r8, LSL #1
+ MOV r8, r8, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r8, [r2], #2 @y[n]
+
+
+ @MOV r8, #0
+ ADD r4, r1, r3, LSL #1
+ ADD r5, r3, #1
+ MOV r6, r0
+ LDRSH r9, [r6], #2
+ LDRSH r10, [r4], #-2
+ LDRSH r12, [r6], #2
+ LDRSH r14, [r4], #-2
+ MUL r8, r9, r10
+ LDRSH r9, [r6], #2
+ LDRSH r10, [r4]
+ MLA r8, r12, r14, r8
+ SUB r5, r5, #3
+ MLA r8, r9, r10, r8
+
+ VMOV.S32 Q10, #0
+LOOP3:
+ CMP r5, #0
+ BLE L3
+ SUB r4, r4, #8
+ MOV r9, r4
+ VLD1.S16 D0, [r6]!
+ VLD1.S16 D1, [r9]!
+ VREV64.16 D1, D1
+ SUBS r5, r5, #4
+ VMLAL.S16 Q10, D0, D1
+ B LOOP3
+
+L3:
+ VADD.S32 D20, D20, D21
+ VPADD.S32 D20, D20, D20
+ VMOV.S32 r5, D20[0]
+ ADD r8, r8, r5
+ ADD r8, r11, r8, LSL #1
+ MOV r8, r8, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r8, [r2], #2 @y[n]
+
+ ADD r5, r3, #1 @ i = n + 1
+ ADD r4, r1, r5, LSL #1 @ tmpH address
+ MOV r6, r0
+ VMOV.S32 Q10, #0
+LOOP4:
+ CMP r5, #0
+ BLE L4
+ SUB r4, r4, #8
+ MOV r9, r4
+ VLD1.S16 D0, [r6]!
+ VLD1.S16 D1, [r9]!
+ VREV64.16 D1, D1
+ SUBS r5, r5, #4
+ VMLAL.S16 Q10, D0, D1
+ B LOOP4
+L4:
+ VADD.S32 D20, D20, D21
+ VPADD.S32 D20, D20, D20
+ VMOV.S32 r5, D20[0]
+ ADD r5, r11, r5, LSL #1
+ MOV r5, r5, LSR #16 @extract_h(s)
+ ADD r3, r3, #1
+ STRH r5, [r2], #2 @y[n]
+
+ CMP r3, #64
+ BLT LOOP
+
+Convolve_asm_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+
+ @ENDFUNC
+ .END
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s
new file mode 100644
index 0000000..2e339db
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/cor_h_vec_neon.s
@@ -0,0 +1,151 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@static void cor_h_vec_012(
+@ Word16 h[], /* (i) scaled impulse response */
+@ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+@ Word16 track, /* (i) track to use */
+@ Word16 sign[], /* (i) sign vector */
+@ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+@ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+@ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+@)
+@r0 ---- h[]
+@r1 ---- vec[]
+@r2 ---- track
+@r3 ---- sign[]
+@r4 ---- rrixix[][NB_POS]
+@r5 ---- cor_1[]
+@r6 ---- cor_2[]
+
+ .section .text
+ .global cor_h_vec_012_asm
+
+cor_h_vec_012_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ LDR r4, [r13, #40] @load rrixix[][NB_POS]
+ ADD r7, r4, r2, LSL #5 @r7 --- p0 = rrixix[track]
+ MOV r4, #0 @i=0
+
+ @r0 --- h[], r1 --- vec[], r2 --- pos
+ @r3 --- sign[], r4 --- i, r7 --- p0
+
+LOOPi:
+ MOV r5, #0 @L_sum1 = 0
+ MOV r6, #0 @L_sum2 = 0
+ ADD r9, r1, r2, LSL #1 @p2 = &vec[pos]
+ MOV r10, r0 @p1 = h
+ RSB r11, r2, #62 @j=62-pos
+
+LOOPj1:
+ LDRSH r12, [r10], #2
+ LDRSH r8, [r9], #2
+ LDRSH r14, [r9]
+ SUBS r11, r11, #1
+ MLA r5, r12, r8, r5
+ MLA r6, r12, r14, r6
+ BGE LOOPj1
+
+ LDRSH r12, [r10], #2 @*p1++
+ MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2)
+ MLA r5, r12, r14, r5
+ MOV r14, #0x8000
+ MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2)
+ ADD r10, r6, r14
+ ADD r9, r5, r14
+ MOV r5, r9, ASR #16
+ MOV r6, r10, ASR #16
+ ADD r9, r3, r2, LSL #1 @address of sign[pos]
+ ADD r8, r7, #32
+ LDRSH r10, [r9], #2 @sign[pos]
+ LDRSH r11, [r9] @sign[pos + 1]
+ MUL r12, r5, r10
+ MUL r14, r6, r11
+ MOV r5, r12, ASR #15
+ MOV r6, r14, ASR #15
+ LDR r9, [r13, #44]
+ LDR r12, [r13, #48]
+ LDRSH r10, [r7], #2 @*p0++
+ LDRSH r11, [r8] @*p3++
+ ADD r9, r9, r4, LSL #1
+ ADD r12, r12, r4, LSL #1
+ ADD r5, r5, r10
+ ADD r6, r6, r11
+ STRH r5, [r9]
+ STRH r6, [r12]
+
+ ADD r2, r2, #4
+
+ MOV r5, #0 @L_sum1 = 0
+ MOV r6, #0 @L_sum2 = 0
+ ADD r9, r1, r2, LSL #1 @p2 = &vec[pos]
+ MOV r10, r0 @p1 = h
+ RSB r11, r2, #62 @j=62-pos
+ ADD r4, r4, #1 @i++
+
+LOOPj2:
+ LDRSH r12, [r10], #2
+ LDRSH r8, [r9], #2
+ LDRSH r14, [r9]
+ SUBS r11, r11, #1
+ MLA r5, r12, r8, r5
+ MLA r6, r12, r14, r6
+ BGE LOOPj2
+
+ LDRSH r12, [r10], #2 @*p1++
+ MOV r6, r6, LSL #2 @L_sum2 = (L_sum2 << 2)
+ MLA r5, r12, r14, r5
+ MOV r14, #0x8000
+ MOV r5, r5, LSL #2 @L_sum1 = (L_sum1 << 2)
+ ADD r10, r6, r14
+ ADD r9, r5, r14
+
+ MOV r5, r9, ASR #16
+ MOV r6, r10, ASR #16
+ ADD r9, r3, r2, LSL #1 @address of sign[pos]
+ ADD r8, r7, #32
+ LDRSH r10, [r9], #2 @sign[pos]
+ LDRSH r11, [r9] @sign[pos + 1]
+ MUL r12, r5, r10
+ MUL r14, r6, r11
+ MOV r5, r12, ASR #15
+ MOV r6, r14, ASR #15
+ LDR r9, [r13, #44]
+ LDR r12, [r13, #48]
+ LDRSH r10, [r7], #2 @*p0++
+ LDRSH r11, [r8] @*p3++
+ ADD r9, r9, r4, LSL #1
+ ADD r12, r12, r4, LSL #1
+ ADD r5, r5, r10
+ ADD r6, r6, r11
+ STRH r5, [r9]
+ STRH r6, [r12]
+ ADD r4, r4, #1 @i+1
+ ADD r2, r2, #4 @pos += STEP
+ CMP r4, #16
+
+ BLT LOOPi
+
+the_end:
+ LDMFD r13!, {r4 - r12, r15}
+
+ .END
+
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
new file mode 100644
index 0000000..3b8853f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/pred_lt4_1_neon.s
@@ -0,0 +1,100 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Pred_lt4(
+@ Word16 exc[], /* in/out: excitation buffer */
+@ Word16 T0, /* input : integer pitch lag */
+@ Word16 frac, /* input : fraction of lag */
+@ Word16 L_subfr /* input : subframe size */
+@)
+@***********************************************************************
+@ r0 --- exc[]
+@ r1 --- T0
+@ r2 --- frac
+@ r3 --- L_subfr
+
+ .section .text
+ .global pred_lt4_asm
+ .extern inter4_2
+
+pred_lt4_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r4, r0, r1, LSL #1 @ x = exc - T0
+ RSB r2, r2, #0 @ frac = - frac
+ SUB r4, r4, #30 @ x -= L_INTERPOL2 - 1
+ CMP r2, #0
+ ADDLT r2, r2, #4 @ frac += UP_SAMP
+ SUBLT r4, r4, #2 @ x--
+
+ LDR r11, Lable1
+ RSB r2, r2, #3 @ k = UP_SAMP - 1 - frac
+ MOV r8, #0 @ j = 0
+ ADD r11, r11, r2, LSL #6 @ get inter4_2[k][]
+
+ VLD1.S16 {Q0, Q1}, [r11]!
+ VLD1.S16 {Q2, Q3}, [r11]!
+
+ MOV r6, #0x8000
+
+ VLD1.S16 {Q4, Q5}, [r4]! @load 16 x[]
+ VLD1.S16 {Q6, Q7}, [r4]! @load 16 x[]
+
+LOOP:
+ VQDMULL.S16 Q15, D8, D0
+ VQDMLAL.S16 Q15, D9, D1
+ VQDMLAL.S16 Q15, D10, D2
+ VQDMLAL.S16 Q15, D11, D3
+
+ VQDMLAL.S16 Q15, D12, D4
+ VQDMLAL.S16 Q15, D13, D5
+ VQDMLAL.S16 Q15, D14, D6
+ VQDMLAL.S16 Q15, D15, D7
+
+ LDRSH r12, [r4], #2
+
+ VEXT.S16 D8, D8, D9, #1
+ VEXT.S16 D9, D9, D10, #1
+ VEXT.S16 D10, D10, D11, #1
+ VEXT.S16 D11, D11, D12, #1
+ VDUP.S16 D24, r12
+ VEXT.S16 D12, D12, D13, #1
+ VEXT.S16 D13, D13, D14, #1
+
+ VQADD.S32 D30, D30, D31
+ MOV r11, #0x8000
+ VPADD.S32 D30, D30, D30
+ ADD r8, r8, #1
+ VMOV.S32 r12, D30[0]
+ VEXT.S16 D14, D14, D15, #1
+
+ QADD r1, r12, r12 @ L_sum = (L_sum << 2)
+ VEXT.S16 D15, D15, D24, #1
+ QADD r5, r1, r6
+ MOV r1, r5, ASR #16
+ CMP r8, r3
+ STRH r1, [r0], #2 @ exc[j] = (L_sum + 0x8000) >> 16
+ BLT LOOP
+
+pred_lt4_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+
+Lable1:
+ .word inter4_2
+ @ENDFUNC
+ .END
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s
new file mode 100644
index 0000000..b9e6b23
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/residu_asm_neon.s
@@ -0,0 +1,127 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Residu (
+@ Word16 a[], /* (i) : prediction coefficients */
+@ Word16 x[], /* (i) : speech signal */
+@ Word16 y[], /* (o) : residual signal */
+@ Word16 lg /* (i) : size of filtering */
+@)
+@a[] RN r0
+@x[] RN r1
+@y[] RN r2
+@lg RN r3
+
+ .section .text
+ .global Residu_opt
+
+Residu_opt:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r7, r3, #4 @i = lg - 4
+
+ VLD1.S16 {D0, D1, D2, D3}, [r0]! @get all a[]
+ VLD1.S16 {D4}, [r0]!
+ VMOV.S32 Q8, #0x8000
+
+LOOP1:
+ ADD r9, r1, r7, LSL #1 @copy the address
+ ADD r10, r2, r7, LSL #1
+ MOV r8, r9
+ VLD1.S16 D5, [r8]! @get x[i], x[i+1], x[i+2], x[i+3]
+ VQDMULL.S16 Q10, D5, D0[0] @finish the first L_mult
+
+ SUB r8, r9, #2 @get the x[i-1] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D0[1]
+
+ SUB r8, r9, #4 @load the x[i-2] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D0[2]
+
+ SUB r8, r9, #6 @load the x[i-3] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D0[3]
+
+ SUB r8, r9, #8 @load the x[i-4] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D1[0]
+
+ SUB r8, r9, #10 @load the x[i-5] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D1[1]
+
+ SUB r8, r9, #12 @load the x[i-6] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D1[2]
+
+ SUB r8, r9, #14 @load the x[i-7] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D1[3]
+
+ SUB r8, r9, #16 @load the x[i-8] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D2[0]
+
+ SUB r8, r9, #18 @load the x[i-9] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D2[1]
+
+ SUB r8, r9, #20 @load the x[i-10] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D2[2]
+
+ SUB r8, r9, #22 @load the x[i-11] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D2[3]
+
+ SUB r8, r9, #24 @load the x[i-12] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D3[0]
+
+ SUB r8, r9, #26 @load the x[i-13] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D3[1]
+
+ SUB r8, r9, #28 @load the x[i-14] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D3[2]
+
+ SUB r8, r9, #30 @load the x[i-15] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D3[3]
+
+ SUB r8, r9, #32 @load the x[i-16] address
+ VLD1.S16 D5, [r8]!
+ VQDMLAL.S16 Q10, D5, D4[0]
+
+ SUB r7, r7, #4 @i-=4
+ VQSHL.S32 Q10, Q10, #4
+ VQADD.S32 Q10, Q10, Q8
+ VSHRN.S32 D5, Q10, #16
+ VST1.S16 D5, [r10]!
+ CMP r7, #0
+
+ BGE LOOP1
+
+Residu_asm_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s
new file mode 100644
index 0000000..14957d8
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/scale_sig_neon.s
@@ -0,0 +1,138 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@**********************************************************************/
+@void Scale_sig(
+@ Word16 x[], /* (i/o) : signal to scale */
+@ Word16 lg, /* (i) : size of x[] */
+@ Word16 exp /* (i) : exponent: x = round(x << exp) */
+@)
+@***********************************************************************
+@ x[] --- r0
+@ lg --- r1
+@ exp --- r2
+
+ .section .text
+ .global Scale_sig_opt
+
+Scale_sig_opt:
+
+ STMFD r13!, {r4 - r12, r14}
+ MOV r4, #4
+ VMOV.S32 Q15, #0x8000
+ VDUP.S32 Q14, r2
+ MOV r5, r0 @ copy x[] address
+ CMP r1, #64
+ MOVEQ r4, #1
+ BEQ LOOP
+ CMP r1, #128
+ MOVEQ r4, #2
+ BEQ LOOP
+ CMP r1, #256
+ BEQ LOOP
+ CMP r1, #80
+ MOVEQ r4, #1
+ BEQ LOOP1
+
+LOOP1:
+ VLD1.S16 {Q0, Q1}, [r5]! @load 16 Word16 x[]
+ VSHLL.S16 Q10, D0, #16
+ VSHLL.S16 Q11, D1, #16
+ VSHLL.S16 Q12, D2, #16
+ VSHLL.S16 Q13, D3, #16
+ VSHL.S32 Q10, Q10, Q14
+ VSHL.S32 Q11, Q11, Q14
+ VSHL.S32 Q12, Q12, Q14
+ VSHL.S32 Q13, Q13, Q14
+ VADDHN.S32 D16, Q10, Q15
+ VADDHN.S32 D17, Q11, Q15
+ VADDHN.S32 D18, Q12, Q15
+ VADDHN.S32 D19, Q13, Q15
+ VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[]
+
+LOOP:
+ VLD1.S16 {Q0, Q1}, [r5]! @load 16 Word16 x[]
+ VLD1.S16 {Q2, Q3}, [r5]! @load 16 Word16 x[]
+ VLD1.S16 {Q4, Q5}, [r5]! @load 16 Word16 x[]
+ VLD1.S16 {Q6, Q7}, [r5]! @load 16 Word16 x[]
+
+ VSHLL.S16 Q8, D0, #16
+ VSHLL.S16 Q9, D1, #16
+ VSHLL.S16 Q10, D2, #16
+ VSHLL.S16 Q11, D3, #16
+ VSHL.S32 Q8, Q8, Q14
+ VSHL.S32 Q9, Q9, Q14
+ VSHL.S32 Q10, Q10, Q14
+ VSHL.S32 Q11, Q11, Q14
+ VADDHN.S32 D16, Q8, Q15
+ VADDHN.S32 D17, Q9, Q15
+ VADDHN.S32 D18, Q10, Q15
+ VADDHN.S32 D19, Q11, Q15
+ VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[]
+
+
+ VSHLL.S16 Q12, D4, #16
+ VSHLL.S16 Q13, D5, #16
+ VSHLL.S16 Q10, D6, #16
+ VSHLL.S16 Q11, D7, #16
+ VSHL.S32 Q12, Q12, Q14
+ VSHL.S32 Q13, Q13, Q14
+ VSHL.S32 Q10, Q10, Q14
+ VSHL.S32 Q11, Q11, Q14
+ VADDHN.S32 D16, Q12, Q15
+ VADDHN.S32 D17, Q13, Q15
+ VADDHN.S32 D18, Q10, Q15
+ VADDHN.S32 D19, Q11, Q15
+ VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[]
+
+ VSHLL.S16 Q10, D8, #16
+ VSHLL.S16 Q11, D9, #16
+ VSHLL.S16 Q12, D10, #16
+ VSHLL.S16 Q13, D11, #16
+ VSHL.S32 Q10, Q10, Q14
+ VSHL.S32 Q11, Q11, Q14
+ VSHL.S32 Q12, Q12, Q14
+ VSHL.S32 Q13, Q13, Q14
+ VADDHN.S32 D16, Q10, Q15
+ VADDHN.S32 D17, Q11, Q15
+ VADDHN.S32 D18, Q12, Q15
+ VADDHN.S32 D19, Q13, Q15
+ VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[]
+
+ VSHLL.S16 Q10, D12, #16
+ VSHLL.S16 Q11, D13, #16
+ VSHLL.S16 Q12, D14, #16
+ VSHLL.S16 Q13, D15, #16
+ VSHL.S32 Q10, Q10, Q14
+ VSHL.S32 Q11, Q11, Q14
+ VSHL.S32 Q12, Q12, Q14
+ VSHL.S32 Q13, Q13, Q14
+ VADDHN.S32 D16, Q10, Q15
+ VADDHN.S32 D17, Q11, Q15
+ VADDHN.S32 D18, Q12, Q15
+ VADDHN.S32 D19, Q13, Q15
+ VST1.S16 {Q8, Q9}, [r0]! @store 16 Word16 x[]
+ SUBS r4, r4, #1
+ BGT LOOP
+
+
+Scale_sig_asm_end:
+
+ LDMFD r13!, {r4 - r12, r15}
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s
new file mode 100644
index 0000000..dc3d4a8
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/asm/ARMV7/syn_filt_neon.s
@@ -0,0 +1,106 @@
+@/*
+@ ** Copyright 2003-2010, VisualOn, Inc.
+@ **
+@ ** Licensed under the Apache License, Version 2.0 (the "License");
+@ ** you may not use this file except in compliance with the License.
+@ ** You may obtain a copy of the License at
+@ **
+@ ** http://www.apache.org/licenses/LICENSE-2.0
+@ **
+@ ** Unless required by applicable law or agreed to in writing, software
+@ ** distributed under the License is distributed on an "AS IS" BASIS,
+@ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@ ** See the License for the specific language governing permissions and
+@ ** limitations under the License.
+@ */
+@
+@void Syn_filt(
+@ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+@ Word16 x[], /* (i) : input signal */
+@ Word16 y[], /* (o) : output signal */
+@ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+@)
+@***********************************************************************
+@ a[] --- r0
+@ x[] --- r1
+@ y[] --- r2
+@ mem[] --- r3
+@ m --- 16 lg --- 80 update --- 1
+
+ .section .text
+ .global Syn_filt_asm
+
+Syn_filt_asm:
+
+ STMFD r13!, {r4 - r12, r14}
+ SUB r13, r13, #700 @ y_buf[L_FRAME16k + M16k]
+
+ MOV r4, r3 @ copy mem[] address
+ MOV r5, r13 @ copy yy = y_buf address
+
+ @ for(i = 0@ i < m@ i++)
+ @{
+ @ *yy++ = mem[i]@
+ @}
+ VLD1.S16 {D0, D1, D2, D3}, [r4]! @load 16 mems
+ VST1.S16 {D0, D1, D2, D3}, [r5]! @store 16 mem[] to *yy
+
+ LDRSH r5, [r0], #2 @ load a[0]
+ MOV r8, #0 @ i = 0
+ MOV r5, r5, ASR #1 @ a0 = a[0] >> 1
+ VMOV.S16 D8[0], r5
+ @ load all a[]
+ VLD1.S16 {D0, D1, D2, D3}, [r0]! @ load a[1] ~ a[16]
+ VREV64.16 D0, D0
+ VREV64.16 D1, D1
+ VREV64.16 D2, D2
+ VREV64.16 D3, D3
+ MOV r8, #0 @ loop times
+ MOV r10, r13 @ temp = y_buf
+ ADD r4, r13, #32 @ yy[i] address
+
+ VLD1.S16 {D4, D5, D6, D7}, [r10]! @ first 16 temp_p
+
+SYN_LOOP:
+
+ LDRSH r6, [r1], #2 @ load x[i]
+ MUL r12, r6, r5 @ L_tmp = x[i] * a0
+ ADD r10, r4, r8, LSL #1 @ y[i], yy[i] address
+
+ VDUP.S32 Q10, r12
+ VMULL.S16 Q5, D3, D4
+ VMLAL.S16 Q5, D2, D5
+ VMLAL.S16 Q5, D1, D6
+ VMLAL.S16 Q5, D0, D7
+ VEXT.8 D4, D4, D5, #2
+ VEXT.8 D5, D5, D6, #2
+ VEXT.8 D6, D6, D7, #2
+ VPADD.S32 D12, D10, D11
+ ADD r8, r8, #1
+ VPADD.S32 D10, D12, D12
+
+ VDUP.S32 Q7, D10[0]
+
+ VSUB.S32 Q9, Q10, Q7
+ VQRSHRN.S32 D20, Q9, #12
+ VMOV.S16 r9, D20[0]
+ VEXT.8 D7, D7, D20, #2
+ CMP r8, #80
+ STRH r9, [r10] @ yy[i]
+ STRH r9, [r2], #2 @ y[i]
+
+ BLT SYN_LOOP
+
+ @ update mem[]
+ ADD r5, r13, #160 @ yy[64] address
+ VLD1.S16 {D0, D1, D2, D3}, [r5]!
+ VST1.S16 {D0, D1, D2, D3}, [r3]!
+
+Syn_filt_asm_end:
+
+ ADD r13, r13, #700
+ LDMFD r13!, {r4 - r12, r15}
+ @ENDFUNC
+ .END
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/autocorr.c b/media/libstagefright/codecs/amrwbenc/src/autocorr.c
new file mode 100644
index 0000000..33ed670
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/autocorr.c
@@ -0,0 +1,127 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: autocorr.c *
+* *
+* Description:Compute autocorrelations of signal with windowing *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+#include "ham_wind.tab"
+
+void Autocorr(
+ Word16 x[], /* (i) : Input signal */
+ Word16 m, /* (i) : LPC order */
+ Word16 r_h[], /* (o) Q15: Autocorrelations (msb) */
+ Word16 r_l[] /* (o) : Autocorrelations (lsb) */
+ )
+{
+ Word32 i, norm, shift;
+ Word16 y[L_WINDOW];
+ Word32 L_sum, L_sum1, L_tmp, F_LEN;
+ Word16 *p1,*p2,*p3;
+ const Word16 *p4;
+ /* Windowing of signal */
+ p1 = x;
+ p4 = vo_window;
+ p3 = y;
+
+ for (i = 0; i < L_WINDOW; i+=4)
+ {
+ *p3++ = vo_mult_r((*p1++), (*p4++));
+ *p3++ = vo_mult_r((*p1++), (*p4++));
+ *p3++ = vo_mult_r((*p1++), (*p4++));
+ *p3++ = vo_mult_r((*p1++), (*p4++));
+ }
+
+ /* calculate energy of signal */
+ L_sum = vo_L_deposit_h(16); /* sqrt(256), avoid overflow after rounding */
+ for (i = 0; i < L_WINDOW; i++)
+ {
+ L_tmp = vo_L_mult(y[i], y[i]);
+ L_tmp = (L_tmp >> 8);
+ L_sum += L_tmp;
+ }
+
+ /* scale signal to avoid overflow in autocorrelation */
+ norm = norm_l(L_sum);
+ shift = 4 - (norm >> 1);
+ if(shift > 0)
+ {
+ p1 = y;
+ for (i = 0; i < L_WINDOW; i+=4)
+ {
+ *p1 = vo_shr_r(*p1, shift);
+ p1++;
+ *p1 = vo_shr_r(*p1, shift);
+ p1++;
+ *p1 = vo_shr_r(*p1, shift);
+ p1++;
+ *p1 = vo_shr_r(*p1, shift);
+ p1++;
+ }
+ }
+
+ /* Compute and normalize r[0] */
+ L_sum = 1;
+ for (i = 0; i < L_WINDOW; i+=4)
+ {
+ L_sum += vo_L_mult(y[i], y[i]);
+ L_sum += vo_L_mult(y[i+1], y[i+1]);
+ L_sum += vo_L_mult(y[i+2], y[i+2]);
+ L_sum += vo_L_mult(y[i+3], y[i+3]);
+ }
+
+ norm = norm_l(L_sum);
+ L_sum = (L_sum << norm);
+
+ r_h[0] = L_sum >> 16;
+ r_l[0] = (L_sum & 0xffff)>>1;
+
+ /* Compute r[1] to r[m] */
+ for (i = 1; i <= 8; i++)
+ {
+ L_sum1 = 0;
+ L_sum = 0;
+ F_LEN = (Word32)(L_WINDOW - 2*i);
+ p1 = y;
+ p2 = y + (2*i)-1;
+ do{
+ L_sum1 += *p1 * *p2++;
+ L_sum += *p1++ * *p2;
+ }while(--F_LEN!=0);
+
+ L_sum1 += *p1 * *p2++;
+
+ L_sum1 = L_sum1<<norm;
+ L_sum = L_sum<<norm;
+
+ r_h[(2*i)-1] = L_sum1 >> 15;
+ r_l[(2*i)-1] = L_sum1 & 0x00007fff;
+ r_h[(2*i)] = L_sum >> 15;
+ r_l[(2*i)] = L_sum & 0x00007fff;
+ }
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/az_isp.c b/media/libstagefright/codecs/amrwbenc/src/az_isp.c
new file mode 100644
index 0000000..8259f91
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/az_isp.c
@@ -0,0 +1,268 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: az_isp.c
+*
+* Description:
+*-----------------------------------------------------------------------*
+* Compute the ISPs from the LPC coefficients (order=M) *
+*-----------------------------------------------------------------------*
+* *
+* The ISPs are the roots of the two polynomials F1(z) and F2(z) *
+* defined as *
+* F1(z) = A(z) + z^-m A(z^-1) *
+* and F2(z) = A(z) - z^-m A(z^-1) *
+* *
+* For a even order m=2n, F1(z) has M/2 conjugate roots on the unit *
+* circle and F2(z) has M/2-1 conjugate roots on the unit circle in *
+* addition to two roots at 0 and pi. *
+* *
+* For a 16th order LP analysis, F1(z) and F2(z) can be written as *
+* *
+* F1(z) = (1 + a[M]) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
+* i=0,2,4,6,8,10,12,14 *
+* *
+* F2(z) = (1 - a[M]) (1 - z^-2) PRODUCT (1 - 2 cos(w_i) z^-1 + z^-2 ) *
+* i=1,3,5,7,9,11,13 *
+* *
+* The ISPs are the M-1 frequencies w_i, i=0...M-2 plus the last *
+* predictor coefficient a[M]. *
+*-----------------------------------------------------------------------*
+
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "stdio.h"
+#include "grid100.tab"
+
+#define M 16
+#define NC (M/2)
+
+/* local function */
+static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n);
+
+void Az_isp(
+ Word16 a[], /* (i) Q12 : predictor coefficients */
+ Word16 isp[], /* (o) Q15 : Immittance spectral pairs */
+ Word16 old_isp[] /* (i) : old isp[] (in case not found M roots) */
+ )
+{
+ Word32 i, j, nf, ip, order;
+ Word16 xlow, ylow, xhigh, yhigh, xmid, ymid, xint;
+ Word16 x, y, sign, exp;
+ Word16 *coef;
+ Word16 f1[NC + 1], f2[NC];
+ Word32 t0;
+ /*-------------------------------------------------------------*
+ * find the sum and diff polynomials F1(z) and F2(z) *
+ * F1(z) = [A(z) + z^M A(z^-1)] *
+ * F2(z) = [A(z) - z^M A(z^-1)]/(1-z^-2) *
+ * *
+ * for (i=0; i<NC; i++) *
+ * { *
+ * f1[i] = a[i] + a[M-i]; *
+ * f2[i] = a[i] - a[M-i]; *
+ * } *
+ * f1[NC] = 2.0*a[NC]; *
+ * *
+ * for (i=2; i<NC; i++) Divide by (1-z^-2) *
+ * f2[i] += f2[i-2]; *
+ *-------------------------------------------------------------*/
+ for (i = 0; i < NC; i++)
+ {
+ t0 = a[i] << 15;
+ f1[i] = vo_round(t0 + (a[M - i] << 15)); /* =(a[i]+a[M-i])/2 */
+ f2[i] = vo_round(t0 - (a[M - i] << 15)); /* =(a[i]-a[M-i])/2 */
+ }
+ f1[NC] = a[NC];
+ for (i = 2; i < NC; i++) /* Divide by (1-z^-2) */
+ f2[i] = add1(f2[i], f2[i - 2]);
+
+ /*---------------------------------------------------------------------*
+ * Find the ISPs (roots of F1(z) and F2(z) ) using the *
+ * Chebyshev polynomial evaluation. *
+ * The roots of F1(z) and F2(z) are alternatively searched. *
+ * We start by finding the first root of F1(z) then we switch *
+ * to F2(z) then back to F1(z) and so on until all roots are found. *
+ * *
+ * - Evaluate Chebyshev pol. at grid points and check for sign change.*
+ * - If sign change track the root by subdividing the interval *
+ * 2 times and ckecking sign change. *
+ *---------------------------------------------------------------------*/
+ nf = 0; /* number of found frequencies */
+ ip = 0; /* indicator for f1 or f2 */
+ coef = f1;
+ order = NC;
+ xlow = vogrid[0];
+ ylow = Chebps2(xlow, coef, order);
+ j = 0;
+ while ((nf < M - 1) && (j < GRID_POINTS))
+ {
+ j ++;
+ xhigh = xlow;
+ yhigh = ylow;
+ xlow = vogrid[j];
+ ylow = Chebps2(xlow, coef, order);
+ if ((ylow * yhigh) <= (Word32) 0)
+ {
+ /* divide 2 times the interval */
+ for (i = 0; i < 2; i++)
+ {
+ xmid = (xlow >> 1) + (xhigh >> 1); /* xmid = (xlow + xhigh)/2 */
+ ymid = Chebps2(xmid, coef, order);
+ if ((ylow * ymid) <= (Word32) 0)
+ {
+ yhigh = ymid;
+ xhigh = xmid;
+ } else
+ {
+ ylow = ymid;
+ xlow = xmid;
+ }
+ }
+ /*-------------------------------------------------------------*
+ * Linear interpolation *
+ * xint = xlow - ylow*(xhigh-xlow)/(yhigh-ylow); *
+ *-------------------------------------------------------------*/
+ x = xhigh - xlow;
+ y = yhigh - ylow;
+ if (y == 0)
+ {
+ xint = xlow;
+ } else
+ {
+ sign = y;
+ y = abs_s(y);
+ exp = norm_s(y);
+ y = y << exp;
+ y = div_s((Word16) 16383, y);
+ t0 = x * y;
+ t0 = (t0 >> (19 - exp));
+ y = vo_extract_l(t0); /* y= (xhigh-xlow)/(yhigh-ylow) in Q11 */
+ if (sign < 0)
+ y = -y;
+ t0 = ylow * y; /* result in Q26 */
+ t0 = (t0 >> 10); /* result in Q15 */
+ xint = vo_sub(xlow, vo_extract_l(t0)); /* xint = xlow - ylow*y */
+ }
+ isp[nf] = xint;
+ xlow = xint;
+ nf++;
+ if (ip == 0)
+ {
+ ip = 1;
+ coef = f2;
+ order = NC - 1;
+ } else
+ {
+ ip = 0;
+ coef = f1;
+ order = NC;
+ }
+ ylow = Chebps2(xlow, coef, order);
+ }
+ }
+ /* Check if M-1 roots found */
+ if(nf < M - 1)
+ {
+ for (i = 0; i < M; i++)
+ {
+ isp[i] = old_isp[i];
+ }
+ } else
+ {
+ isp[M - 1] = a[M] << 3; /* From Q12 to Q15 with saturation */
+ }
+ return;
+}
+
+/*--------------------------------------------------------------*
+* function Chebps2: *
+* ~~~~~~~ *
+* Evaluates the Chebishev polynomial series *
+*--------------------------------------------------------------*
+* *
+* The polynomial order is *
+* n = M/2 (M is the prediction order) *
+* The polynomial is given by *
+* C(x) = f(0)T_n(x) + f(1)T_n-1(x) + ... +f(n-1)T_1(x) + f(n)/2 *
+* Arguments: *
+* x: input value of evaluation; x = cos(frequency) in Q15 *
+* f[]: coefficients of the pol. in Q11 *
+* n: order of the pol. *
+* *
+* The value of C(x) is returned. (Satured to +-1.99 in Q14) *
+* *
+*--------------------------------------------------------------*/
+
+static __inline Word16 Chebps2(Word16 x, Word16 f[], Word32 n)
+{
+ Word32 i, cheb;
+ Word16 b0_h, b0_l, b1_h, b1_l, b2_h, b2_l;
+ Word32 t0;
+
+ /* Note: All computation are done in Q24. */
+
+ t0 = f[0] << 13;
+ b2_h = t0 >> 16;
+ b2_l = (t0 & 0xffff)>>1;
+
+ t0 = ((b2_h * x)<<1) + (((b2_l * x)>>15)<<1);
+ t0 <<= 1;
+ t0 += (f[1] << 13); /* + f[1] in Q24 */
+
+ b1_h = t0 >> 16;
+ b1_l = (t0 & 0xffff) >> 1;
+
+ for (i = 2; i < n; i++)
+ {
+ t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);
+
+ t0 += (b2_h * (-16384))<<1;
+ t0 += (f[i] << 12);
+ t0 <<= 1;
+ t0 -= (b2_l << 1); /* t0 = 2.0*x*b1 - b2 + f[i]; */
+
+ b0_h = t0 >> 16;
+ b0_l = (t0 & 0xffff) >> 1;
+
+ b2_l = b1_l; /* b2 = b1; */
+ b2_h = b1_h;
+ b1_l = b0_l; /* b1 = b0; */
+ b1_h = b0_h;
+ }
+
+ t0 = ((b1_h * x)<<1) + (((b1_l * x)>>15)<<1);
+ t0 += (b2_h * (-32768))<<1; /* t0 = x*b1 - b2 */
+ t0 -= (b2_l << 1);
+ t0 += (f[n] << 12); /* t0 = x*b1 - b2 + f[i]/2 */
+
+ t0 = L_shl2(t0, 6); /* Q24 to Q30 with saturation */
+
+ cheb = extract_h(t0); /* Result in Q14 */
+
+ if (cheb == -32768)
+ {
+ cheb = -32767; /* to avoid saturation in Az_isp */
+ }
+ return (cheb);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/bits.c b/media/libstagefright/codecs/amrwbenc/src/bits.c
new file mode 100644
index 0000000..90d1a00
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/bits.c
@@ -0,0 +1,210 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: bits.c
+
+ Description: Performs bit stream manipulation
+
+************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "bits.h"
+#include "acelp.h"
+#include "dtx.h"
+#include "mime_io.tab"
+
+
+int PackBits(Word16 prms[], /* i: analysis parameters */
+ Word16 coding_mode, /* i: coding bit-stream ratio mode */
+ Word16 mode, /* i: coding bit-stream ratio mode*/
+ Coder_State *st /*i/o: coder global parameters struct */
+ )
+{
+ Word16 i, frame_type;
+ UWord8 temp;
+ UWord8 *stream_ptr;
+ Word16 bitstreamformat = st->frameType;
+
+ unsigned short* dataOut = st->outputStream;
+
+ if (coding_mode == MRDTX)
+ {
+ st->sid_update_counter--;
+
+ if (st->prev_ft == TX_SPEECH)
+ {
+ frame_type = TX_SID_FIRST;
+ st->sid_update_counter = 3;
+ } else
+ {
+ if ((st->sid_handover_debt > 0) && (st->sid_update_counter > 2))
+ {
+ /* ensure extra updates are properly delayed after a possible SID_FIRST */
+ frame_type = TX_SID_UPDATE;
+ st->sid_handover_debt--;
+ } else
+ {
+ if (st->sid_update_counter == 0)
+ {
+ frame_type = TX_SID_UPDATE;
+ st->sid_update_counter = 8;
+ } else
+ {
+ frame_type = TX_NO_DATA;
+ }
+ }
+ }
+ } else
+ {
+ st->sid_update_counter = 8;
+ frame_type = TX_SPEECH;
+ }
+ st->prev_ft = frame_type;
+
+ if(bitstreamformat == 0) /* default file format */
+ {
+ *(dataOut) = TX_FRAME_TYPE;
+ *(dataOut + 1) = frame_type;
+ *(dataOut + 2) = mode;
+ for (i = 0; i < nb_of_bits[coding_mode]; i++)
+ {
+ *(dataOut + 3 + i) = prms[i];
+ }
+ return (3 + nb_of_bits[coding_mode])<<1;
+ } else
+ {
+ if (bitstreamformat == 1) /* ITU file format */
+ {
+ *(dataOut) = 0x6b21;
+ if(frame_type != TX_NO_DATA && frame_type != TX_SID_FIRST)
+ {
+ *(dataOut + 1) = nb_of_bits[coding_mode];
+ for (i = 0; i < nb_of_bits[coding_mode]; i++)
+ {
+ if(prms[i] == BIT_0){
+ *(dataOut + 2 + i) = BIT_0_ITU;
+ }
+ else{
+ *(dataOut + 2 + i) = BIT_1_ITU;
+ }
+ }
+ return (2 + nb_of_bits[coding_mode])<<1;
+ } else
+ {
+ *(dataOut + 1) = 0;
+ return 2<<1;
+ }
+ } else /* MIME/storage file format */
+ {
+#define MRSID 9
+ /* change mode index in case of SID frame */
+ if (coding_mode == MRDTX)
+ {
+ coding_mode = MRSID;
+ if (frame_type == TX_SID_FIRST)
+ {
+ for (i = 0; i < NBBITS_SID; i++) prms[i] = BIT_0;
+ }
+ }
+ /* -> force NO_DATA frame */
+ if (coding_mode < 0 || coding_mode > 15 || (coding_mode > MRSID && coding_mode < 14))
+ {
+ coding_mode = 15;
+ }
+ /* mark empty frames between SID updates as NO_DATA frames */
+ if (coding_mode == MRSID && frame_type == TX_NO_DATA)
+ {
+ coding_mode = 15;
+ }
+ /* set pointer for packed frame, note that we handle data as bytes */
+ stream_ptr = (UWord8*)dataOut;
+ /* insert table of contents (ToC) byte at the beginning of the packet */
+ *stream_ptr = toc_byte[coding_mode];
+ stream_ptr++;
+ temp = 0;
+ /* sort and pack AMR-WB speech or SID bits */
+ for (i = 1; i < unpacked_size[coding_mode] + 1; i++)
+ {
+ if (prms[sort_ptr[coding_mode][i-1]] == BIT_1)
+ {
+ temp++;
+ }
+ if (i&0x7)
+ {
+ temp <<= 1;
+ }
+ else
+ {
+ *stream_ptr = temp;
+ stream_ptr++;
+ temp = 0;
+ }
+ }
+ /* insert SID type indication and speech mode in case of SID frame */
+ if (coding_mode == MRSID)
+ {
+ if (frame_type == TX_SID_UPDATE)
+ {
+ temp++;
+ }
+ temp <<= 4;
+ temp += mode & 0x000F;
+ }
+ /* insert unused bits (zeros) at the tail of the last byte */
+ if (unused_size[coding_mode])
+ {
+ temp <<= (unused_size[coding_mode] - 1);
+ }
+ *stream_ptr = temp;
+ /* write packed frame into file (1 byte added to cover ToC entry) */
+ return (1 + packed_size[coding_mode]);
+ }
+ }
+}
+
+/*-----------------------------------------------------*
+* Parm_serial -> convert parameters to serial stream *
+*-----------------------------------------------------*/
+
+void Parm_serial(
+ Word16 value, /* input : parameter value */
+ Word16 no_of_bits, /* input : number of bits */
+ Word16 ** prms
+ )
+{
+ Word16 i, bit;
+ *prms += no_of_bits;
+ for (i = 0; i < no_of_bits; i++)
+ {
+ bit = (Word16) (value & 0x0001); /* get lsb */
+ if (bit == 0)
+ *--(*prms) = BIT_0;
+ else
+ *--(*prms) = BIT_1;
+ value >>= 1;
+ }
+ *prms += no_of_bits;
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
new file mode 100644
index 0000000..39fc4c5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/c2t64fx.c
@@ -0,0 +1,297 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: c2t64fx.c *
+* *
+* Description:Performs algebraic codebook search for 6.60kbits mode*
+* *
+*************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "acelp.h"
+#include "cnst.h"
+
+#define NB_TRACK 2
+#define STEP 2
+#define NB_POS 32
+#define MSIZE 1024
+
+/*************************************************************************
+* Function: ACELP_2t64_fx() *
+* *
+* 12 bits algebraic codebook. *
+* 2 tracks x 32 positions per track = 64 samples. *
+* *
+* 12 bits --> 2 pulses in a frame of 64 samples. *
+* *
+* All pulses can have two (2) possible amplitudes: +1 or -1. *
+* Each pulse can have 32 possible positions. *
+**************************************************************************/
+
+void ACELP_2t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 * index /* (o) : index (12): 5+1+5+1 = 11 bits. */
+ )
+{
+ Word32 i, j, k, i0, i1, ix, iy, pos, pos2;
+ Word16 ps, psk, ps1, ps2, alpk, alp1, alp2, sq;
+ Word16 alp, val, exp, k_cn, k_dn;
+ Word16 *p0, *p1, *p2, *psign;
+ Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf;
+
+ Word16 sign[L_SUBFR], vec[L_SUBFR], dn2[L_SUBFR];
+ Word16 h_buf[4 * L_SUBFR] = {0};
+ Word16 rrixix[NB_TRACK][NB_POS];
+ Word16 rrixiy[MSIZE];
+ Word32 s, cor;
+
+ /*----------------------------------------------------------------*
+ * Find sign for each pulse position. *
+ *----------------------------------------------------------------*/
+ alp = 8192; /* alp = 2.0 (Q12) */
+
+ /* calculate energy for normalization of cn[] and dn[] */
+ /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
+#ifdef ASM_OPT /* asm optimization branch */
+ s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);
+#else
+ s = Dot_product12(cn, cn, L_SUBFR, &exp);
+#endif
+
+ Isqrt_n(&s, &exp);
+ s = L_shl(s, add1(exp, 5));
+ k_cn = vo_round(s);
+
+ /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
+#ifdef ASM_OPT /* asm optimization branch */
+ s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);
+#else
+ s = Dot_product12(dn, dn, L_SUBFR, &exp);
+#endif
+
+ Isqrt_n(&s, &exp);
+ k_dn = vo_round(L_shl(s, (exp + 8))); /* k_dn = 256..4096 */
+ k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */
+
+ /* mix normalized cn[] and dn[] */
+ p0 = cn;
+ p1 = dn;
+ p2 = dn2;
+
+ for (i = 0; i < L_SUBFR/4; i++)
+ {
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ }
+
+ /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */
+ for (i = 0; i < L_SUBFR; i ++)
+ {
+ val = dn[i];
+ ps = dn2[i];
+ if (ps >= 0)
+ {
+ sign[i] = 32767; /* sign = +1 (Q12) */
+ vec[i] = -32768;
+ } else
+ {
+ sign[i] = -32768; /* sign = -1 (Q12) */
+ vec[i] = 32767;
+ dn[i] = -val;
+ }
+ }
+ /*------------------------------------------------------------*
+ * Compute h_inv[i]. *
+ *------------------------------------------------------------*/
+ /* impulse response buffer for fast computation */
+ h = h_buf + L_SUBFR;
+ h_inv = h + (L_SUBFR<<1);
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ h[i] = H[i];
+ h_inv[i] = vo_negate(h[i]);
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixix[][] needed for the codebook search. *
+ * Result is multiplied by 0.5 *
+ *------------------------------------------------------------*/
+ /* Init pointers to last position of rrixix[] */
+ p0 = &rrixix[0][NB_POS - 1];
+ p1 = &rrixix[1][NB_POS - 1];
+
+ ptr_h1 = h;
+ cor = 0x00010000L; /* for rounding */
+ for (i = 0; i < NB_POS; i++)
+ {
+ cor += ((*ptr_h1) * (*ptr_h1) << 1);
+ ptr_h1++;
+ *p1-- = (extract_h(cor) >> 1);
+ cor += ((*ptr_h1) * (*ptr_h1) << 1);
+ ptr_h1++;
+ *p0-- = (extract_h(cor) >> 1);
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixiy[][] needed for the codebook search. *
+ *------------------------------------------------------------*/
+ pos = MSIZE - 1;
+ pos2 = MSIZE - 2;
+ ptr_hf = h + 1;
+
+ for (k = 0; k < NB_POS; k++)
+ {
+ p1 = &rrixiy[pos];
+ p0 = &rrixiy[pos2];
+ cor = 0x00008000L; /* for rounding */
+ ptr_h1 = h;
+ ptr_h2 = ptr_hf;
+
+ for (i = (k + 1); i < NB_POS; i++)
+ {
+ cor += ((*ptr_h1) * (*ptr_h2))<<1;
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor);
+ cor += ((*ptr_h1) * (*ptr_h2))<<1;
+ ptr_h1++;
+ ptr_h2++;
+ *p0 = extract_h(cor);
+
+ p1 -= (NB_POS + 1);
+ p0 -= (NB_POS + 1);
+ }
+ cor += ((*ptr_h1) * (*ptr_h2))<<1;
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor);
+
+ pos -= NB_POS;
+ pos2--;
+ ptr_hf += STEP;
+ }
+
+ /*------------------------------------------------------------*
+ * Modification of rrixiy[][] to take signs into account. *
+ *------------------------------------------------------------*/
+ p0 = rrixiy;
+ for (i = 0; i < L_SUBFR; i += STEP)
+ {
+ psign = sign;
+ if (psign[i] < 0)
+ {
+ psign = vec;
+ }
+ for (j = 1; j < L_SUBFR; j += STEP)
+ {
+ *p0 = vo_mult(*p0, psign[j]);
+ p0++;
+ }
+ }
+ /*-------------------------------------------------------------------*
+ * search 2 pulses: *
+ * ~@~~~~~~~~~~~~~~ *
+ * 32 pos x 32 pos = 1024 tests (all combinaisons is tested) *
+ *-------------------------------------------------------------------*/
+ p0 = rrixix[0];
+ p1 = rrixix[1];
+ p2 = rrixiy;
+
+ psk = -1;
+ alpk = 1;
+ ix = 0;
+ iy = 1;
+
+ for (i0 = 0; i0 < L_SUBFR; i0 += STEP)
+ {
+ ps1 = dn[i0];
+ alp1 = (*p0++);
+ pos = -1;
+ for (i1 = 1; i1 < L_SUBFR; i1 += STEP)
+ {
+ ps2 = add1(ps1, dn[i1]);
+ alp2 = add1(alp1, add1(*p1++, *p2++));
+ sq = vo_mult(ps2, ps2);
+ s = vo_L_mult(alpk, sq) - ((psk * alp2)<<1);
+ if (s > 0)
+ {
+ psk = sq;
+ alpk = alp2;
+ pos = i1;
+ }
+ }
+ p1 -= NB_POS;
+ if (pos >= 0)
+ {
+ ix = i0;
+ iy = pos;
+ }
+ }
+ /*-------------------------------------------------------------------*
+ * Build the codeword, the filtered codeword and index of codevector.*
+ *-------------------------------------------------------------------*/
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = 0;
+ }
+
+ i0 = (ix >> 1); /* pos of pulse 1 (0..31) */
+ i1 = (iy >> 1); /* pos of pulse 2 (0..31) */
+ if (sign[ix] > 0)
+ {
+ code[ix] = 512; /* codeword in Q9 format */
+ p0 = h - ix;
+ } else
+ {
+ code[ix] = -512;
+ i0 += NB_POS;
+ p0 = h_inv - ix;
+ }
+ if (sign[iy] > 0)
+ {
+ code[iy] = 512;
+ p1 = h - iy;
+ } else
+ {
+ code[iy] = -512;
+ i1 += NB_POS;
+ p1 = h_inv - iy;
+ }
+ *index = add1((i0 << 6), i1);
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ y[i] = vo_shr_r(add1((*p0++), (*p1++)), 3);
+ }
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
new file mode 100644
index 0000000..27ba95d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/c4t64fx.c
@@ -0,0 +1,1043 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: c4t64fx.c *
+* *
+* Description:Performs algebraic codebook search for higher modes *
+* *
+************************************************************************/
+
+/************************************************************************
+* Function: ACELP_4t64_fx() *
+* *
+* 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. *
+* 4 tracks x 16 positions per track = 64 samples. *
+* *
+* 20 bits --> 4 pulses in a frame of 64 samples. *
+* 36 bits --> 8 pulses in a frame of 64 samples. *
+* 44 bits --> 10 pulses in a frame of 64 samples. *
+* 52 bits --> 12 pulses in a frame of 64 samples. *
+* 64 bits --> 16 pulses in a frame of 64 samples. *
+* 72 bits --> 18 pulses in a frame of 64 samples. *
+* 88 bits --> 24 pulses in a frame of 64 samples. *
+* *
+* All pulses can have two (2) possible amplitudes: +1 or -1. *
+* Each pulse can have sixteen (16) possible positions. *
+*************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "acelp.h"
+#include "cnst.h"
+
+#include "q_pulse.h"
+
+static Word16 tipos[36] = {
+ 0, 1, 2, 3, /* starting point &ipos[0], 1st iter */
+ 1, 2, 3, 0, /* starting point &ipos[4], 2nd iter */
+ 2, 3, 0, 1, /* starting point &ipos[8], 3rd iter */
+ 3, 0, 1, 2, /* starting point &ipos[12], 4th iter */
+ 0, 1, 2, 3,
+ 1, 2, 3, 0,
+ 2, 3, 0, 1,
+ 3, 0, 1, 2,
+ 0, 1, 2, 3}; /* end point for 24 pulses &ipos[35], 4th iter */
+
+#define NB_PULSE_MAX 24
+
+#define L_SUBFR 64
+#define NB_TRACK 4
+#define STEP 4
+#define NB_POS 16
+#define MSIZE 256
+#define NB_MAX 8
+#define NPMAXPT ((NB_PULSE_MAX+NB_TRACK-1)/NB_TRACK)
+
+/* Private functions */
+void cor_h_vec_012(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+ );
+
+void cor_h_vec_012_asm(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+ );
+
+void cor_h_vec_30(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+ );
+
+void search_ixiy(
+ Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */
+ Word16 track_x, /* (i) track of pulse 1 */
+ Word16 track_y, /* (i) track of pulse 2 */
+ Word16 * ps, /* (i/o) correlation of all fixed pulses */
+ Word16 * alp, /* (i/o) energy of all fixed pulses */
+ Word16 * ix, /* (o) position of pulse 1 */
+ Word16 * iy, /* (o) position of pulse 2 */
+ Word16 dn[], /* (i) corr. between target and h[] */
+ Word16 dn2[], /* (i) vector of selected positions */
+ Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */
+ Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */
+ Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */
+ );
+
+
+void ACELP_4t64_fx(
+ Word16 dn[], /* (i) <12b : correlation between target x[] and H[] */
+ Word16 cn[], /* (i) <12b : residual after long term prediction */
+ Word16 H[], /* (i) Q12: impulse response of weighted synthesis filter */
+ Word16 code[], /* (o) Q9 : algebraic (fixed) codebook excitation */
+ Word16 y[], /* (o) Q9 : filtered fixed codebook excitation */
+ Word16 nbbits, /* (i) : 20, 36, 44, 52, 64, 72 or 88 bits */
+ Word16 ser_size, /* (i) : bit rate */
+ Word16 _index[] /* (o) : index (20): 5+5+5+5 = 20 bits. */
+ /* (o) : index (36): 9+9+9+9 = 36 bits. */
+ /* (o) : index (44): 13+9+13+9 = 44 bits. */
+ /* (o) : index (52): 13+13+13+13 = 52 bits. */
+ /* (o) : index (64): 2+2+2+2+14+14+14+14 = 64 bits. */
+ /* (o) : index (72): 10+2+10+2+10+14+10+14 = 72 bits. */
+ /* (o) : index (88): 11+11+11+11+11+11+11+11 = 88 bits. */
+ )
+{
+ Word32 i, j, k;
+ Word16 st, ix, iy, pos, index, track, nb_pulse, nbiter, j_temp;
+ Word16 psk, ps, alpk, alp, val, k_cn, k_dn, exp;
+ Word16 *p0, *p1, *p2, *p3, *psign;
+ Word16 *h, *h_inv, *ptr_h1, *ptr_h2, *ptr_hf, h_shift;
+ Word32 s, cor, L_tmp, L_index;
+ Word16 dn2[L_SUBFR], sign[L_SUBFR], vec[L_SUBFR];
+ Word16 ind[NPMAXPT * NB_TRACK];
+ Word16 codvec[NB_PULSE_MAX], nbpos[10];
+ Word16 cor_x[NB_POS], cor_y[NB_POS], pos_max[NB_TRACK];
+ Word16 h_buf[4 * L_SUBFR];
+ Word16 rrixix[NB_TRACK][NB_POS], rrixiy[NB_TRACK][MSIZE];
+ Word16 ipos[NB_PULSE_MAX];
+
+ switch (nbbits)
+ {
+ case 20: /* 20 bits, 4 pulses, 4 tracks */
+ nbiter = 4; /* 4x16x16=1024 loop */
+ alp = 8192; /* alp = 2.0 (Q12) */
+ nb_pulse = 4;
+ nbpos[0] = 4;
+ nbpos[1] = 8;
+ break;
+ case 36: /* 36 bits, 8 pulses, 4 tracks */
+ nbiter = 4; /* 4x20x16=1280 loop */
+ alp = 4096; /* alp = 1.0 (Q12) */
+ nb_pulse = 8;
+ nbpos[0] = 4;
+ nbpos[1] = 8;
+ nbpos[2] = 8;
+ break;
+ case 44: /* 44 bits, 10 pulses, 4 tracks */
+ nbiter = 4; /* 4x26x16=1664 loop */
+ alp = 4096; /* alp = 1.0 (Q12) */
+ nb_pulse = 10;
+ nbpos[0] = 4;
+ nbpos[1] = 6;
+ nbpos[2] = 8;
+ nbpos[3] = 8;
+ break;
+ case 52: /* 52 bits, 12 pulses, 4 tracks */
+ nbiter = 4; /* 4x26x16=1664 loop */
+ alp = 4096; /* alp = 1.0 (Q12) */
+ nb_pulse = 12;
+ nbpos[0] = 4;
+ nbpos[1] = 6;
+ nbpos[2] = 8;
+ nbpos[3] = 8;
+ break;
+ case 64: /* 64 bits, 16 pulses, 4 tracks */
+ nbiter = 3; /* 3x36x16=1728 loop */
+ alp = 3277; /* alp = 0.8 (Q12) */
+ nb_pulse = 16;
+ nbpos[0] = 4;
+ nbpos[1] = 4;
+ nbpos[2] = 6;
+ nbpos[3] = 6;
+ nbpos[4] = 8;
+ nbpos[5] = 8;
+ break;
+ case 72: /* 72 bits, 18 pulses, 4 tracks */
+ nbiter = 3; /* 3x35x16=1680 loop */
+ alp = 3072; /* alp = 0.75 (Q12) */
+ nb_pulse = 18;
+ nbpos[0] = 2;
+ nbpos[1] = 3;
+ nbpos[2] = 4;
+ nbpos[3] = 5;
+ nbpos[4] = 6;
+ nbpos[5] = 7;
+ nbpos[6] = 8;
+ break;
+ case 88: /* 88 bits, 24 pulses, 4 tracks */
+ if(ser_size > 462)
+ nbiter = 1;
+ else
+ nbiter = 2; /* 2x53x16=1696 loop */
+
+ alp = 2048; /* alp = 0.5 (Q12) */
+ nb_pulse = 24;
+ nbpos[0] = 2;
+ nbpos[1] = 2;
+ nbpos[2] = 3;
+ nbpos[3] = 4;
+ nbpos[4] = 5;
+ nbpos[5] = 6;
+ nbpos[6] = 7;
+ nbpos[7] = 8;
+ nbpos[8] = 8;
+ nbpos[9] = 8;
+ break;
+ default:
+ nbiter = 0;
+ alp = 0;
+ nb_pulse = 0;
+ }
+
+ for (i = 0; i < nb_pulse; i++)
+ {
+ codvec[i] = i;
+ }
+
+ /*----------------------------------------------------------------*
+ * Find sign for each pulse position. *
+ *----------------------------------------------------------------*/
+ /* calculate energy for normalization of cn[] and dn[] */
+ /* set k_cn = 32..32767 (ener_cn = 2^30..256-0) */
+#ifdef ASM_OPT /* asm optimization branch */
+ s = Dot_product12_asm(cn, cn, L_SUBFR, &exp);
+#else
+ s = Dot_product12(cn, cn, L_SUBFR, &exp);
+#endif
+
+ Isqrt_n(&s, &exp);
+ s = L_shl(s, (exp + 5));
+ k_cn = extract_h(L_add(s, 0x8000));
+
+ /* set k_dn = 32..512 (ener_dn = 2^30..2^22) */
+#ifdef ASM_OPT /* asm optimization branch */
+ s = Dot_product12_asm(dn, dn, L_SUBFR, &exp);
+#else
+ s = Dot_product12(dn, dn, L_SUBFR, &exp);
+#endif
+
+ Isqrt_n(&s, &exp);
+ k_dn = (L_shl(s, (exp + 5 + 3)) + 0x8000) >> 16; /* k_dn = 256..4096 */
+ k_dn = vo_mult_r(alp, k_dn); /* alp in Q12 */
+
+ /* mix normalized cn[] and dn[] */
+ p0 = cn;
+ p1 = dn;
+ p2 = dn2;
+
+ for (i = 0; i < L_SUBFR/4; i++)
+ {
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ s = (k_cn* (*p0++))+(k_dn * (*p1++));
+ *p2++ = s >> 7;
+ }
+
+ /* set sign according to dn2[] = k_cn*cn[] + k_dn*dn[] */
+ for(i = 0; i < L_SUBFR; i++)
+ {
+ val = dn[i];
+ ps = dn2[i];
+ if (ps >= 0)
+ {
+ sign[i] = 32767; /* sign = +1 (Q12) */
+ vec[i] = -32768;
+ } else
+ {
+ sign[i] = -32768; /* sign = -1 (Q12) */
+ vec[i] = 32767;
+ dn[i] = -val;
+ dn2[i] = -ps;
+ }
+ }
+ /*----------------------------------------------------------------*
+ * Select NB_MAX position per track according to max of dn2[]. *
+ *----------------------------------------------------------------*/
+ pos = 0;
+ for (i = 0; i < NB_TRACK; i++)
+ {
+ for (k = 0; k < NB_MAX; k++)
+ {
+ ps = -1;
+ for (j = i; j < L_SUBFR; j += STEP)
+ {
+ if(dn2[j] > ps)
+ {
+ ps = dn2[j];
+ pos = j;
+ }
+ }
+ dn2[pos] = (k - NB_MAX); /* dn2 < 0 when position is selected */
+ if (k == 0)
+ {
+ pos_max[i] = pos;
+ }
+ }
+ }
+
+ /*--------------------------------------------------------------*
+ * Scale h[] to avoid overflow and to get maximum of precision *
+ * on correlation. *
+ * *
+ * Maximum of h[] (h[0]) is fixed to 2048 (MAX16 / 16). *
+ * ==> This allow addition of 16 pulses without saturation. *
+ * *
+ * Energy worst case (on resonant impulse response), *
+ * - energy of h[] is approximately MAX/16. *
+ * - During search, the energy is divided by 8 to avoid *
+ * overflow on "alp". (energy of h[] = MAX/128). *
+ * ==> "alp" worst case detected is 22854 on sinusoidal wave. *
+ *--------------------------------------------------------------*/
+
+ /* impulse response buffer for fast computation */
+
+ h = h_buf;
+ h_inv = h_buf + (2 * L_SUBFR);
+ L_tmp = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ *h++ = 0;
+ *h_inv++ = 0;
+ L_tmp += (H[i] * H[i]) << 1;
+ }
+ /* scale h[] down (/2) when energy of h[] is high with many pulses used */
+ val = extract_h(L_tmp);
+ h_shift = 0;
+
+ if ((nb_pulse >= 12) && (val > 1024))
+ {
+ h_shift = 1;
+ }
+ p0 = H;
+ p1 = h;
+ p2 = h_inv;
+
+ for (i = 0; i < L_SUBFR/4; i++)
+ {
+ *p1 = *p0++ >> h_shift;
+ *p2++ = -(*p1++);
+ *p1 = *p0++ >> h_shift;
+ *p2++ = -(*p1++);
+ *p1 = *p0++ >> h_shift;
+ *p2++ = -(*p1++);
+ *p1 = *p0++ >> h_shift;
+ *p2++ = -(*p1++);
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixix[][] needed for the codebook search. *
+ * This algorithm compute impulse response energy of all *
+ * positions (16) in each track (4). Total = 4x16 = 64. *
+ *------------------------------------------------------------*/
+
+ /* storage order --> i3i3, i2i2, i1i1, i0i0 */
+
+ /* Init pointers to last position of rrixix[] */
+ p0 = &rrixix[0][NB_POS - 1];
+ p1 = &rrixix[1][NB_POS - 1];
+ p2 = &rrixix[2][NB_POS - 1];
+ p3 = &rrixix[3][NB_POS - 1];
+
+ ptr_h1 = h;
+ cor = 0x00008000L; /* for rounding */
+ for (i = 0; i < NB_POS; i++)
+ {
+ cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ ptr_h1++;
+ *p3-- = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ ptr_h1++;
+ *p2-- = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ ptr_h1++;
+ *p1-- = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h1));
+ ptr_h1++;
+ *p0-- = extract_h(cor);
+ }
+
+ /*------------------------------------------------------------*
+ * Compute rrixiy[][] needed for the codebook search. *
+ * This algorithm compute correlation between 2 pulses *
+ * (2 impulses responses) in 4 possible adjacents tracks. *
+ * (track 0-1, 1-2, 2-3 and 3-0). Total = 4x16x16 = 1024. *
+ *------------------------------------------------------------*/
+
+ /* storage order --> i2i3, i1i2, i0i1, i3i0 */
+
+ pos = MSIZE - 1;
+ ptr_hf = h + 1;
+
+ for (k = 0; k < NB_POS; k++)
+ {
+ p3 = &rrixiy[2][pos];
+ p2 = &rrixiy[1][pos];
+ p1 = &rrixiy[0][pos];
+ p0 = &rrixiy[3][pos - NB_POS];
+
+ cor = 0x00008000L; /* for rounding */
+ ptr_h1 = h;
+ ptr_h2 = ptr_hf;
+
+ for (i = k + 1; i < NB_POS; i++)
+ {
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p2 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p0 = extract_h(cor);
+
+ p3 -= (NB_POS + 1);
+ p2 -= (NB_POS + 1);
+ p1 -= (NB_POS + 1);
+ p0 -= (NB_POS + 1);
+ }
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p2 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor);
+
+ pos -= NB_POS;
+ ptr_hf += STEP;
+ }
+
+ /* storage order --> i3i0, i2i3, i1i2, i0i1 */
+
+ pos = MSIZE - 1;
+ ptr_hf = h + 3;
+
+ for (k = 0; k < NB_POS; k++)
+ {
+ p3 = &rrixiy[3][pos];
+ p2 = &rrixiy[2][pos - 1];
+ p1 = &rrixiy[1][pos - 1];
+ p0 = &rrixiy[0][pos - 1];
+
+ cor = 0x00008000L; /* for rounding */
+ ptr_h1 = h;
+ ptr_h2 = ptr_hf;
+
+ for (i = k + 1; i < NB_POS; i++)
+ {
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p2 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p1 = extract_h(cor);
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p0 = extract_h(cor);
+
+ p3 -= (NB_POS + 1);
+ p2 -= (NB_POS + 1);
+ p1 -= (NB_POS + 1);
+ p0 -= (NB_POS + 1);
+ }
+ cor += vo_L_mult((*ptr_h1), (*ptr_h2));
+ ptr_h1++;
+ ptr_h2++;
+ *p3 = extract_h(cor);
+
+ pos--;
+ ptr_hf += STEP;
+ }
+
+ /*------------------------------------------------------------*
+ * Modification of rrixiy[][] to take signs into account. *
+ *------------------------------------------------------------*/
+
+ p0 = &rrixiy[0][0];
+
+ for (k = 0; k < NB_TRACK; k++)
+ {
+ j_temp = (k + 1)&0x03;
+ for (i = k; i < L_SUBFR; i += STEP)
+ {
+ psign = sign;
+ if (psign[i] < 0)
+ {
+ psign = vec;
+ }
+ j = j_temp;
+ for (; j < L_SUBFR; j += STEP)
+ {
+ *p0 = vo_mult(*p0, psign[j]);
+ p0++;
+ }
+ }
+ }
+
+ /*-------------------------------------------------------------------*
+ * Deep first search *
+ *-------------------------------------------------------------------*/
+
+ psk = -1;
+ alpk = 1;
+
+ for (k = 0; k < nbiter; k++)
+ {
+ j_temp = k<<2;
+ for (i = 0; i < nb_pulse; i++)
+ ipos[i] = tipos[j_temp + i];
+
+ if(nbbits == 20)
+ {
+ pos = 0;
+ ps = 0;
+ alp = 0;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = 0;
+ }
+ } else if ((nbbits == 36) || (nbbits == 44))
+ {
+ /* first stage: fix 2 pulses */
+ pos = 2;
+
+ ix = ind[0] = pos_max[ipos[0]];
+ iy = ind[1] = pos_max[ipos[1]];
+ ps = dn[ix] + dn[iy];
+ i = ix >> 2; /* ix / STEP */
+ j = iy >> 2; /* iy / STEP */
+ s = rrixix[ipos[0]][i] << 13;
+ s += rrixix[ipos[1]][j] << 13;
+ i = (i << 4) + j; /* (ix/STEP)*NB_POS + (iy/STEP) */
+ s += rrixiy[ipos[0]][i] << 14;
+ alp = (s + 0x8000) >> 16;
+ if (sign[ix] < 0)
+ p0 = h_inv - ix;
+ else
+ p0 = h - ix;
+ if (sign[iy] < 0)
+ p1 = h_inv - iy;
+ else
+ p1 = h - iy;
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = (*p0++) + (*p1++);
+ }
+
+ if(nbbits == 44)
+ {
+ ipos[8] = 0;
+ ipos[9] = 1;
+ }
+ } else
+ {
+ /* first stage: fix 4 pulses */
+ pos = 4;
+
+ ix = ind[0] = pos_max[ipos[0]];
+ iy = ind[1] = pos_max[ipos[1]];
+ i = ind[2] = pos_max[ipos[2]];
+ j = ind[3] = pos_max[ipos[3]];
+ ps = add1(add1(add1(dn[ix], dn[iy]), dn[i]), dn[j]);
+
+ if (sign[ix] < 0)
+ p0 = h_inv - ix;
+ else
+ p0 = h - ix;
+
+ if (sign[iy] < 0)
+ p1 = h_inv - iy;
+ else
+ p1 = h - iy;
+
+ if (sign[i] < 0)
+ p2 = h_inv - i;
+ else
+ p2 = h - i;
+
+ if (sign[j] < 0)
+ p3 = h_inv - j;
+ else
+ p3 = h - j;
+
+ L_tmp = 0L;
+ for(i = 0; i < L_SUBFR; i++)
+ {
+ vec[i] = add1(add1(add1(*p0++, *p1++), *p2++), *p3++);
+ L_tmp += (vec[i] * vec[i]) << 1;
+ }
+
+ alp = ((L_tmp >> 3) + 0x8000) >> 16;
+
+ if(nbbits == 72)
+ {
+ ipos[16] = 0;
+ ipos[17] = 1;
+ }
+ }
+
+ /* other stages of 2 pulses */
+
+ for (j = pos, st = 0; j < nb_pulse; j += 2, st++)
+ {
+ /*--------------------------------------------------*
+ * Calculate correlation of all possible positions *
+ * of the next 2 pulses with previous fixed pulses. *
+ * Each pulse can have 16 possible positions. *
+ *--------------------------------------------------*/
+ if(ipos[j] == 3)
+ {
+ cor_h_vec_30(h, vec, ipos[j], sign, rrixix, cor_x, cor_y);
+ }
+ else
+ {
+#ifdef ASM_OPT /* asm optimization branch */
+ cor_h_vec_012_asm(h, vec, ipos[j], sign, rrixix, cor_x, cor_y);
+#else
+ cor_h_vec_012(h, vec, ipos[j], sign, rrixix, cor_x, cor_y);
+#endif
+ }
+ /*--------------------------------------------------*
+ * Find best positions of 2 pulses. *
+ *--------------------------------------------------*/
+ search_ixiy(nbpos[st], ipos[j], ipos[j + 1], &ps, &alp,
+ &ix, &iy, dn, dn2, cor_x, cor_y, rrixiy);
+
+ ind[j] = ix;
+ ind[j + 1] = iy;
+
+ if (sign[ix] < 0)
+ p0 = h_inv - ix;
+ else
+ p0 = h - ix;
+ if (sign[iy] < 0)
+ p1 = h_inv - iy;
+ else
+ p1 = h - iy;
+
+ for (i = 0; i < L_SUBFR; i+=4)
+ {
+ vec[i] += add1((*p0++), (*p1++));
+ vec[i+1] += add1((*p0++), (*p1++));
+ vec[i+2] += add1((*p0++), (*p1++));
+ vec[i+3] += add1((*p0++), (*p1++));
+ }
+ }
+ /* memorise the best codevector */
+ ps = vo_mult(ps, ps);
+ s = vo_L_msu(vo_L_mult(alpk, ps), psk, alp);
+ if (s > 0)
+ {
+ psk = ps;
+ alpk = alp;
+ for (i = 0; i < nb_pulse; i++)
+ {
+ codvec[i] = ind[i];
+ }
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ y[i] = vec[i];
+ }
+ }
+ }
+ /*-------------------------------------------------------------------*
+ * Build the codeword, the filtered codeword and index of codevector.*
+ *-------------------------------------------------------------------*/
+ for (i = 0; i < NPMAXPT * NB_TRACK; i++)
+ {
+ ind[i] = -1;
+ }
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ code[i] = 0;
+ y[i] = vo_shr_r(y[i], 3); /* Q12 to Q9 */
+ }
+ val = (512 >> h_shift); /* codeword in Q9 format */
+ for (k = 0; k < nb_pulse; k++)
+ {
+ i = codvec[k]; /* read pulse position */
+ j = sign[i]; /* read sign */
+ index = i >> 2; /* index = pos of pulse (0..15) */
+ track = (Word16) (i & 0x03); /* track = i % NB_TRACK (0..3) */
+
+ if (j > 0)
+ {
+ code[i] += val;
+ codvec[k] += 128;
+ } else
+ {
+ code[i] -= val;
+ index += NB_POS;
+ }
+
+ i = (Word16)((vo_L_mult(track, NPMAXPT) >> 1));
+
+ while (ind[i] >= 0)
+ {
+ i += 1;
+ }
+ ind[i] = index;
+ }
+
+ k = 0;
+ /* Build index of codevector */
+ if(nbbits == 20)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ _index[track] = (Word16)(quant_1p_N1(ind[k], 4));
+ k += NPMAXPT;
+ }
+ } else if(nbbits == 36)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ _index[track] = (Word16)(quant_2p_2N1(ind[k], ind[k + 1], 4));
+ k += NPMAXPT;
+ }
+ } else if(nbbits == 44)
+ {
+ for (track = 0; track < NB_TRACK - 2; track++)
+ {
+ _index[track] = (Word16)(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4));
+ k += NPMAXPT;
+ }
+ for (track = 2; track < NB_TRACK; track++)
+ {
+ _index[track] = (Word16)(quant_2p_2N1(ind[k], ind[k + 1], 4));
+ k += NPMAXPT;
+ }
+ } else if(nbbits == 52)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ _index[track] = (Word16)(quant_3p_3N1(ind[k], ind[k + 1], ind[k + 2], 4));
+ k += NPMAXPT;
+ }
+ } else if(nbbits == 64)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ L_index = quant_4p_4N(&ind[k], 4);
+ _index[track] = (Word16)((L_index >> 14) & 3);
+ _index[track + NB_TRACK] = (Word16)(L_index & 0x3FFF);
+ k += NPMAXPT;
+ }
+ } else if(nbbits == 72)
+ {
+ for (track = 0; track < NB_TRACK - 2; track++)
+ {
+ L_index = quant_5p_5N(&ind[k], 4);
+ _index[track] = (Word16)((L_index >> 10) & 0x03FF);
+ _index[track + NB_TRACK] = (Word16)(L_index & 0x03FF);
+ k += NPMAXPT;
+ }
+ for (track = 2; track < NB_TRACK; track++)
+ {
+ L_index = quant_4p_4N(&ind[k], 4);
+ _index[track] = (Word16)((L_index >> 14) & 3);
+ _index[track + NB_TRACK] = (Word16)(L_index & 0x3FFF);
+ k += NPMAXPT;
+ }
+ } else if(nbbits == 88)
+ {
+ for (track = 0; track < NB_TRACK; track++)
+ {
+ L_index = quant_6p_6N_2(&ind[k], 4);
+ _index[track] = (Word16)((L_index >> 11) & 0x07FF);
+ _index[track + NB_TRACK] = (Word16)(L_index & 0x07FF);
+ k += NPMAXPT;
+ }
+ }
+ return;
+}
+
+
+/*-------------------------------------------------------------------*
+ * Function cor_h_vec() *
+ * ~~~~~~~~~~~~~~~~~~~~~ *
+ * Compute correlations of h[] with vec[] for the specified track. *
+ *-------------------------------------------------------------------*/
+void cor_h_vec_30(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+ )
+{
+ Word32 i, j, pos, corr;
+ Word16 *p0, *p1, *p2,*p3,*cor_x,*cor_y;
+ Word32 L_sum1,L_sum2;
+ cor_x = cor_1;
+ cor_y = cor_2;
+ p0 = rrixix[track];
+ p3 = rrixix[0];
+ pos = track;
+
+ for (i = 0; i < NB_POS; i+=2)
+ {
+ L_sum1 = L_sum2 = 0L;
+ p1 = h;
+ p2 = &vec[pos];
+ for (j=pos;j < L_SUBFR; j++)
+ {
+ L_sum1 += *p1 * *p2;
+ p2-=3;
+ L_sum2 += *p1++ * *p2;
+ p2+=4;
+ }
+ p2-=3;
+ L_sum2 += *p1++ * *p2++;
+ L_sum2 += *p1++ * *p2++;
+ L_sum2 += *p1++ * *p2++;
+
+ L_sum1 = (L_sum1 << 2);
+ L_sum2 = (L_sum2 << 2);
+
+ corr = vo_round(L_sum1);
+ *cor_x++ = vo_mult(corr, sign[pos]) + (*p0++);
+ corr = vo_round(L_sum2);
+ *cor_y++ = vo_mult(corr, sign[pos-3]) + (*p3++);
+ pos += STEP;
+
+ L_sum1 = L_sum2 = 0L;
+ p1 = h;
+ p2 = &vec[pos];
+ for (j=pos;j < L_SUBFR; j++)
+ {
+ L_sum1 += *p1 * *p2;
+ p2-=3;
+ L_sum2 += *p1++ * *p2;
+ p2+=4;
+ }
+ p2-=3;
+ L_sum2 += *p1++ * *p2++;
+ L_sum2 += *p1++ * *p2++;
+ L_sum2 += *p1++ * *p2++;
+
+ L_sum1 = (L_sum1 << 2);
+ L_sum2 = (L_sum2 << 2);
+
+ corr = vo_round(L_sum1);
+ *cor_x++ = vo_mult(corr, sign[pos]) + (*p0++);
+ corr = vo_round(L_sum2);
+ *cor_y++ = vo_mult(corr, sign[pos-3]) + (*p3++);
+ pos += STEP;
+ }
+ return;
+}
+
+void cor_h_vec_012(
+ Word16 h[], /* (i) scaled impulse response */
+ Word16 vec[], /* (i) scaled vector (/8) to correlate with h[] */
+ Word16 track, /* (i) track to use */
+ Word16 sign[], /* (i) sign vector */
+ Word16 rrixix[][NB_POS], /* (i) correlation of h[x] with h[x] */
+ Word16 cor_1[], /* (o) result of correlation (NB_POS elements) */
+ Word16 cor_2[] /* (o) result of correlation (NB_POS elements) */
+ )
+{
+ Word32 i, j, pos, corr;
+ Word16 *p0, *p1, *p2,*p3,*cor_x,*cor_y;
+ Word32 L_sum1,L_sum2;
+ cor_x = cor_1;
+ cor_y = cor_2;
+ p0 = rrixix[track];
+ p3 = rrixix[track+1];
+ pos = track;
+
+ for (i = 0; i < NB_POS; i+=2)
+ {
+ L_sum1 = L_sum2 = 0L;
+ p1 = h;
+ p2 = &vec[pos];
+ for (j=62-pos ;j >= 0; j--)
+ {
+ L_sum1 += *p1 * *p2++;
+ L_sum2 += *p1++ * *p2;
+ }
+ L_sum1 += *p1 * *p2;
+ L_sum1 = (L_sum1 << 2);
+ L_sum2 = (L_sum2 << 2);
+
+ corr = (L_sum1 + 0x8000) >> 16;
+ cor_x[i] = vo_mult(corr, sign[pos]) + (*p0++);
+ corr = (L_sum2 + 0x8000) >> 16;
+ cor_y[i] = vo_mult(corr, sign[pos + 1]) + (*p3++);
+ pos += STEP;
+
+ L_sum1 = L_sum2 = 0L;
+ p1 = h;
+ p2 = &vec[pos];
+ for (j= 62-pos;j >= 0; j--)
+ {
+ L_sum1 += *p1 * *p2++;
+ L_sum2 += *p1++ * *p2;
+ }
+ L_sum1 += *p1 * *p2;
+ L_sum1 = (L_sum1 << 2);
+ L_sum2 = (L_sum2 << 2);
+
+ corr = (L_sum1 + 0x8000) >> 16;
+ cor_x[i+1] = vo_mult(corr, sign[pos]) + (*p0++);
+ corr = (L_sum2 + 0x8000) >> 16;
+ cor_y[i+1] = vo_mult(corr, sign[pos + 1]) + (*p3++);
+ pos += STEP;
+ }
+ return;
+}
+
+/*-------------------------------------------------------------------*
+ * Function search_ixiy() *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * Find the best positions of 2 pulses in a subframe. *
+ *-------------------------------------------------------------------*/
+
+void search_ixiy(
+ Word16 nb_pos_ix, /* (i) nb of pos for pulse 1 (1..8) */
+ Word16 track_x, /* (i) track of pulse 1 */
+ Word16 track_y, /* (i) track of pulse 2 */
+ Word16 * ps, /* (i/o) correlation of all fixed pulses */
+ Word16 * alp, /* (i/o) energy of all fixed pulses */
+ Word16 * ix, /* (o) position of pulse 1 */
+ Word16 * iy, /* (o) position of pulse 2 */
+ Word16 dn[], /* (i) corr. between target and h[] */
+ Word16 dn2[], /* (i) vector of selected positions */
+ Word16 cor_x[], /* (i) corr. of pulse 1 with fixed pulses */
+ Word16 cor_y[], /* (i) corr. of pulse 2 with fixed pulses */
+ Word16 rrixiy[][MSIZE] /* (i) corr. of pulse 1 with pulse 2 */
+ )
+{
+ Word32 x, y, pos, thres_ix;
+ Word16 ps1, ps2, sq, sqk;
+ Word16 alp_16, alpk;
+ Word16 *p0, *p1, *p2;
+ Word32 s, alp0, alp1, alp2;
+
+ p0 = cor_x;
+ p1 = cor_y;
+ p2 = rrixiy[track_x];
+
+ thres_ix = nb_pos_ix - NB_MAX;
+
+ alp0 = L_deposit_h(*alp);
+ alp0 = (alp0 + 0x00008000L); /* for rounding */
+
+ sqk = -1;
+ alpk = 1;
+
+ for (x = track_x; x < L_SUBFR; x += STEP)
+ {
+ ps1 = *ps + dn[x];
+ alp1 = alp0 + ((*p0++)<<13);
+
+ if (dn2[x] < thres_ix)
+ {
+ pos = -1;
+ for (y = track_y; y < L_SUBFR; y += STEP)
+ {
+ ps2 = add1(ps1, dn[y]);
+
+ alp2 = alp1 + ((*p1++)<<13);
+ alp2 = alp2 + ((*p2++)<<14);
+ alp_16 = extract_h(alp2);
+ sq = vo_mult(ps2, ps2);
+ s = vo_L_mult(alpk, sq) - ((sqk * alp_16)<<1);
+
+ if (s > 0)
+ {
+ sqk = sq;
+ alpk = alp_16;
+ pos = y;
+ }
+ }
+ p1 -= NB_POS;
+
+ if (pos >= 0)
+ {
+ *ix = x;
+ *iy = pos;
+ }
+ } else
+ {
+ p2 += NB_POS;
+ }
+ }
+
+ *ps = add1(*ps, add1(dn[*ix], dn[*iy]));
+ *alp = alpk;
+
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c
new file mode 100644
index 0000000..c17264c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/cmnMemory.c
@@ -0,0 +1,73 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: cmnMemory.c
+
+ Content: sample code for memory operator implementation
+
+*******************************************************************************/
+#include "cmnMemory.h"
+
+#include <malloc.h>
+#if defined LINUX
+#include <string.h>
+#endif
+
+//VO_MEM_OPERATOR g_memOP;
+
+VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo)
+{
+ if (!pMemInfo)
+ return VO_ERR_INVALID_ARG;
+
+ pMemInfo->VBuffer = malloc (pMemInfo->Size);
+ return 0;
+}
+
+VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem)
+{
+ free (pMem);
+ return 0;
+}
+
+VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize)
+{
+ memset (pBuff, uValue, uSize);
+ return 0;
+}
+
+VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)
+{
+ memcpy (pDest, pSource, uSize);
+ return 0;
+}
+
+VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize)
+{
+ return 0;
+}
+
+VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize)
+{
+ return memcmp(pBuffer1, pBuffer2, uSize);
+}
+
+VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)
+{
+ memmove (pDest, pSource, uSize);
+ return 0;
+}
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/convolve.c b/media/libstagefright/codecs/amrwbenc/src/convolve.c
new file mode 100644
index 0000000..66c74d6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/convolve.c
@@ -0,0 +1,109 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: convolve.c
+
+ Description:Perform the convolution between two vectors x[] and h[]
+ and write the result in the vector y[]
+
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Convolve (
+ Word16 x[], /* (i) : input vector */
+ Word16 h[], /* (i) : impulse response */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector size */
+ )
+{
+ Word32 i, n;
+ Word16 *tmpH,*tmpX;
+ Word32 s;
+ for (n = 0; n < 64;)
+ {
+ tmpH = h+n;
+ tmpX = x;
+ i=n+1;
+ s = vo_mult32((*tmpX++), (*tmpH--));i--;
+ while(i>0)
+ {
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ i -= 4;
+ }
+ y[n] = ((s<<1) + 0x8000)>>16;
+ n++;
+
+ tmpH = h+n;
+ tmpX = x;
+ i=n+1;
+ s = vo_mult32((*tmpX++), (*tmpH--));i--;
+ s += vo_mult32((*tmpX++), (*tmpH--));i--;
+
+ while(i>0)
+ {
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ i -= 4;
+ }
+ y[n] = ((s<<1) + 0x8000)>>16;
+ n++;
+
+ tmpH = h+n;
+ tmpX = x;
+ i=n+1;
+ s = vo_mult32((*tmpX++), (*tmpH--));i--;
+ s += vo_mult32((*tmpX++), (*tmpH--));i--;
+ s += vo_mult32((*tmpX++), (*tmpH--));i--;
+
+ while(i>0)
+ {
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ i -= 4;
+ }
+ y[n] = ((s<<1) + 0x8000)>>16;
+ n++;
+
+ s = 0;
+ tmpH = h+n;
+ tmpX = x;
+ i=n+1;
+ while(i>0)
+ {
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ s += vo_mult32((*tmpX++), (*tmpH--));
+ i -= 4;
+ }
+ y[n] = ((s<<1) + 0x8000)>>16;
+ n++;
+ }
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
new file mode 100644
index 0000000..3c2e9d5
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/cor_h_x.c
@@ -0,0 +1,127 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: cor_h_x.c *
+* *
+* Description:Compute correlation between target "x[]" and "h[]" *
+* Designed for codebook search (24 pulses, 4 tracks, *
+* 4 pulses per track, 16 positions in each track) to *
+* avoid saturation. *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+
+#define L_SUBFR 64
+#define NB_TRACK 4
+#define STEP 4
+
+void cor_h_x(
+ Word16 h[], /* (i) Q12 : impulse response of weighted synthesis filter */
+ Word16 x[], /* (i) Q0 : target vector */
+ Word16 dn[] /* (o) <12bit : correlation between target and h[] */
+ )
+{
+ Word32 i, j;
+ Word32 L_tmp, y32[L_SUBFR], L_tot;
+ Word16 *p1, *p2;
+ Word32 *p3;
+ Word32 L_max, L_max1, L_max2, L_max3;
+ /* first keep the result on 32 bits and find absolute maximum */
+ L_tot = 1;
+ L_max = 0;
+ L_max1 = 0;
+ L_max2 = 0;
+ L_max3 = 0;
+ for (i = 0; i < L_SUBFR; i += STEP)
+ {
+ L_tmp = 1; /* 1 -> to avoid null dn[] */
+ p1 = &x[i];
+ p2 = &h[0];
+ for (j = i; j < L_SUBFR; j++)
+ L_tmp += vo_L_mult(*p1++, *p2++);
+
+ y32[i] = L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ if(L_tmp > L_max)
+ {
+ L_max = L_tmp;
+ }
+
+ L_tmp = 1L;
+ p1 = &x[i+1];
+ p2 = &h[0];
+ for (j = i+1; j < L_SUBFR; j++)
+ L_tmp += vo_L_mult(*p1++, *p2++);
+
+ y32[i+1] = L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ if(L_tmp > L_max1)
+ {
+ L_max1 = L_tmp;
+ }
+
+ L_tmp = 1;
+ p1 = &x[i+2];
+ p2 = &h[0];
+ for (j = i+2; j < L_SUBFR; j++)
+ L_tmp += vo_L_mult(*p1++, *p2++);
+
+ y32[i+2] = L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ if(L_tmp > L_max2)
+ {
+ L_max2 = L_tmp;
+ }
+
+ L_tmp = 1;
+ p1 = &x[i+3];
+ p2 = &h[0];
+ for (j = i+3; j < L_SUBFR; j++)
+ L_tmp += vo_L_mult(*p1++, *p2++);
+
+ y32[i+3] = L_tmp;
+ L_tmp = (L_tmp > 0)? L_tmp:-L_tmp;
+ if(L_tmp > L_max3)
+ {
+ L_max3 = L_tmp;
+ }
+ }
+ /* tot += 3*max / 8 */
+ L_max = ((L_max + L_max1 + L_max2 + L_max3) >> 2);
+ L_tot = vo_L_add(L_tot, L_max); /* +max/4 */
+ L_tot = vo_L_add(L_tot, (L_max >> 1)); /* +max/8 */
+
+ /* Find the number of right shifts to do on y32[] so that */
+ /* 6.0 x sumation of max of dn[] in each track not saturate. */
+ j = norm_l(L_tot) - 4; /* 4 -> 16 x tot */
+ p1 = dn;
+ p3 = y32;
+ for (i = 0; i < L_SUBFR; i+=4)
+ {
+ *p1++ = vo_round(L_shl(*p3++, j));
+ *p1++ = vo_round(L_shl(*p3++, j));
+ *p1++ = vo_round(L_shl(*p3++, j));
+ *p1++ = vo_round(L_shl(*p3++, j));
+ }
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/decim54.c b/media/libstagefright/codecs/amrwbenc/src/decim54.c
new file mode 100644
index 0000000..429a7d6
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/decim54.c
@@ -0,0 +1,146 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: decim54.c *
+* *
+* Description:Decimation of 16kHz signal to 12.8kHz *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "cnst.h"
+
+#define FAC5 5
+#define DOWN_FAC 26215 /* 4/5 in Q15 */
+
+#define NB_COEF_DOWN 15
+
+/* Local functions */
+static void Down_samp(
+ Word16 * sig, /* input: signal to downsampling */
+ Word16 * sig_d, /* output: downsampled signal */
+ Word16 L_frame_d /* input: length of output */
+ );
+
+/* 1/5 resolution interpolation filter (in Q14) */
+/* -1.5dB @ 6kHz, -6dB @ 6.4kHz, -10dB @ 6.6kHz, -20dB @ 6.9kHz, -25dB @ 7kHz, -55dB @ 8kHz */
+
+static Word16 fir_down1[4][30] =
+{
+ {-5, 24, -50, 54, 0, -128, 294, -408, 344, 0, -647, 1505, -2379, 3034, 13107, 3034, -2379, 1505, -647, 0, 344, -408,
+ 294, -128, 0, 54, -50, 24, -5, 0},
+
+ {-6, 19, -26, 0, 77, -188, 270, -233, 0, 434, -964, 1366, -1293, 0, 12254, 6575, -2746, 1030, 0, -507, 601, -441,
+ 198, 0, -95, 99, -58, 18, 0, -1},
+
+ {-3, 9, 0, -41, 111, -170, 153, 0, -295, 649, -888, 770, 0, -1997, 9894, 9894, -1997, 0, 770, -888, 649, -295, 0,
+ 153, -170, 111, -41, 0, 9, -3},
+
+ {-1, 0, 18, -58, 99, -95, 0, 198, -441, 601, -507, 0, 1030, -2746, 6575, 12254, 0, -1293, 1366, -964, 434, 0,
+ -233, 270, -188, 77, 0, -26, 19, -6}
+};
+
+void Init_Decim_12k8(
+ Word16 mem[] /* output: memory (2*NB_COEF_DOWN) set to zeros */
+ )
+{
+ Set_zero(mem, 2 * NB_COEF_DOWN);
+ return;
+}
+
+void Decim_12k8(
+ Word16 sig16k[], /* input: signal to downsampling */
+ Word16 lg, /* input: length of input */
+ Word16 sig12k8[], /* output: decimated signal */
+ Word16 mem[] /* in/out: memory (2*NB_COEF_DOWN) */
+ )
+{
+ Word16 lg_down;
+ Word16 signal[L_FRAME16k + (2 * NB_COEF_DOWN)];
+
+ Copy(mem, signal, 2 * NB_COEF_DOWN);
+
+ Copy(sig16k, signal + (2 * NB_COEF_DOWN), lg);
+
+ lg_down = (lg * DOWN_FAC)>>15;
+
+ Down_samp(signal + NB_COEF_DOWN, sig12k8, lg_down);
+
+ Copy(signal + lg, mem, 2 * NB_COEF_DOWN);
+
+ return;
+}
+
+static void Down_samp(
+ Word16 * sig, /* input: signal to downsampling */
+ Word16 * sig_d, /* output: downsampled signal */
+ Word16 L_frame_d /* input: length of output */
+ )
+{
+ Word32 i, j, frac, pos;
+ Word16 *x, *y;
+ Word32 L_sum;
+
+ pos = 0; /* position is in Q2 -> 1/4 resolution */
+ for (j = 0; j < L_frame_d; j++)
+ {
+ i = (pos >> 2); /* integer part */
+ frac = pos & 3; /* fractional part */
+ x = sig + i - NB_COEF_DOWN + 1;
+ y = (Word16 *)(fir_down1 + frac);
+
+ L_sum = vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x++),(*y++));
+ L_sum += vo_mult32((*x),(*y));
+
+ L_sum = L_shl2(L_sum, 2);
+ sig_d[j] = extract_h(L_add(L_sum, 0x8000));
+ pos += FAC5; /* pos + 5/4 */
+ }
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/deemph.c b/media/libstagefright/codecs/amrwbenc/src/deemph.c
new file mode 100644
index 0000000..6ad528d
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/deemph.c
@@ -0,0 +1,117 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: deemph.c *
+* *
+* Description:filtering through 1/(1-mu z^ -1) *
+* Deemph2 --> signal is divided by 2 *
+* Deemph_32 --> for 32 bits signal. *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+
+void Deemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ )
+{
+ Word32 i;
+ Word32 L_tmp;
+
+ L_tmp = L_deposit_h(x[0]);
+ L_tmp = L_mac(L_tmp, *mem, mu);
+ x[0] = vo_round(L_tmp);
+
+ for (i = 1; i < L; i++)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp = L_mac(L_tmp, x[i - 1], mu);
+ x[i] = voround(L_tmp);
+ }
+
+ *mem = x[L - 1];
+
+ return;
+}
+
+
+void Deemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ )
+{
+ Word32 i;
+ Word32 L_tmp;
+ L_tmp = x[0] << 15;
+ L_tmp += ((*mem) * mu)<<1;
+ x[0] = (L_tmp + 0x8000)>>16;
+ for (i = 1; i < L; i++)
+ {
+ L_tmp = x[i] << 15;
+ L_tmp += (x[i - 1] * mu)<<1;
+ x[i] = (L_tmp + 0x8000)>>16;
+ }
+ *mem = x[L - 1];
+ return;
+}
+
+
+void Deemph_32(
+ Word16 x_hi[], /* (i) : input signal (bit31..16) */
+ Word16 x_lo[], /* (i) : input signal (bit15..4) */
+ Word16 y[], /* (o) : output signal (x16) */
+ Word16 mu, /* (i) Q15 : deemphasis factor */
+ Word16 L, /* (i) : vector size */
+ Word16 * mem /* (i/o) : memory (y[-1]) */
+ )
+{
+ Word16 fac;
+ Word32 i, L_tmp;
+
+ fac = mu >> 1; /* Q15 --> Q14 */
+
+ L_tmp = L_deposit_h(x_hi[0]);
+ L_tmp += (x_lo[0] * 8)<<1;
+ L_tmp = (L_tmp << 3);
+ L_tmp += ((*mem) * fac)<<1;
+ L_tmp = (L_tmp << 1);
+ y[0] = (L_tmp + 0x8000)>>16;
+
+ for (i = 1; i < L; i++)
+ {
+ L_tmp = L_deposit_h(x_hi[i]);
+ L_tmp += (x_lo[i] * 8)<<1;
+ L_tmp = (L_tmp << 3);
+ L_tmp += (y[i - 1] * fac)<<1;
+ L_tmp = (L_tmp << 1);
+ y[i] = (L_tmp + 0x8000)>>16;
+ }
+
+ *mem = y[L - 1];
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/dtx.c b/media/libstagefright/codecs/amrwbenc/src/dtx.c
new file mode 100644
index 0000000..02921eb
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/dtx.c
@@ -0,0 +1,605 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: dtx.c *
+* *
+* Description:DTX functions *
+* *
+************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "cnst.h"
+#include "acelp.h" /* prototype of functions */
+#include "bits.h"
+#include "dtx.h"
+#include "log2.h"
+#include "mem_align.h"
+
+static void aver_isf_history(
+ Word16 isf_old[],
+ Word16 indices[],
+ Word32 isf_aver[]
+ );
+
+static void find_frame_indices(
+ Word16 isf_old_tx[],
+ Word16 indices[],
+ dtx_encState * st
+ );
+
+static Word16 dithering_control(
+ dtx_encState * st
+ );
+
+/* excitation energy adjustment depending on speech coder mode used, Q7 */
+static Word16 en_adjust[9] =
+{
+ 230, /* mode0 = 7k : -5.4dB */
+ 179, /* mode1 = 9k : -4.2dB */
+ 141, /* mode2 = 12k : -3.3dB */
+ 128, /* mode3 = 14k : -3.0dB */
+ 122, /* mode4 = 16k : -2.85dB */
+ 115, /* mode5 = 18k : -2.7dB */
+ 115, /* mode6 = 20k : -2.7dB */
+ 115, /* mode7 = 23k : -2.7dB */
+ 115 /* mode8 = 24k : -2.7dB */
+};
+
+/**************************************************************************
+*
+* Function : dtx_enc_init
+*
+**************************************************************************/
+Word16 dtx_enc_init(dtx_encState ** st, Word16 isf_init[], VO_MEM_OPERATOR *pMemOP)
+{
+ dtx_encState *s;
+
+ if (st == (dtx_encState **) NULL)
+ {
+ fprintf(stderr, "dtx_enc_init: invalid parameter\n");
+ return -1;
+ }
+ *st = NULL;
+
+ /* allocate memory */
+ if ((s = (dtx_encState *)mem_malloc(pMemOP, sizeof(dtx_encState), 32, VO_INDEX_ENC_AMRWB)) == NULL)
+ {
+ fprintf(stderr, "dtx_enc_init: can not malloc state structure\n");
+ return -1;
+ }
+ dtx_enc_reset(s, isf_init);
+ *st = s;
+ return 0;
+}
+
+/**************************************************************************
+*
+* Function : dtx_enc_reset
+*
+**************************************************************************/
+Word16 dtx_enc_reset(dtx_encState * st, Word16 isf_init[])
+{
+ Word32 i;
+
+ if (st == (dtx_encState *) NULL)
+ {
+ fprintf(stderr, "dtx_enc_reset: invalid parameter\n");
+ return -1;
+ }
+ st->hist_ptr = 0;
+ st->log_en_index = 0;
+
+ /* Init isf_hist[] */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ Copy(isf_init, &st->isf_hist[i * M], M);
+ }
+ st->cng_seed = RANDOM_INITSEED;
+
+ /* Reset energy history */
+ Set_zero(st->log_en_hist, DTX_HIST_SIZE);
+
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ st->decAnaElapsedCount = 32767;
+
+ for (i = 0; i < 28; i++)
+ {
+ st->D[i] = 0;
+ }
+
+ for (i = 0; i < DTX_HIST_SIZE - 1; i++)
+ {
+ st->sumD[i] = 0;
+ }
+
+ return 1;
+}
+
+/**************************************************************************
+*
+* Function : dtx_enc_exit
+*
+**************************************************************************/
+void dtx_enc_exit(dtx_encState ** st, VO_MEM_OPERATOR *pMemOP)
+{
+ if (st == NULL || *st == NULL)
+ return;
+ /* deallocate memory */
+ mem_free(pMemOP, *st, VO_INDEX_ENC_AMRWB);
+ *st = NULL;
+ return;
+}
+
+
+/**************************************************************************
+*
+* Function : dtx_enc
+*
+**************************************************************************/
+Word16 dtx_enc(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf[M], /* o : CN ISF vector */
+ Word16 * exc2, /* o : CN excitation */
+ Word16 ** prms
+ )
+{
+ Word32 i, j;
+ Word16 indice[7];
+ Word16 log_en, gain, level, exp, exp0, tmp;
+ Word16 log_en_int_e, log_en_int_m;
+ Word32 L_isf[M], ener32, level32;
+ Word16 isf_order[3];
+ Word16 CN_dith;
+
+ /* VOX mode computation of SID parameters */
+ log_en = 0;
+ for (i = 0; i < M; i++)
+ {
+ L_isf[i] = 0;
+ }
+ /* average energy and isf */
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ /* Division by DTX_HIST_SIZE = 8 has been done in dtx_buffer. log_en is in Q10 */
+ log_en = add(log_en, st->log_en_hist[i]);
+
+ }
+ find_frame_indices(st->isf_hist, isf_order, st);
+ aver_isf_history(st->isf_hist, isf_order, L_isf);
+
+ for (j = 0; j < M; j++)
+ {
+ isf[j] = (Word16)(L_isf[j] >> 3); /* divide by 8 */
+ }
+
+ /* quantize logarithmic energy to 6 bits (-6 : 66 dB) which corresponds to -2:22 in log2(E). */
+ /* st->log_en_index = (short)( (log_en + 2.0) * 2.625 ); */
+
+ /* increase dynamics to 7 bits (Q8) */
+ log_en = (log_en >> 2);
+
+ /* Add 2 in Q8 = 512 to get log2(E) between 0:24 */
+ log_en = add(log_en, 512);
+
+ /* Multiply by 2.625 to get full 6 bit range. 2.625 = 21504 in Q13. The result is in Q6 */
+ log_en = mult(log_en, 21504);
+
+ /* Quantize Energy */
+ st->log_en_index = shr(log_en, 6);
+
+ if(st->log_en_index > 63)
+ {
+ st->log_en_index = 63;
+ }
+ if (st->log_en_index < 0)
+ {
+ st->log_en_index = 0;
+ }
+ /* Quantize ISFs */
+ Qisf_ns(isf, isf, indice);
+
+
+ Parm_serial(indice[0], 6, prms);
+ Parm_serial(indice[1], 6, prms);
+ Parm_serial(indice[2], 6, prms);
+ Parm_serial(indice[3], 5, prms);
+ Parm_serial(indice[4], 5, prms);
+
+ Parm_serial((st->log_en_index), 6, prms);
+
+ CN_dith = dithering_control(st);
+ Parm_serial(CN_dith, 1, prms);
+
+ /* level = (float)( pow( 2.0f, (float)st->log_en_index / 2.625 - 2.0 ) ); */
+ /* log2(E) in Q9 (log2(E) lies in between -2:22) */
+ log_en = shl(st->log_en_index, 15 - 6);
+
+ /* Divide by 2.625; log_en will be between 0:24 */
+ log_en = mult(log_en, 12483);
+ /* the result corresponds to log2(gain) in Q10 */
+
+ /* Find integer part */
+ log_en_int_e = (log_en >> 10);
+
+ /* Find fractional part */
+ log_en_int_m = (Word16) (log_en & 0x3ff);
+ log_en_int_m = shl(log_en_int_m, 5);
+
+ /* Subtract 2 from log_en in Q9, i.e divide the gain by 2 (energy by 4) */
+ /* Add 16 in order to have the result of pow2 in Q16 */
+ log_en_int_e = add(log_en_int_e, 16 - 1);
+
+ level32 = Pow2(log_en_int_e, log_en_int_m); /* Q16 */
+ exp0 = norm_l(level32);
+ level32 = (level32 << exp0); /* level in Q31 */
+ exp0 = (15 - exp0);
+ level = extract_h(level32); /* level in Q15 */
+
+ /* generate white noise vector */
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = (Random(&(st->cng_seed)) >> 4);
+ }
+
+ /* gain = level / sqrt(ener) * sqrt(L_FRAME) */
+
+ /* energy of generated excitation */
+ ener32 = Dot_product12(exc2, exc2, L_FRAME, &exp);
+
+ Isqrt_n(&ener32, &exp);
+
+ gain = extract_h(ener32);
+
+ gain = mult(level, gain); /* gain in Q15 */
+
+ exp = add(exp0, exp);
+
+ /* Multiply by sqrt(L_FRAME)=16, i.e. shift left by 4 */
+ exp += 4;
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ tmp = mult(exc2[i], gain); /* Q0 * Q15 */
+ exc2[i] = shl(tmp, exp);
+ }
+
+ return 0;
+}
+
+/**************************************************************************
+*
+* Function : dtx_buffer Purpose : handles the DTX buffer
+*
+**************************************************************************/
+Word16 dtx_buffer(
+ dtx_encState * st, /* i/o : State struct */
+ Word16 isf_new[], /* i : isf vector */
+ Word32 enr, /* i : residual energy (in L_FRAME) */
+ Word16 codec_mode
+ )
+{
+ Word16 log_en;
+
+ Word16 log_en_e;
+ Word16 log_en_m;
+ st->hist_ptr = add(st->hist_ptr, 1);
+ if(st->hist_ptr == DTX_HIST_SIZE)
+ {
+ st->hist_ptr = 0;
+ }
+ /* copy lsp vector into buffer */
+ Copy(isf_new, &st->isf_hist[st->hist_ptr * M], M);
+
+ /* log_en = (float)log10(enr*0.0059322)/(float)log10(2.0f); */
+ Log2(enr, &log_en_e, &log_en_m);
+
+ /* convert exponent and mantissa to Word16 Q7. Q7 is used to simplify averaging in dtx_enc */
+ log_en = shl(log_en_e, 7); /* Q7 */
+ log_en = add(log_en, shr(log_en_m, 15 - 7));
+
+ /* Find energy per sample by multiplying with 0.0059322, i.e subtract log2(1/0.0059322) = 7.39722 The
+ * constant 0.0059322 takes into account windowings and analysis length from autocorrelation
+ * computations; 7.39722 in Q7 = 947 */
+ /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
+ /* log_en = sub( log_en, 947 + en_adjust[codec_mode] ); */
+
+ /* Find energy per sample (divide by L_FRAME=256), i.e subtract log2(256) = 8.0 (1024 in Q7) */
+ /* Subtract 3 dB = 0.99658 in log2(E) = 127 in Q7. */
+
+ log_en = sub(log_en, add(1024, en_adjust[codec_mode]));
+
+ /* Insert into the buffer */
+ st->log_en_hist[st->hist_ptr] = log_en;
+ return 0;
+}
+
+/**************************************************************************
+*
+* Function : tx_dtx_handler Purpose : adds extra speech hangover
+* to analyze speech on
+* the decoding side.
+**************************************************************************/
+void tx_dtx_handler(dtx_encState * st, /* i/o : State struct */
+ Word16 vad_flag, /* i : vad decision */
+ Word16 * usedMode /* i/o : mode changed or not */
+ )
+{
+
+ /* this state machine is in synch with the GSMEFR txDtx machine */
+ st->decAnaElapsedCount = add(st->decAnaElapsedCount, 1);
+
+ if (vad_flag != 0)
+ {
+ st->dtxHangoverCount = DTX_HANG_CONST;
+ } else
+ { /* non-speech */
+ if (st->dtxHangoverCount == 0)
+ { /* out of decoder analysis hangover */
+ st->decAnaElapsedCount = 0;
+ *usedMode = MRDTX;
+ } else
+ { /* in possible analysis hangover */
+ st->dtxHangoverCount = sub(st->dtxHangoverCount, 1);
+
+ /* decAnaElapsedCount + dtxHangoverCount < DTX_ELAPSED_FRAMES_THRESH */
+ if (sub(add(st->decAnaElapsedCount, st->dtxHangoverCount),
+ DTX_ELAPSED_FRAMES_THRESH) < 0)
+ {
+ *usedMode = MRDTX;
+ /* if short time since decoder update, do not add extra HO */
+ }
+ /* else override VAD and stay in speech mode *usedMode and add extra hangover */
+ }
+ }
+
+ return;
+}
+
+
+
+static void aver_isf_history(
+ Word16 isf_old[],
+ Word16 indices[],
+ Word32 isf_aver[]
+ )
+{
+ Word32 i, j, k;
+ Word16 isf_tmp[2 * M];
+ Word32 L_tmp;
+
+ /* Memorize in isf_tmp[][] the ISF vectors to be replaced by */
+ /* the median ISF vector prior to the averaging */
+ for (k = 0; k < 2; k++)
+ {
+ if ((indices[k] + 1) != 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ isf_tmp[k * M + i] = isf_old[indices[k] * M + i];
+ isf_old[indices[k] * M + i] = isf_old[indices[2] * M + i];
+ }
+ }
+ }
+
+ /* Perform the ISF averaging */
+ for (j = 0; j < M; j++)
+ {
+ L_tmp = 0;
+
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ L_tmp = L_add(L_tmp, L_deposit_l(isf_old[i * M + j]));
+ }
+ isf_aver[j] = L_tmp;
+ }
+
+ /* Retrieve from isf_tmp[][] the ISF vectors saved prior to averaging */
+ for (k = 0; k < 2; k++)
+ {
+ if ((indices[k] + 1) != 0)
+ {
+ for (i = 0; i < M; i++)
+ {
+ isf_old[indices[k] * M + i] = isf_tmp[k * M + i];
+ }
+ }
+ }
+
+ return;
+}
+
+static void find_frame_indices(
+ Word16 isf_old_tx[],
+ Word16 indices[],
+ dtx_encState * st
+ )
+{
+ Word32 L_tmp, summin, summax, summax2nd;
+ Word16 i, j, tmp;
+ Word16 ptr;
+
+ /* Remove the effect of the oldest frame from the column */
+ /* sum sumD[0..DTX_HIST_SIZE-1]. sumD[DTX_HIST_SIZE] is */
+ /* not updated since it will be removed later. */
+
+ tmp = DTX_HIST_SIZE_MIN_ONE;
+ j = -1;
+ for (i = 0; i < DTX_HIST_SIZE_MIN_ONE; i++)
+ {
+ j = add(j, tmp);
+ st->sumD[i] = L_sub(st->sumD[i], st->D[j]);
+ tmp = sub(tmp, 1);
+ }
+
+ /* Shift the column sum sumD. The element sumD[DTX_HIST_SIZE-1] */
+ /* corresponding to the oldest frame is removed. The sum of */
+ /* the distances between the latest isf and other isfs, */
+ /* i.e. the element sumD[0], will be computed during this call. */
+ /* Hence this element is initialized to zero. */
+
+ for (i = DTX_HIST_SIZE_MIN_ONE; i > 0; i--)
+ {
+ st->sumD[i] = st->sumD[i - 1];
+ }
+ st->sumD[0] = 0;
+
+ /* Remove the oldest frame from the distance matrix. */
+ /* Note that the distance matrix is replaced by a one- */
+ /* dimensional array to save static memory. */
+
+ tmp = 0;
+ for (i = 27; i >= 12; i = (Word16) (i - tmp))
+ {
+ tmp = add(tmp, 1);
+ for (j = tmp; j > 0; j--)
+ {
+ st->D[i - j + 1] = st->D[i - j - tmp];
+ }
+ }
+
+ /* Compute the first column of the distance matrix D */
+ /* (squared Euclidean distances from isf1[] to isf_old_tx[][]). */
+
+ ptr = st->hist_ptr;
+ for (i = 1; i < DTX_HIST_SIZE; i++)
+ {
+ /* Compute the distance between the latest isf and the other isfs. */
+ ptr = sub(ptr, 1);
+ if (ptr < 0)
+ {
+ ptr = DTX_HIST_SIZE_MIN_ONE;
+ }
+ L_tmp = 0;
+ for (j = 0; j < M; j++)
+ {
+ tmp = sub(isf_old_tx[st->hist_ptr * M + j], isf_old_tx[ptr * M + j]);
+ L_tmp = L_mac(L_tmp, tmp, tmp);
+ }
+ st->D[i - 1] = L_tmp;
+
+ /* Update also the column sums. */
+ st->sumD[0] = L_add(st->sumD[0], st->D[i - 1]);
+ st->sumD[i] = L_add(st->sumD[i], st->D[i - 1]);
+ }
+
+ /* Find the minimum and maximum distances */
+ summax = st->sumD[0];
+ summin = st->sumD[0];
+ indices[0] = 0;
+ indices[2] = 0;
+ for (i = 1; i < DTX_HIST_SIZE; i++)
+ {
+ if (L_sub(st->sumD[i], summax) > 0)
+ {
+ indices[0] = i;
+ summax = st->sumD[i];
+ }
+ if (L_sub(st->sumD[i], summin) < 0)
+ {
+ indices[2] = i;
+ summin = st->sumD[i];
+ }
+ }
+
+ /* Find the second largest distance */
+ summax2nd = -2147483647L;
+ indices[1] = -1;
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ if ((L_sub(st->sumD[i], summax2nd) > 0) && (sub(i, indices[0]) != 0))
+ {
+ indices[1] = i;
+ summax2nd = st->sumD[i];
+ }
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ indices[i] = sub(st->hist_ptr, indices[i]);
+ if (indices[i] < 0)
+ {
+ indices[i] = add(indices[i], DTX_HIST_SIZE);
+ }
+ }
+
+ /* If maximum distance/MED_THRESH is smaller than minimum distance */
+ /* then the median ISF vector replacement is not performed */
+ tmp = norm_l(summax);
+ summax = (summax << tmp);
+ summin = (summin << tmp);
+ L_tmp = L_mult(voround(summax), INV_MED_THRESH);
+ if(L_tmp <= summin)
+ {
+ indices[0] = -1;
+ }
+ /* If second largest distance/MED_THRESH is smaller than */
+ /* minimum distance then the median ISF vector replacement is */
+ /* not performed */
+ summax2nd = L_shl(summax2nd, tmp);
+ L_tmp = L_mult(voround(summax2nd), INV_MED_THRESH);
+ if(L_tmp <= summin)
+ {
+ indices[1] = -1;
+ }
+ return;
+}
+
+static Word16 dithering_control(
+ dtx_encState * st
+ )
+{
+ Word16 tmp, mean, CN_dith, gain_diff;
+ Word32 i, ISF_diff;
+
+ /* determine how stationary the spectrum of background noise is */
+ ISF_diff = 0;
+ for (i = 0; i < 8; i++)
+ {
+ ISF_diff = L_add(ISF_diff, st->sumD[i]);
+ }
+ if ((ISF_diff >> 26) > 0)
+ {
+ CN_dith = 1;
+ } else
+ {
+ CN_dith = 0;
+ }
+
+ /* determine how stationary the energy of background noise is */
+ mean = 0;
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ mean = add(mean, st->log_en_hist[i]);
+ }
+ mean = (mean >> 3);
+ gain_diff = 0;
+ for (i = 0; i < DTX_HIST_SIZE; i++)
+ {
+ tmp = abs_s(sub(st->log_en_hist[i], mean));
+ gain_diff = add(gain_diff, tmp);
+ }
+ if (gain_diff > GAIN_THR)
+ {
+ CN_dith = 1;
+ }
+ return CN_dith;
+}
diff --git a/media/libstagefright/codecs/amrwbenc/src/g_pitch.c b/media/libstagefright/codecs/amrwbenc/src/g_pitch.c
new file mode 100644
index 0000000..570138e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/g_pitch.c
@@ -0,0 +1,79 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: g_pitch.c *
+* *
+* Description:Compute the gain of pitch. Result in Q12 *
+* if(gain < 0) gain = 0 *
+* if(gain > 1.2) gain = 1.2 *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+
+Word16 G_pitch( /* (o) Q14 : Gain of pitch lag saturated to 1.2 */
+ Word16 xn[], /* (i) : Pitch target. */
+ Word16 y1[], /* (i) : filtered adaptive codebook. */
+ Word16 g_coeff[], /* : Correlations need for gain quantization. */
+ Word16 L_subfr /* : Length of subframe. */
+ )
+{
+ Word32 i;
+ Word16 xy, yy, exp_xy, exp_yy, gain;
+ /* Compute scalar product <y1[],y1[]> */
+#ifdef ASM_OPT /* asm optimization branch */
+ /* Compute scalar product <xn[],y1[]> */
+ xy = extract_h(Dot_product12_asm(xn, y1, L_subfr, &exp_xy));
+ yy = extract_h(Dot_product12_asm(y1, y1, L_subfr, &exp_yy));
+
+#else
+ /* Compute scalar product <xn[],y1[]> */
+ xy = extract_h(Dot_product12(xn, y1, L_subfr, &exp_xy));
+ yy = extract_h(Dot_product12(y1, y1, L_subfr, &exp_yy));
+
+#endif
+
+ g_coeff[0] = yy;
+ g_coeff[1] = exp_yy;
+ g_coeff[2] = xy;
+ g_coeff[3] = exp_xy;
+
+ /* If (xy < 0) gain = 0 */
+ if (xy < 0)
+ return ((Word16) 0);
+
+ /* compute gain = xy/yy */
+
+ xy >>= 1; /* Be sure xy < yy */
+ gain = div_s(xy, yy);
+
+ i = exp_xy;
+ i -= exp_yy;
+
+ gain = shl(gain, i);
+
+ /* if (gain > 1.2) gain = 1.2 in Q14 */
+ if(gain > 19661)
+ {
+ gain = 19661;
+ }
+ return (gain);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/gpclip.c b/media/libstagefright/codecs/amrwbenc/src/gpclip.c
new file mode 100644
index 0000000..e23f2f4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/gpclip.c
@@ -0,0 +1,110 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: gpclip.c *
+* *
+* Description:To avoid unstable synthesis on frame erasure, the gain *
+* need to be limited(gain pitch < 1.0) when the following *
+* case occurs *
+* a resonance on LPC filter(lp_disp < 60Hz) *
+* a good pitch prediction (lp_gp > 0.95) *
+* *
+***************************************************************************/
+#include "typedef.h"
+#include "basic_op.h"
+
+#define DIST_ISF_MAX 307 /* 120 Hz (6400Hz=16384) */
+#define DIST_ISF_THRES 154 /* 60 (6400Hz=16384) */
+#define GAIN_PIT_THRES 14746 /* 0.9 in Q14 */
+#define GAIN_PIT_MIN 9830 /* 0.6 in Q14 */
+#define M 16
+
+
+void Init_gp_clip(
+ Word16 mem[] /* (o) : memory of gain of pitch clipping algorithm */
+ )
+{
+ mem[0] = DIST_ISF_MAX;
+ mem[1] = GAIN_PIT_MIN;
+}
+
+
+Word16 Gp_clip(
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+ )
+{
+ Word16 clip = 0;
+ if ((mem[0] < DIST_ISF_THRES) && (mem[1] > GAIN_PIT_THRES))
+ clip = 1;
+
+ return (clip);
+}
+
+
+void Gp_clip_test_isf(
+ Word16 isf[], /* (i) : isf values (in frequency domain) */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+ )
+{
+ Word16 dist, dist_min;
+ Word32 i;
+
+ dist_min = vo_sub(isf[1], isf[0]);
+
+ for (i = 2; i < M - 1; i++)
+ {
+ dist = vo_sub(isf[i], isf[i - 1]);
+ if(dist < dist_min)
+ {
+ dist_min = dist;
+ }
+ }
+
+ dist = extract_h(L_mac(vo_L_mult(26214, mem[0]), 6554, dist_min));
+
+ if (dist > DIST_ISF_MAX)
+ {
+ dist = DIST_ISF_MAX;
+ }
+ mem[0] = dist;
+
+ return;
+}
+
+
+void Gp_clip_test_gain_pit(
+ Word16 gain_pit, /* (i) Q14 : gain of quantized pitch */
+ Word16 mem[] /* (i/o) : memory of gain of pitch clipping algorithm */
+ )
+{
+ Word16 gain;
+ Word32 L_tmp;
+ L_tmp = (29491 * mem[1])<<1;
+ L_tmp += (3277 * gain_pit)<<1;
+
+ gain = extract_h(L_tmp);
+
+ if(gain < GAIN_PIT_MIN)
+ {
+ gain = GAIN_PIT_MIN;
+ }
+ mem[1] = gain;
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/homing.c b/media/libstagefright/codecs/amrwbenc/src/homing.c
new file mode 100644
index 0000000..015633f
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/homing.c
@@ -0,0 +1,46 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: homing.c *
+* *
+* Description:Performs the homing routines *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "cnst.h"
+#include "basic_op.h"
+#include "bits.h"
+#include "homing.tab"
+
+Word16 encoder_homing_frame_test(Word16 input_frame[])
+{
+ Word32 i;
+ Word16 j = 0;
+
+ /* check 320 input samples for matching EHF_MASK: defined in e_homing.h */
+ for (i = 0; i < L_FRAME16k; i++)
+ {
+ j = (Word16) (input_frame[i] ^ EHF_MASK);
+
+ if (j)
+ break;
+ }
+
+ return (Word16) (!j);
+}
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp400.c b/media/libstagefright/codecs/amrwbenc/src/hp400.c
new file mode 100644
index 0000000..463a53a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp400.c
@@ -0,0 +1,106 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: hp400.c *
+* *
+* Description: *
+* 2nd order high pass filter with cut off frequency at 400 Hz. *
+* Designed with cheby2 function in MATLAB. *
+* Optimized for fixed-point to get the following frequency response: *
+* *
+* frequency: 0Hz 100Hz 200Hz 300Hz 400Hz 630Hz 1.5kHz 3kHz *
+* dB loss: -infdB -30dB -20dB -10dB -3dB +6dB +1dB 0dB *
+* *
+* Algorithm: *
+* *
+* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] *
+* + a[1]*y[i-1] + a[2]*y[i-2]; *
+* *
+* Word16 b[3] = {3660, -7320, 3660}; in Q12 *
+* Word16 a[3] = {4096, 7320, -3540}; in Q12 *
+* *
+* float --> b[3] = {0.893554687, -1.787109375, 0.893554687}; *
+* a[3] = {1.000000000, 1.787109375, -0.864257812}; *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+
+/* filter coefficients */
+static Word16 b[3] = {915, -1830, 915}; /* Q12 (/4) */
+static Word16 a[3] = {16384, 29280, -14160}; /* Q12 (x4) */
+/* Initialization of static values */
+
+void Init_HP400_12k8(Word16 mem[])
+{
+ Set_zero(mem, 6);
+}
+
+
+void HP400_12k8(
+ Word16 signal[], /* input signal / output is divided by 16 */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+ )
+{
+ Word16 x2;
+ Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+ Word32 L_tmp;
+ Word32 num;
+ y2_hi = *mem++;
+ y2_lo = *mem++;
+ y1_hi = *mem++;
+ y1_lo = *mem++;
+ x0 = *mem++;
+ x1 = *mem;
+ num = (Word32)lg;
+ do
+ {
+ x2 = x1;
+ x1 = x0;
+ x0 = *signal;
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */
+ /* + a[1]*y[i-1] + a[2] * y[i-2]; */
+ L_tmp = 8192L; /* rounding to maximise precision */
+ L_tmp += y1_lo * a[1];
+ L_tmp += y2_lo * a[2];
+ L_tmp = L_tmp >> 14;
+ L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2)* b[0] + x1 * b[1]) << 1;
+ L_tmp <<= 1; /* coeff Q12 --> Q13 */
+ y2_hi = y1_hi;
+ y2_lo = y1_lo;
+ y1_hi = (Word16)(L_tmp>>16);
+ y1_lo = (Word16)((L_tmp & 0xffff)>>1);
+
+ /* signal is divided by 16 to avoid overflow in energy computation */
+ *signal++ = (L_tmp + 0x8000) >> 16;
+ }while(--num !=0);
+
+ *mem-- = x1;
+ *mem-- = x0;
+ *mem-- = y1_lo;
+ *mem-- = y1_hi;
+ *mem-- = y2_lo;
+ *mem = y2_hi;
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp50.c b/media/libstagefright/codecs/amrwbenc/src/hp50.c
new file mode 100644
index 0000000..53e3d7b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp50.c
@@ -0,0 +1,106 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: hp50.c *
+* *
+* Description: *
+* 2nd order high pass filter with cut off frequency at 31 Hz. *
+* Designed with cheby2 function in MATLAB. *
+* Optimized for fixed-point to get the following frequency response: *
+* *
+* frequency: 0Hz 14Hz 24Hz 31Hz 37Hz 41Hz 47Hz *
+* dB loss: -infdB -15dB -6dB -3dB -1.5dB -1dB -0.5dB *
+* *
+* Algorithm: *
+* *
+* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] *
+* + a[1]*y[i-1] + a[2]*y[i-2]; *
+* *
+* Word16 b[3] = {4053, -8106, 4053}; in Q12 *
+* Word16 a[3] = {8192, 16211, -8021}; in Q12 *
+* *
+* float --> b[3] = {0.989501953, -1.979003906, 0.989501953}; *
+* a[3] = {1.000000000, 1.978881836, -0.979125977}; *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+#include "acelp.h"
+
+/* filter coefficients */
+static Word16 b[3] = {4053, -8106, 4053}; /* Q12 */
+static Word16 a[3] = {8192, 16211, -8021}; /* Q12 (x2) */
+
+/* Initialization of static values */
+
+void Init_HP50_12k8(Word16 mem[])
+{
+ Set_zero(mem, 6);
+}
+
+
+void HP50_12k8(
+ Word16 signal[], /* input/output signal */
+ Word16 lg, /* lenght of signal */
+ Word16 mem[] /* filter memory [6] */
+ )
+{
+ Word16 x2;
+ Word16 y2_hi, y2_lo, y1_hi, y1_lo, x0, x1;
+ Word32 L_tmp;
+ Word32 num;
+
+ y2_hi = *mem++;
+ y2_lo = *mem++;
+ y1_hi = *mem++;
+ y1_lo = *mem++;
+ x0 = *mem++;
+ x1 = *mem;
+ num = (Word32)lg;
+ do
+ {
+ x2 = x1;
+ x1 = x0;
+ x0 = *signal;
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] */
+ /* + a[1]*y[i-1] + a[2] * y[i-2]; */
+ L_tmp = 8192 ; /* rounding to maximise precision */
+ L_tmp += y1_lo * a[1];
+ L_tmp += y2_lo * a[2];
+ L_tmp = L_tmp >> 14;
+ L_tmp += (y1_hi * a[1] + y2_hi * a[2] + (x0 + x2) * b[0] + x1 * b[1]) << 1;
+ L_tmp <<= 2; /* coeff Q12 --> Q13 */
+ y2_hi = y1_hi;
+ y2_lo = y1_lo;
+ y1_hi = (Word16)(L_tmp>>16);
+ y1_lo = (Word16)((L_tmp & 0xffff)>>1);
+ *signal++ = extract_h((L_add((L_tmp<<1), 0x8000)));
+ }while(--num !=0);
+
+ *mem-- = x1;
+ *mem-- = x0;
+ *mem-- = y1_lo;
+ *mem-- = y1_hi;
+ *mem-- = y2_lo;
+ *mem-- = y2_hi;
+
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp6k.c b/media/libstagefright/codecs/amrwbenc/src/hp6k.c
new file mode 100644
index 0000000..5ee5b20
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp6k.c
@@ -0,0 +1,93 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: hp6k.c *
+* *
+* Description:15th order band pass 6kHz to 7kHz FIR filter *
+* frequency: 4kHz 5kHz 5.5kHz 6kHz 6.5kHz 7kHz 7.5kHz 8kHz *
+* dB loss: -60dB -45dB -13dB -3dB 0dB -3dB -13dB -45dB *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "cnst.h"
+
+#define L_FIR 31
+
+/* filter coefficients (gain=4.0) */
+
+Word16 fir_6k_7k[L_FIR] =
+{
+ -32, 47, 32, -27, -369,
+ 1122, -1421, 0, 3798, -8880,
+ 12349, -10984, 3548, 7766, -18001,
+ 22118, -18001, 7766, 3548, -10984,
+ 12349, -8880, 3798, 0, -1421,
+ 1122, -369, -27, 32, 47,
+ -32
+};
+
+
+void Init_Filt_6k_7k(Word16 mem[]) /* mem[30] */
+{
+ Set_zero(mem, L_FIR - 1);
+ return;
+}
+
+void Filt_6k_7k(
+ Word16 signal[], /* input: signal */
+ Word16 lg, /* input: length of input */
+ Word16 mem[] /* in/out: memory (size=30) */
+ )
+{
+ Word16 x[L_SUBFR16k + (L_FIR - 1)];
+ Word32 i, L_tmp;
+
+ Copy(mem, x, L_FIR - 1);
+ for (i = lg - 1; i >= 0; i--)
+ {
+ x[i + L_FIR - 1] = signal[i] >> 2; /* gain of filter = 4 */
+ }
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = (x[i] + x[i+ 30]) * fir_6k_7k[0];
+ L_tmp += (x[i+1] + x[i + 29]) * fir_6k_7k[1];
+ L_tmp += (x[i+2] + x[i + 28]) * fir_6k_7k[2];
+ L_tmp += (x[i+3] + x[i + 27]) * fir_6k_7k[3];
+ L_tmp += (x[i+4] + x[i + 26]) * fir_6k_7k[4];
+ L_tmp += (x[i+5] + x[i + 25]) * fir_6k_7k[5];
+ L_tmp += (x[i+6] + x[i + 24]) * fir_6k_7k[6];
+ L_tmp += (x[i+7] + x[i + 23]) * fir_6k_7k[7];
+ L_tmp += (x[i+8] + x[i + 22]) * fir_6k_7k[8];
+ L_tmp += (x[i+9] + x[i + 21]) * fir_6k_7k[9];
+ L_tmp += (x[i+10] + x[i + 20]) * fir_6k_7k[10];
+ L_tmp += (x[i+11] + x[i + 19]) * fir_6k_7k[11];
+ L_tmp += (x[i+12] + x[i + 18]) * fir_6k_7k[12];
+ L_tmp += (x[i+13] + x[i + 17]) * fir_6k_7k[13];
+ L_tmp += (x[i+14] + x[i + 16]) * fir_6k_7k[14];
+ L_tmp += (x[i+15]) * fir_6k_7k[15];
+ signal[i] = (L_tmp + 0x4000) >> 15;
+ }
+
+ Copy(x + lg, mem, L_FIR - 1);
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c b/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c
new file mode 100644
index 0000000..7fb62a4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/hp_wsp.c
@@ -0,0 +1,148 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: hp_wsp.c *
+* Description: *
+* 3nd order high pass filter with cut off frequency at 180Hz *
+* Algorithm: *
+* *
+* y[i] = b[0]*x[i] + b[1]*x[i-1] + b[2]*x[i-2] + b[3]*x[i-3] *
+* + a[1]*y[i-1] + a[2]*y[i-2] + a[3]*y[i-3]; *
+* *
+* float a_coef[HP_ORDER]= { *
+* -2.64436711600664f, *
+* 2.35087386625360f, *
+* -0.70001156927424f}; *
+* *
+* float b_coef[HP_ORDER+1]= { *
+* -0.83787057505665f, *
+* 2.50975570071058f, *
+* -2.50975570071058f, *
+* 0.83787057505665f}; *
+* *
+*************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+
+/* filter coefficients in Q12 */
+static Word16 a[4] = {8192, 21663, -19258, 5734};
+static Word16 b[4] = {-3432, +10280, -10280, +3432};
+
+/* Initialization of static values */
+void Init_Hp_wsp(Word16 mem[])
+{
+ Set_zero(mem, 9);
+
+ return;
+}
+
+void scale_mem_Hp_wsp(Word16 mem[], Word16 exp)
+{
+ Word32 i;
+ Word32 L_tmp;
+
+ for (i = 0; i < 6; i += 2)
+ {
+ L_tmp = ((mem[i] << 16) + (mem[i + 1]<<1));
+ L_tmp = L_shl(L_tmp, exp);
+ mem[i] = L_tmp >> 16;
+ mem[i + 1] = (L_tmp & 0xffff)>>1;
+ }
+
+ for (i = 6; i < 9; i++)
+ {
+ L_tmp = L_deposit_h(mem[i]); /* x[i] */
+ L_tmp = L_shl(L_tmp, exp);
+ mem[i] = vo_round(L_tmp);
+ }
+
+ return;
+}
+
+
+void Hp_wsp(
+ Word16 wsp[], /* i : wsp[] signal */
+ Word16 hp_wsp[], /* o : hypass wsp[] */
+ Word16 lg, /* i : lenght of signal */
+ Word16 mem[] /* i/o : filter memory [9] */
+ )
+{
+ Word16 x0, x1, x2, x3;
+ Word16 y3_hi, y3_lo, y2_hi, y2_lo, y1_hi, y1_lo;
+ Word32 i, L_tmp;
+
+ y3_hi = mem[0];
+ y3_lo = mem[1];
+ y2_hi = mem[2];
+ y2_lo = mem[3];
+ y1_hi = mem[4];
+ y1_lo = mem[5];
+ x0 = mem[6];
+ x1 = mem[7];
+ x2 = mem[8];
+
+ for (i = 0; i < lg; i++)
+ {
+ x3 = x2;
+ x2 = x1;
+ x1 = x0;
+ x0 = wsp[i];
+ /* y[i] = b[0]*x[i] + b[1]*x[i-1] + b140[2]*x[i-2] + b[3]*x[i-3] */
+ /* + a[1]*y[i-1] + a[2] * y[i-2] + a[3]*y[i-3] */
+
+ L_tmp = 16384L; /* rounding to maximise precision */
+ L_tmp += (y1_lo * a[1])<<1;
+ L_tmp += (y2_lo * a[2])<<1;
+ L_tmp += (y3_lo * a[3])<<1;
+ L_tmp = L_tmp >> 15;
+ L_tmp += (y1_hi * a[1])<<1;
+ L_tmp += (y2_hi * a[2])<<1;
+ L_tmp += (y3_hi * a[3])<<1;
+ L_tmp += (x0 * b[0])<<1;
+ L_tmp += (x1 * b[1])<<1;
+ L_tmp += (x2 * b[2])<<1;
+ L_tmp += (x3 * b[3])<<1;
+
+ L_tmp = L_tmp << 2;
+
+ y3_hi = y2_hi;
+ y3_lo = y2_lo;
+ y2_hi = y1_hi;
+ y2_lo = y1_lo;
+ y1_hi = L_tmp >> 16;
+ y1_lo = (L_tmp & 0xffff) >>1;
+
+ hp_wsp[i] = (L_tmp + 0x4000)>>15;
+ }
+
+ mem[0] = y3_hi;
+ mem[1] = y3_lo;
+ mem[2] = y2_hi;
+ mem[3] = y2_lo;
+ mem[4] = y1_hi;
+ mem[5] = y1_lo;
+ mem[6] = x0;
+ mem[7] = x1;
+ mem[8] = x2;
+
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/int_lpc.c b/media/libstagefright/codecs/amrwbenc/src/int_lpc.c
new file mode 100644
index 0000000..be1fd0b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/int_lpc.c
@@ -0,0 +1,66 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: int_lpc.c *
+* *
+* Description:Interpolation of the LP parameters in 4 subframes. *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "acelp.h"
+
+#define MP1 (M+1)
+
+
+void Int_isp(
+ Word16 isp_old[], /* input : isps from past frame */
+ Word16 isp_new[], /* input : isps from present frame */
+ Word16 frac[], /* input : fraction for 3 first subfr (Q15) */
+ Word16 Az[] /* output: LP coefficients in 4 subframes */
+ )
+{
+ Word32 i, k;
+ Word16 fac_old, fac_new;
+ Word16 isp[M];
+ Word32 L_tmp;
+
+ for (k = 0; k < 3; k++)
+ {
+ fac_new = frac[k];
+ fac_old = (32767 - fac_new) + 1; /* 1.0 - fac_new */
+
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = (isp_old[i] * fac_old)<<1;
+ L_tmp += (isp_new[i] * fac_new)<<1;
+ isp[i] = (L_tmp + 0x8000)>>16;
+ }
+ Isp_Az(isp, Az, M, 0);
+ Az += MP1;
+ }
+
+ /* 4th subframe: isp_new (frac=1.0) */
+ Isp_Az(isp_new, Az, M, 0);
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_az.c b/media/libstagefright/codecs/amrwbenc/src/isp_az.c
new file mode 100644
index 0000000..7b44d12
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/isp_az.c
@@ -0,0 +1,247 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: isp_az.c *
+* *
+* Description:Compute the LPC coefficients from isp (order=M) *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "cnst.h"
+
+#define NC (M/2)
+#define NC16k (M16k/2)
+
+/* local function */
+
+static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n);
+static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n);
+
+void Isp_Az(
+ Word16 isp[], /* (i) Q15 : Immittance spectral pairs */
+ Word16 a[], /* (o) Q12 : predictor coefficients (order = M) */
+ Word16 m,
+ Word16 adaptive_scaling /* (i) 0 : adaptive scaling disabled */
+ /* 1 : adaptive scaling enabled */
+ )
+{
+ Word32 i, j;
+ Word16 hi, lo;
+ Word32 f1[NC16k + 1], f2[NC16k];
+ Word16 nc;
+ Word32 t0;
+ Word16 q, q_sug;
+ Word32 tmax;
+
+ nc = (m >> 1);
+ if(nc > 8)
+ {
+ Get_isp_pol_16kHz(&isp[0], f1, nc);
+ for (i = 0; i <= nc; i++)
+ {
+ f1[i] = f1[i] << 2;
+ }
+ } else
+ Get_isp_pol(&isp[0], f1, nc);
+
+ if (nc > 8)
+ {
+ Get_isp_pol_16kHz(&isp[1], f2, (nc - 1));
+ for (i = 0; i <= nc - 1; i++)
+ {
+ f2[i] = f2[i] << 2;
+ }
+ } else
+ Get_isp_pol(&isp[1], f2, (nc - 1));
+
+ /*-----------------------------------------------------*
+ * Multiply F2(z) by (1 - z^-2) *
+ *-----------------------------------------------------*/
+
+ for (i = (nc - 1); i > 1; i--)
+ {
+ f2[i] = vo_L_sub(f2[i], f2[i - 2]); /* f2[i] -= f2[i-2]; */
+ }
+
+ /*----------------------------------------------------------*
+ * Scale F1(z) by (1+isp[m-1]) and F2(z) by (1-isp[m-1]) *
+ *----------------------------------------------------------*/
+
+ for (i = 0; i < nc; i++)
+ {
+ /* f1[i] *= (1.0 + isp[M-1]); */
+
+ hi = f1[i] >> 16;
+ lo = (f1[i] & 0xffff)>>1;
+
+ t0 = Mpy_32_16(hi, lo, isp[m - 1]);
+ f1[i] = vo_L_add(f1[i], t0);
+
+ /* f2[i] *= (1.0 - isp[M-1]); */
+
+ hi = f2[i] >> 16;
+ lo = (f2[i] & 0xffff)>>1;
+ t0 = Mpy_32_16(hi, lo, isp[m - 1]);
+ f2[i] = vo_L_sub(f2[i], t0);
+ }
+
+ /*-----------------------------------------------------*
+ * A(z) = (F1(z)+F2(z))/2 *
+ * F1(z) is symmetric and F2(z) is antisymmetric *
+ *-----------------------------------------------------*/
+
+ /* a[0] = 1.0; */
+ a[0] = 4096;
+ tmax = 1;
+ for (i = 1, j = m - 1; i < nc; i++, j--)
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]); */
+
+ t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */
+ tmax |= L_abs(t0);
+ a[i] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */
+
+ /* a[j] = 0.5*(f1[i] - f2[i]); */
+
+ t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */
+ tmax |= L_abs(t0);
+ a[j] = (Word16)(vo_L_shr_r(t0, 12)); /* from Q23 to Q12 and * 0.5 */
+ }
+
+ /* rescale data if overflow has occured and reprocess the loop */
+ if(adaptive_scaling == 1)
+ q = 4 - norm_l(tmax); /* adaptive scaling enabled */
+ else
+ q = 0; /* adaptive scaling disabled */
+
+ if (q > 0)
+ {
+ q_sug = (12 + q);
+ for (i = 1, j = m - 1; i < nc; i++, j--)
+ {
+ /* a[i] = 0.5*(f1[i] + f2[i]); */
+ t0 = vo_L_add(f1[i], f2[i]); /* f1[i] + f2[i] */
+ a[i] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */
+
+ /* a[j] = 0.5*(f1[i] - f2[i]); */
+ t0 = vo_L_sub(f1[i], f2[i]); /* f1[i] - f2[i] */
+ a[j] = (Word16)(vo_L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */
+ }
+ a[0] = shr(a[0], q);
+ }
+ else
+ {
+ q_sug = 12;
+ q = 0;
+ }
+ /* a[NC] = 0.5*f1[NC]*(1.0 + isp[M-1]); */
+ hi = f1[nc] >> 16;
+ lo = (f1[nc] & 0xffff)>>1;
+ t0 = Mpy_32_16(hi, lo, isp[m - 1]);
+ t0 = vo_L_add(f1[nc], t0);
+ a[nc] = (Word16)(L_shr_r(t0, q_sug)); /* from Q23 to Q12 and * 0.5 */
+ /* a[m] = isp[m-1]; */
+
+ a[m] = vo_shr_r(isp[m - 1], (3 + q)); /* from Q15 to Q12 */
+ return;
+}
+
+/*-----------------------------------------------------------*
+* procedure Get_isp_pol: *
+* ~~~~~~~~~~~ *
+* Find the polynomial F1(z) or F2(z) from the ISPs. *
+* This is performed by expanding the product polynomials: *
+* *
+* F1(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) *
+* i=0,2,4,6,8 *
+* F2(z) = product ( 1 - 2 isp_i z^-1 + z^-2 ) *
+* i=1,3,5,7 *
+* *
+* where isp_i are the ISPs in the cosine domain. *
+*-----------------------------------------------------------*
+* *
+* Parameters: *
+* isp[] : isp vector (cosine domaine) in Q15 *
+* f[] : the coefficients of F1 or F2 in Q23 *
+* n : == NC for F1(z); == NC-1 for F2(z) *
+*-----------------------------------------------------------*/
+
+static void Get_isp_pol(Word16 * isp, Word32 * f, Word16 n)
+{
+ Word16 hi, lo;
+ Word32 i, j, t0;
+ /* All computation in Q23 */
+
+ f[0] = vo_L_mult(4096, 1024); /* f[0] = 1.0; in Q23 */
+ f[1] = vo_L_mult(isp[0], -256); /* f[1] = -2.0*isp[0] in Q23 */
+
+ f += 2; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ for (i = 2; i <= n; i++)
+ {
+ *f = f[-2];
+ for (j = 1; j < i; j++, f--)
+ {
+ hi = f[-1]>>16;
+ lo = (f[-1] & 0xffff)>>1;
+
+ t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */
+ t0 = t0 << 1;
+ *f = vo_L_sub(*f, t0); /* *f -= t0 */
+ *f = vo_L_add(*f, f[-2]); /* *f += f[-2] */
+ }
+ *f -= (*isp << 9); /* *f -= isp<<8 */
+ f += i; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ }
+ return;
+}
+
+static void Get_isp_pol_16kHz(Word16 * isp, Word32 * f, Word16 n)
+{
+ Word16 hi, lo;
+ Word32 i, j, t0;
+
+ /* All computation in Q23 */
+ f[0] = L_mult(4096, 256); /* f[0] = 1.0; in Q23 */
+ f[1] = L_mult(isp[0], -64); /* f[1] = -2.0*isp[0] in Q23 */
+
+ f += 2; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+
+ for (i = 2; i <= n; i++)
+ {
+ *f = f[-2];
+ for (j = 1; j < i; j++, f--)
+ {
+ VO_L_Extract(f[-1], &hi, &lo);
+ t0 = Mpy_32_16(hi, lo, *isp); /* t0 = f[-1] * isp */
+ t0 = L_shl2(t0, 1);
+ *f = L_sub(*f, t0); /* *f -= t0 */
+ *f = L_add(*f, f[-2]); /* *f += f[-2] */
+ }
+ *f = L_msu(*f, *isp, 64); /* *f -= isp<<8 */
+ f += i; /* Advance f pointer */
+ isp += 2; /* Advance isp pointer */
+ }
+ return;
+}
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/isp_isf.c b/media/libstagefright/codecs/amrwbenc/src/isp_isf.c
new file mode 100644
index 0000000..6c6e389
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/isp_isf.c
@@ -0,0 +1,91 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: isp_isf.c *
+* *
+* Description: *
+* Isp_isf Transformation isp to isf *
+* Isf_isp Transformation isf to isp *
+* *
+* The transformation from isp[i] to isf[i] and isf[i] to isp[i] *
+* are approximated by a look-up table and interpolation *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "isp_isf.tab" /* Look-up table for transformations */
+
+void Isp_isf(
+ Word16 isp[], /* (i) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 isf[], /* (o) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 m /* (i) : LPC order */
+ )
+{
+ Word32 i, ind;
+ Word32 L_tmp;
+ ind = 127; /* beging at end of table -1 */
+ for (i = (m - 1); i >= 0; i--)
+ {
+ if (i >= (m - 2))
+ { /* m-2 is a constant */
+ ind = 127; /* beging at end of table -1 */
+ }
+ /* find value in table that is just greater than isp[i] */
+ while (table[ind] < isp[i])
+ ind--;
+ /* acos(isp[i])= ind*128 + ( ( isp[i]-table[ind] ) * slope[ind] )/2048 */
+ L_tmp = vo_L_mult(vo_sub(isp[i], table[ind]), slope[ind]);
+ isf[i] = vo_round((L_tmp << 4)); /* (isp[i]-table[ind])*slope[ind])>>11 */
+ isf[i] = add1(isf[i], (ind << 7));
+ }
+ isf[m - 1] = (isf[m - 1] >> 1);
+ return;
+}
+
+
+void Isf_isp(
+ Word16 isf[], /* (i) Q15 : isf[m] normalized (range: 0.0<=val<=0.5) */
+ Word16 isp[], /* (o) Q15 : isp[m] (range: -1<=val<1) */
+ Word16 m /* (i) : LPC order */
+ )
+{
+ Word16 offset;
+ Word32 i, ind, L_tmp;
+
+ for (i = 0; i < m - 1; i++)
+ {
+ isp[i] = isf[i];
+ }
+ isp[m - 1] = (isf[m - 1] << 1);
+
+ for (i = 0; i < m; i++)
+ {
+ ind = (isp[i] >> 7); /* ind = b7-b15 of isf[i] */
+ offset = (Word16) (isp[i] & 0x007f); /* offset = b0-b6 of isf[i] */
+
+ /* isp[i] = table[ind]+ ((table[ind+1]-table[ind])*offset) / 128 */
+ L_tmp = vo_L_mult(vo_sub(table[ind + 1], table[ind]), offset);
+ isp[i] = add1(table[ind], (Word16)((L_tmp >> 8)));
+ }
+
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/lag_wind.c b/media/libstagefright/codecs/amrwbenc/src/lag_wind.c
new file mode 100644
index 0000000..0397704
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/lag_wind.c
@@ -0,0 +1,49 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: lag_wind.c *
+* *
+* Description: Lag_windows on autocorrelations *
+* r[i] *= lag_wind[i] *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "lag_wind.tab"
+
+
+void Lag_window(
+ Word16 r_h[], /* (i/o) : Autocorrelations (msb) */
+ Word16 r_l[] /* (i/o) : Autocorrelations (lsb) */
+ )
+{
+ Word32 i;
+ Word32 x;
+
+ for (i = 1; i <= M; i++)
+ {
+ x = Mpy_32(r_h[i], r_l[i], volag_h[i - 1], volag_l[i - 1]);
+ r_h[i] = x >> 16;
+ r_l[i] = (x & 0xffff)>>1;
+ }
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/levinson.c b/media/libstagefright/codecs/amrwbenc/src/levinson.c
new file mode 100644
index 0000000..8bc6f62
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/levinson.c
@@ -0,0 +1,250 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: levinson.c *
+* *
+* Description:LEVINSON-DURBIN algorithm in double precision *
+* *
+************************************************************************/
+/*---------------------------------------------------------------------------*
+ * LEVINSON.C *
+ *---------------------------------------------------------------------------*
+ * *
+ * LEVINSON-DURBIN algorithm in double precision *
+ * *
+ * *
+ * Algorithm *
+ * *
+ * R[i] autocorrelations. *
+ * A[i] filter coefficients. *
+ * K reflection coefficients. *
+ * Alpha prediction gain. *
+ * *
+ * Initialization: *
+ * A[0] = 1 *
+ * K = -R[1]/R[0] *
+ * A[1] = K *
+ * Alpha = R[0] * (1-K**2] *
+ * *
+ * Do for i = 2 to M *
+ * *
+ * S = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] *
+ * *
+ * K = -S / Alpha *
+ * *
+ * An[j] = A[j] + K*A[i-j] for j=1 to i-1 *
+ * where An[i] = new A[i] *
+ * An[i]=K *
+ * *
+ * Alpha=Alpha * (1-K**2) *
+ * *
+ * END *
+ * *
+ * Remarks on the dynamics of the calculations. *
+ * *
+ * The numbers used are in double precision in the following format : *
+ * A = AH <<16 + AL<<1. AH and AL are 16 bit signed integers. *
+ * Since the LSB's also contain a sign bit, this format does not *
+ * correspond to standard 32 bit integers. We use this format since *
+ * it allows fast execution of multiplications and divisions. *
+ * *
+ * "DPF" will refer to this special format in the following text. *
+ * See oper_32b.c *
+ * *
+ * The R[i] were normalized in routine AUTO (hence, R[i] < 1.0). *
+ * The K[i] and Alpha are theoretically < 1.0. *
+ * The A[i], for a sampling frequency of 8 kHz, are in practice *
+ * always inferior to 16.0. *
+ * *
+ * These characteristics allow straigthforward fixed-point *
+ * implementation. We choose to represent the parameters as *
+ * follows : *
+ * *
+ * R[i] Q31 +- .99.. *
+ * K[i] Q31 +- .99.. *
+ * Alpha Normalized -> mantissa in Q31 plus exponent *
+ * A[i] Q27 +- 15.999.. *
+ * *
+ * The additions are performed in 32 bit. For the summation used *
+ * to calculate the K[i], we multiply numbers in Q31 by numbers *
+ * in Q27, with the result of the multiplications in Q27, *
+ * resulting in a dynamic of +- 16. This is sufficient to avoid *
+ * overflow, since the final result of the summation is *
+ * necessarily < 1.0 as both the K[i] and Alpha are *
+ * theoretically < 1.0. *
+ *___________________________________________________________________________*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "acelp.h"
+
+#define M 16
+#define NC (M/2)
+
+void Init_Levinson(
+ Word16 * mem /* output :static memory (18 words) */
+ )
+{
+ Set_zero(mem, 18); /* old_A[0..M-1] = 0, old_rc[0..1] = 0 */
+ return;
+}
+
+
+void Levinson(
+ Word16 Rh[], /* (i) : Rh[M+1] Vector of autocorrelations (msb) */
+ Word16 Rl[], /* (i) : Rl[M+1] Vector of autocorrelations (lsb) */
+ Word16 A[], /* (o) Q12 : A[M] LPC coefficients (m = 16) */
+ Word16 rc[], /* (o) Q15 : rc[M] Reflection coefficients. */
+ Word16 * mem /* (i/o) :static memory (18 words) */
+ )
+{
+ Word32 i, j;
+ Word16 hi, lo;
+ Word16 Kh, Kl; /* reflection coefficient; hi and lo */
+ Word16 alp_h, alp_l, alp_exp; /* Prediction gain; hi lo and exponent */
+ Word16 Ah[M + 1], Al[M + 1]; /* LPC coef. in double prec. */
+ Word16 Anh[M + 1], Anl[M + 1]; /* LPC coef.for next iteration in double prec. */
+ Word32 t0, t1, t2; /* temporary variable */
+ Word16 *old_A, *old_rc;
+
+ /* Last A(z) for case of unstable filter */
+ old_A = mem;
+ old_rc = mem + M;
+
+ /* K = A[1] = -R[1] / R[0] */
+
+ t1 = ((Rh[1] << 16) + (Rl[1] << 1)); /* R[1] in Q31 */
+ t2 = L_abs(t1); /* abs R[1] */
+ t0 = Div_32(t2, Rh[0], Rl[0]); /* R[1]/R[0] in Q31 */
+ if (t1 > 0)
+ t0 = -t0; /* -R[1]/R[0] */
+
+ Kh = t0 >> 16;
+ Kl = (t0 & 0xffff)>>1;
+ rc[0] = Kh;
+ t0 = (t0 >> 4); /* A[1] in Q27 */
+
+ Ah[1] = t0 >> 16;
+ Al[1] = (t0 & 0xffff)>>1;
+
+ /* Alpha = R[0] * (1-K**2) */
+ t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */
+ t0 = L_abs(t0); /* Some case <0 !! */
+ t0 = vo_L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */
+
+ hi = t0 >> 16;
+ lo = (t0 & 0xffff)>>1;
+
+ t0 = Mpy_32(Rh[0], Rl[0], hi, lo); /* Alpha in Q31 */
+
+ /* Normalize Alpha */
+ alp_exp = norm_l(t0);
+ t0 = (t0 << alp_exp);
+
+ alp_h = t0 >> 16;
+ alp_l = (t0 & 0xffff)>>1;
+ /*--------------------------------------*
+ * ITERATIONS I=2 to M *
+ *--------------------------------------*/
+ for (i = 2; i <= M; i++)
+ {
+ /* t0 = SUM ( R[j]*A[i-j] ,j=1,i-1 ) + R[i] */
+ t0 = 0;
+ for (j = 1; j < i; j++)
+ t0 = vo_L_add(t0, Mpy_32(Rh[j], Rl[j], Ah[i - j], Al[i - j]));
+
+ t0 = t0 << 4; /* result in Q27 -> convert to Q31 */
+ /* No overflow possible */
+ t1 = ((Rh[i] << 16) + (Rl[i] << 1));
+ t0 = vo_L_add(t0, t1); /* add R[i] in Q31 */
+
+ /* K = -t0 / Alpha */
+ t1 = L_abs(t0);
+ t2 = Div_32(t1, alp_h, alp_l); /* abs(t0)/Alpha */
+ if (t0 > 0)
+ t2 = -t2; /* K =-t0/Alpha */
+ t2 = (t2 << alp_exp); /* denormalize; compare to Alpha */
+
+ Kh = t2 >> 16;
+ Kl = (t2 & 0xffff)>>1;
+
+ rc[i - 1] = Kh;
+ /* Test for unstable filter. If unstable keep old A(z) */
+ if (abs_s(Kh) > 32750)
+ {
+ A[0] = 4096; /* Ai[0] not stored (always 1.0) */
+ for (j = 0; j < M; j++)
+ {
+ A[j + 1] = old_A[j];
+ }
+ rc[0] = old_rc[0]; /* only two rc coefficients are needed */
+ rc[1] = old_rc[1];
+ return;
+ }
+ /*------------------------------------------*
+ * Compute new LPC coeff. -> An[i] *
+ * An[j]= A[j] + K*A[i-j] , j=1 to i-1 *
+ * An[i]= K *
+ *------------------------------------------*/
+ for (j = 1; j < i; j++)
+ {
+ t0 = Mpy_32(Kh, Kl, Ah[i - j], Al[i - j]);
+ t0 = vo_L_add(t0, ((Ah[j] << 16) + (Al[j] << 1)));
+ Anh[j] = t0 >> 16;
+ Anl[j] = (t0 & 0xffff)>>1;
+ }
+ t2 = (t2 >> 4); /* t2 = K in Q31 ->convert to Q27 */
+
+ VO_L_Extract(t2, &Anh[i], &Anl[i]); /* An[i] in Q27 */
+
+ /* Alpha = Alpha * (1-K**2) */
+ t0 = Mpy_32(Kh, Kl, Kh, Kl); /* K*K in Q31 */
+ t0 = L_abs(t0); /* Some case <0 !! */
+ t0 = vo_L_sub((Word32) 0x7fffffffL, t0); /* 1 - K*K in Q31 */
+ hi = t0 >> 16;
+ lo = (t0 & 0xffff)>>1;
+ t0 = Mpy_32(alp_h, alp_l, hi, lo); /* Alpha in Q31 */
+
+ /* Normalize Alpha */
+ j = norm_l(t0);
+ t0 = (t0 << j);
+ alp_h = t0 >> 16;
+ alp_l = (t0 & 0xffff)>>1;
+ alp_exp += j; /* Add normalization to alp_exp */
+
+ /* A[j] = An[j] */
+ for (j = 1; j <= i; j++)
+ {
+ Ah[j] = Anh[j];
+ Al[j] = Anl[j];
+ }
+ }
+ /* Truncate A[i] in Q27 to Q12 with rounding */
+ A[0] = 4096;
+ for (i = 1; i <= M; i++)
+ {
+ t0 = (Ah[i] << 16) + (Al[i] << 1);
+ old_A[i - 1] = A[i] = vo_round((t0 << 1));
+ }
+ old_rc[0] = rc[0];
+ old_rc[1] = rc[1];
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/log2.c b/media/libstagefright/codecs/amrwbenc/src/log2.c
new file mode 100644
index 0000000..cd3d815
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/log2.c
@@ -0,0 +1,111 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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 : log2.c *
+* Purpose : Computes log2(L_x) *
+* *
+************************************************************************/
+
+#include "log2.h"
+/********************************************************************************
+* INCLUDE FILES
+*********************************************************************************/
+#include "typedef.h"
+#include "basic_op.h"
+
+/*********************************************************************************
+* LOCAL VARIABLES AND TABLES
+**********************************************************************************/
+#include "log2_tab.h" /* Table for Log2() */
+
+/*************************************************************************
+*
+* FUNCTION: Log2_norm()
+*
+* PURPOSE: Computes log2(L_x, exp), where L_x is positive and
+* normalized, and exp is the normalisation exponent
+* If L_x is negative or zero, the result is 0.
+*
+* DESCRIPTION:
+* The function Log2(L_x) is approximated by a table and linear
+* interpolation. The following steps are used to compute Log2(L_x)
+*
+* 1- exponent = 30-norm_exponent
+* 2- i = bit25-b31 of L_x; 32<=i<=63 (because of normalization).
+* 3- a = bit10-b24
+* 4- i -=32
+* 5- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2
+*
+*************************************************************************/
+
+void Log2_norm (
+ Word32 L_x, /* (i) : input value (normalized) */
+ Word16 exp, /* (i) : norm_l (L_x) */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ )
+{
+ Word16 i, a, tmp;
+ Word32 L_y;
+ if (L_x <= (Word32) 0)
+ {
+ *exponent = 0;
+ *fraction = 0;
+ return;
+ }
+ *exponent = (30 - exp);
+ L_x = (L_x >> 9);
+ i = extract_h (L_x); /* Extract b25-b31 */
+ L_x = (L_x >> 1);
+ a = (Word16)(L_x); /* Extract b10-b24 of fraction */
+ a = (Word16)(a & (Word16)0x7fff);
+ i -= 32;
+ L_y = L_deposit_h (table[i]); /* table[i] << 16 */
+ tmp = vo_sub(table[i], table[i + 1]); /* table[i] - table[i+1] */
+ L_y = vo_L_msu (L_y, tmp, a); /* L_y -= tmp*a*2 */
+ *fraction = extract_h (L_y);
+
+ return;
+}
+
+/*************************************************************************
+*
+* FUNCTION: Log2()
+*
+* PURPOSE: Computes log2(L_x), where L_x is positive.
+* If L_x is negative or zero, the result is 0.
+*
+* DESCRIPTION:
+* normalizes L_x and then calls Log2_norm().
+*
+*************************************************************************/
+
+void Log2 (
+ Word32 L_x, /* (i) : input value */
+ Word16 *exponent, /* (o) : Integer part of Log2. (range: 0<=val<=30) */
+ Word16 *fraction /* (o) : Fractional part of Log2. (range: 0<=val<1) */
+ )
+{
+ Word16 exp;
+
+ exp = norm_l(L_x);
+ Log2_norm ((L_x << exp), exp, exponent, fraction);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c b/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c
new file mode 100644
index 0000000..63b746b
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/lp_dec2.c
@@ -0,0 +1,70 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: lp_dec2.c *
+* *
+* Description:Decimate a vector by 2 with 2nd order fir filter *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+
+#define L_FIR 5
+#define L_MEM (L_FIR-2)
+
+/* static float h_fir[L_FIR] = {0.13, 0.23, 0.28, 0.23, 0.13}; */
+/* fixed-point: sum of coef = 32767 to avoid overflow on DC */
+static Word16 h_fir[L_FIR] = {4260, 7536, 9175, 7536, 4260};
+
+void LP_Decim2(
+ Word16 x[], /* in/out: signal to process */
+ Word16 l, /* input : size of filtering */
+ Word16 mem[] /* in/out: memory (size=3) */
+ )
+{
+ Word16 *p_x, x_buf[L_FRAME + L_MEM];
+ Word32 i, j;
+ Word32 L_tmp;
+ /* copy initial filter states into buffer */
+ p_x = x_buf;
+ for (i = 0; i < L_MEM; i++)
+ {
+ *p_x++ = mem[i];
+ mem[i] = x[l - L_MEM + i];
+ }
+ for (i = 0; i < l; i++)
+ {
+ *p_x++ = x[i];
+ }
+ for (i = 0, j = 0; i < l; i += 2, j++)
+ {
+ p_x = &x_buf[i];
+ L_tmp = ((*p_x++) * h_fir[0]);
+ L_tmp += ((*p_x++) * h_fir[1]);
+ L_tmp += ((*p_x++) * h_fir[2]);
+ L_tmp += ((*p_x++) * h_fir[3]);
+ L_tmp += ((*p_x++) * h_fir[4]);
+ x[j] = (L_tmp + 0x4000)>>15;
+ }
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/math_op.c b/media/libstagefright/codecs/amrwbenc/src/math_op.c
new file mode 100644
index 0000000..1c95ed0
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/math_op.c
@@ -0,0 +1,219 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+/*___________________________________________________________________________
+| |
+| This file contains mathematic operations in fixed point. |
+| |
+| Isqrt() : inverse square root (16 bits precision). |
+| Pow2() : 2^x (16 bits precision). |
+| Log2() : log2 (16 bits precision). |
+| Dot_product() : scalar product of <x[],y[]> |
+| |
+| These operations are not standard double precision operations. |
+| They are used where low complexity is important and the full 32 bits |
+| precision is not necessary. For example, the function Div_32() has a |
+| 24 bits precision which is enough for our purposes. |
+| |
+| In this file, the values use theses representations: |
+| |
+| Word32 L_32 : standard signed 32 bits format |
+| Word16 hi, lo : L_32 = hi<<16 + lo<<1 (DPF - Double Precision Format) |
+| Word32 frac, Word16 exp : L_32 = frac << exp-31 (normalised format) |
+| Word16 int, frac : L_32 = int.frac (fractional format) |
+|___________________________________________________________________________|
+*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+
+/*___________________________________________________________________________
+| |
+| Function Name : Isqrt |
+| |
+| Compute 1/sqrt(L_x). |
+| if L_x is negative or zero, result is 1 (7fffffff). |
+|---------------------------------------------------------------------------|
+| Algorithm: |
+| |
+| 1- Normalization of L_x. |
+| 2- call Isqrt_n(L_x, exponant) |
+| 3- L_y = L_x << exponant |
+|___________________________________________________________________________|
+*/
+Word32 Isqrt( /* (o) Q31 : output value (range: 0<=val<1) */
+ Word32 L_x /* (i) Q0 : input value (range: 0<=val<=7fffffff) */
+ )
+{
+ Word16 exp;
+ Word32 L_y;
+ exp = norm_l(L_x);
+ L_x = (L_x << exp); /* L_x is normalized */
+ exp = (31 - exp);
+ Isqrt_n(&L_x, &exp);
+ L_y = (L_x << exp); /* denormalization */
+ return (L_y);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : Isqrt_n |
+| |
+| Compute 1/sqrt(value). |
+| if value is negative or zero, result is 1 (frac=7fffffff, exp=0). |
+|---------------------------------------------------------------------------|
+| Algorithm: |
+| |
+| The function 1/sqrt(value) is approximated by a table and linear |
+| interpolation. |
+| |
+| 1- If exponant is odd then shift fraction right once. |
+| 2- exponant = -((exponant-1)>>1) |
+| 3- i = bit25-b30 of fraction, 16 <= i <= 63 ->because of normalization. |
+| 4- a = bit10-b24 |
+| 5- i -=16 |
+| 6- fraction = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
+|___________________________________________________________________________|
+*/
+static Word16 table_isqrt[49] =
+{
+ 32767, 31790, 30894, 30070, 29309, 28602, 27945, 27330, 26755, 26214,
+ 25705, 25225, 24770, 24339, 23930, 23541, 23170, 22817, 22479, 22155,
+ 21845, 21548, 21263, 20988, 20724, 20470, 20225, 19988, 19760, 19539,
+ 19326, 19119, 18919, 18725, 18536, 18354, 18176, 18004, 17837, 17674,
+ 17515, 17361, 17211, 17064, 16921, 16782, 16646, 16514, 16384
+};
+
+void Isqrt_n(
+ Word32 * frac, /* (i/o) Q31: normalized value (1.0 < frac <= 0.5) */
+ Word16 * exp /* (i/o) : exponent (value = frac x 2^exponent) */
+ )
+{
+ Word16 i, a, tmp;
+
+ if (*frac <= (Word32) 0)
+ {
+ *exp = 0;
+ *frac = 0x7fffffffL;
+ return;
+ }
+
+ if((*exp & 1) == 1) /*If exponant odd -> shift right */
+ *frac = (*frac) >> 1;
+
+ *exp = negate((*exp - 1) >> 1);
+
+ *frac = (*frac >> 9);
+ i = extract_h(*frac); /* Extract b25-b31 */
+ *frac = (*frac >> 1);
+ a = (Word16)(*frac); /* Extract b10-b24 */
+ a = (Word16) (a & (Word16) 0x7fff);
+ i -= 16;
+ *frac = L_deposit_h(table_isqrt[i]); /* table[i] << 16 */
+ tmp = vo_sub(table_isqrt[i], table_isqrt[i + 1]); /* table[i] - table[i+1]) */
+ *frac = vo_L_msu(*frac, tmp, a); /* frac -= tmp*a*2 */
+
+ return;
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : Pow2() |
+| |
+| L_x = pow(2.0, exponant.fraction) (exponant = interger part) |
+| = pow(2.0, 0.fraction) << exponant |
+|---------------------------------------------------------------------------|
+| Algorithm: |
+| |
+| The function Pow2(L_x) is approximated by a table and linear |
+| interpolation. |
+| |
+| 1- i = bit10-b15 of fraction, 0 <= i <= 31 |
+| 2- a = bit0-b9 of fraction |
+| 3- L_x = table[i]<<16 - (table[i] - table[i+1]) * a * 2 |
+| 4- L_x = L_x >> (30-exponant) (with rounding) |
+|___________________________________________________________________________|
+*/
+static Word16 table_pow2[33] =
+{
+ 16384, 16743, 17109, 17484, 17867, 18258, 18658, 19066, 19484, 19911,
+ 20347, 20792, 21247, 21713, 22188, 22674, 23170, 23678, 24196, 24726,
+ 25268, 25821, 26386, 26964, 27554, 28158, 28774, 29405, 30048, 30706,
+ 31379, 32066, 32767
+};
+
+Word32 Pow2( /* (o) Q0 : result (range: 0<=val<=0x7fffffff) */
+ Word16 exponant, /* (i) Q0 : Integer part. (range: 0<=val<=30) */
+ Word16 fraction /* (i) Q15 : Fractionnal part. (range: 0.0<=val<1.0) */
+ )
+{
+ Word16 exp, i, a, tmp;
+ Word32 L_x;
+
+ L_x = vo_L_mult(fraction, 32); /* L_x = fraction<<6 */
+ i = extract_h(L_x); /* Extract b10-b16 of fraction */
+ L_x =L_x >> 1;
+ a = (Word16)(L_x); /* Extract b0-b9 of fraction */
+ a = (Word16) (a & (Word16) 0x7fff);
+
+ L_x = L_deposit_h(table_pow2[i]); /* table[i] << 16 */
+ tmp = vo_sub(table_pow2[i], table_pow2[i + 1]); /* table[i] - table[i+1] */
+ L_x -= (tmp * a)<<1; /* L_x -= tmp*a*2 */
+
+ exp = vo_sub(30, exponant);
+ L_x = vo_L_shr_r(L_x, exp);
+
+ return (L_x);
+}
+
+/*___________________________________________________________________________
+| |
+| Function Name : Dot_product12() |
+| |
+| Compute scalar product of <x[],y[]> using accumulator. |
+| |
+| The result is normalized (in Q31) with exponent (0..30). |
+|---------------------------------------------------------------------------|
+| Algorithm: |
+| |
+| dot_product = sum(x[i]*y[i]) i=0..N-1 |
+|___________________________________________________________________________|
+*/
+
+Word32 Dot_product12( /* (o) Q31: normalized result (1 < val <= -1) */
+ Word16 x[], /* (i) 12bits: x vector */
+ Word16 y[], /* (i) 12bits: y vector */
+ Word16 lg, /* (i) : vector length */
+ Word16 * exp /* (o) : exponent of result (0..+30) */
+ )
+{
+ Word16 sft;
+ Word32 i, L_sum;
+ L_sum = 0;
+ for (i = 0; i < lg; i++)
+ {
+ L_sum += x[i] * y[i];
+ }
+ L_sum = (L_sum << 1) + 1;
+ /* Normalize acc in Q31 */
+ sft = norm_l(L_sum);
+ L_sum = L_sum << sft;
+ *exp = 30 - sft; /* exponent = 0..30 */
+ return (L_sum);
+
+}
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/mem_align.c b/media/libstagefright/codecs/amrwbenc/src/mem_align.c
new file mode 100644
index 0000000..e58915a
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/mem_align.c
@@ -0,0 +1,107 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: mem_align.c
+
+ Content: Memory alloc alignments functions
+
+*******************************************************************************/
+
+
+#include "mem_align.h"
+
+/*****************************************************************************
+*
+* function name: mem_malloc
+* description: malloc the alignments memory
+* returns: the point of the memory
+*
+**********************************************************************************/
+void *
+mem_malloc(VO_MEM_OPERATOR *pMemop, unsigned int size, unsigned char alignment, unsigned int CodecID)
+{
+ int ret;
+ unsigned char *mem_ptr;
+ VO_MEM_INFO MemInfo;
+
+ if (!alignment) {
+
+ MemInfo.Flag = 0;
+ MemInfo.Size = size + 1;
+ ret = pMemop->Alloc(CodecID, &MemInfo);
+ if(ret != 0)
+ return 0;
+ mem_ptr = (unsigned char *)MemInfo.VBuffer;
+
+ pMemop->Set(CodecID, mem_ptr, 0, size + 1);
+
+ *mem_ptr = (unsigned char)1;
+
+ return ((void *)(mem_ptr+1));
+ } else {
+ unsigned char *tmp;
+
+ MemInfo.Flag = 0;
+ MemInfo.Size = size + alignment;
+ ret = pMemop->Alloc(CodecID, &MemInfo);
+ if(ret != 0)
+ return 0;
+
+ tmp = (unsigned char *)MemInfo.VBuffer;
+
+ pMemop->Set(CodecID, tmp, 0, size + alignment);
+
+ mem_ptr =
+ (unsigned char *) ((unsigned int) (tmp + alignment - 1) &
+ (~((unsigned int) (alignment - 1))));
+
+ if (mem_ptr == tmp)
+ mem_ptr += alignment;
+
+ *(mem_ptr - 1) = (unsigned char) (mem_ptr - tmp);
+
+ return ((void *)mem_ptr);
+ }
+
+ return(0);
+}
+
+
+/*****************************************************************************
+*
+* function name: mem_free
+* description: free the memory
+*
+*******************************************************************************/
+void
+mem_free(VO_MEM_OPERATOR *pMemop, void *mem_ptr, unsigned int CodecID)
+{
+
+ unsigned char *ptr;
+
+ if (mem_ptr == 0)
+ return;
+
+ ptr = mem_ptr;
+
+ ptr -= *(ptr - 1);
+
+ pMemop->Free(CodecID, ptr);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/oper_32b.c b/media/libstagefright/codecs/amrwbenc/src/oper_32b.c
new file mode 100644
index 0000000..5f1523e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/oper_32b.c
@@ -0,0 +1,223 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+/*****************************************************************************
+ * This file contains operations in double precision. *
+ * These operations are not standard double precision operations. *
+ * They are used where single precision is not enough but the full 32 bits *
+ * precision is not necessary. For example, the function Div_32() has a *
+ * 24 bits precision which is enough for our purposes. *
+ * *
+ * The double precision numbers use a special representation: *
+ * *
+ * L_32 = hi<<16 + lo<<1 *
+ * *
+ * L_32 is a 32 bit integer. *
+ * hi and lo are 16 bit signed integers. *
+ * As the low part also contains the sign, this allows fast multiplication. *
+ * *
+ * 0x8000 0000 <= L_32 <= 0x7fff fffe. *
+ * *
+ * We will use DPF (Double Precision Format )in this file to specify *
+ * this special format. *
+ *****************************************************************************
+*/
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+
+/*****************************************************************************
+ * *
+ * Function L_Extract() *
+ * *
+ * Extract from a 32 bit integer two 16 bit DPF. *
+ * *
+ * Arguments: *
+ * *
+ * L_32 : 32 bit integer. *
+ * 0x8000 0000 <= L_32 <= 0x7fff ffff. *
+ * hi : b16 to b31 of L_32 *
+ * lo : (L_32 - hi<<16)>>1 *
+ *****************************************************************************
+*/
+
+__inline void VO_L_Extract (Word32 L_32, Word16 *hi, Word16 *lo)
+{
+ *hi = (Word16)(L_32 >> 16);
+ *lo = (Word16)((L_32 & 0xffff) >> 1);
+ return;
+}
+
+/*****************************************************************************
+ * *
+ * Function L_Comp() *
+ * *
+ * Compose from two 16 bit DPF a 32 bit integer. *
+ * *
+ * L_32 = hi<<16 + lo<<1 *
+ * *
+ * Arguments: *
+ * *
+ * hi msb *
+ * lo lsf (with sign) *
+ * *
+ * Return Value : *
+ * *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x8000 0000 <= L_32 <= 0x7fff fff0. *
+ * *
+ *****************************************************************************
+*/
+
+Word32 L_Comp (Word16 hi, Word16 lo)
+{
+ Word32 L_32;
+
+ L_32 = L_deposit_h (hi);
+
+ return (L_mac (L_32, lo, 1)); /* = hi<<16 + lo<<1 */
+}
+
+/*****************************************************************************
+ * Function Mpy_32() *
+ * *
+ * Multiply two 32 bit integers (DPF). The result is divided by 2**31 *
+ * *
+ * L_32 = (hi1*hi2)<<1 + ( (hi1*lo2)>>15 + (lo1*hi2)>>15 )<<1 *
+ * *
+ * This operation can also be viewed as the multiplication of two Q31 *
+ * number and the result is also in Q31. *
+ * *
+ * Arguments: *
+ * *
+ * hi1 hi part of first number *
+ * lo1 lo part of first number *
+ * hi2 hi part of second number *
+ * lo2 lo part of second number *
+ * *
+ *****************************************************************************
+*/
+
+__inline Word32 Mpy_32 (Word16 hi1, Word16 lo1, Word16 hi2, Word16 lo2)
+{
+ Word32 L_32;
+ L_32 = (hi1 * hi2);
+ L_32 += (hi1 * lo2) >> 15;
+ L_32 += (lo1 * hi2) >> 15;
+ L_32 <<= 1;
+
+ return (L_32);
+}
+
+/*****************************************************************************
+ * Function Mpy_32_16() *
+ * *
+ * Multiply a 16 bit integer by a 32 bit (DPF). The result is divided *
+ * by 2**15 *
+ * *
+ * *
+ * L_32 = (hi1*lo2)<<1 + ((lo1*lo2)>>15)<<1 *
+ * *
+ * Arguments: *
+ * *
+ * hi hi part of 32 bit number. *
+ * lo lo part of 32 bit number. *
+ * n 16 bit number. *
+ * *
+ *****************************************************************************
+*/
+
+__inline Word32 Mpy_32_16 (Word16 hi, Word16 lo, Word16 n)
+{
+ Word32 L_32;
+
+ L_32 = (hi * n)<<1;
+ L_32 += (((lo * n)>>15)<<1);
+
+ return (L_32);
+}
+
+/*****************************************************************************
+ * *
+ * Function Name : Div_32 *
+ * *
+ * Purpose : *
+ * Fractional integer division of two 32 bit numbers. *
+ * L_num / L_denom. *
+ * L_num and L_denom must be positive and L_num < L_denom. *
+ * L_denom = denom_hi<<16 + denom_lo<<1 *
+ * denom_hi is a normalize number. *
+ * *
+ * Inputs : *
+ * *
+ * L_num *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x0000 0000 < L_num < L_denom *
+ * *
+ * L_denom = denom_hi<<16 + denom_lo<<1 (DPF) *
+ * *
+ * denom_hi *
+ * 16 bit positive normalized integer whose value falls in the *
+ * range : 0x4000 < hi < 0x7fff *
+ * denom_lo *
+ * 16 bit positive integer whose value falls in the *
+ * range : 0 < lo < 0x7fff *
+ * *
+ * Return Value : *
+ * *
+ * L_div *
+ * 32 bit long signed integer (Word32) whose value falls in the *
+ * range : 0x0000 0000 <= L_div <= 0x7fff ffff. *
+ * *
+ * Algorithm: *
+ * *
+ * - find = 1/L_denom. *
+ * First approximation: approx = 1 / denom_hi *
+ * 1/L_denom = approx * (2.0 - L_denom * approx ) *
+ * *
+ * - result = L_num * (1/L_denom) *
+ *****************************************************************************
+*/
+
+Word32 Div_32 (Word32 L_num, Word16 denom_hi, Word16 denom_lo)
+{
+ Word16 approx, hi, lo, n_hi, n_lo;
+ Word32 L_32;
+
+ /* First approximation: 1 / L_denom = 1/denom_hi */
+
+ approx = div_s ((Word16) 0x3fff, denom_hi);
+
+ /* 1/L_denom = approx * (2.0 - L_denom * approx) */
+
+ L_32 = Mpy_32_16 (denom_hi, denom_lo, approx);
+
+ L_32 = L_sub ((Word32) 0x7fffffffL, L_32);
+ hi = L_32 >> 16;
+ lo = (L_32 & 0xffff) >> 1;
+
+ L_32 = Mpy_32_16 (hi, lo, approx);
+
+ /* L_num * (1/L_denom) */
+ hi = L_32 >> 16;
+ lo = (L_32 & 0xffff) >> 1;
+ VO_L_Extract (L_num, &n_hi, &n_lo);
+ L_32 = Mpy_32 (n_hi, n_lo, hi, lo);
+ L_32 = L_shl2(L_32, 2);
+
+ return (L_32);
+}
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c b/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c
new file mode 100644
index 0000000..39ee966
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/p_med_ol.c
@@ -0,0 +1,256 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: p_med_ol.c *
+* *
+* Description: Compute the open loop pitch lag *
+* output: open loop pitch lag *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "p_med_ol.tab"
+
+Word16 Pitch_med_ol(
+ Word16 wsp[], /* i: signal used to compute the open loop pitch*/
+ /* wsp[-pit_max] to wsp[-1] should be known */
+ Coder_State *st, /* i/o: codec global structure */
+ Word16 L_frame /* i: length of frame to compute pitch */
+ )
+{
+ Word16 Tm;
+ Word16 hi, lo;
+ Word16 *ww, *we, *hp_wsp;
+ Word16 exp_R0, exp_R1, exp_R2;
+ Word32 i, j, max, R0, R1, R2;
+ Word16 *p1, *p2;
+ Word16 L_min = 17; /* minimum pitch lag: PIT_MIN / OPL_DECIM */
+ Word16 L_max = 115; /* maximum pitch lag: PIT_MAX / OPL_DECIM */
+ Word16 L_0 = st->old_T0_med; /* old open-loop pitch */
+ Word16 *gain = &(st->ol_gain); /* normalize correlation of hp_wsp for the lag */
+ Word16 *hp_wsp_mem = st->hp_wsp_mem; /* memory of the hypass filter for hp_wsp[] (lg = 9)*/
+ Word16 *old_hp_wsp = st->old_hp_wsp; /* hypass wsp[] */
+ Word16 wght_flg = st->ol_wght_flg; /* is weighting function used */
+
+ ww = &corrweight[198];
+ we = &corrweight[98 + L_max - L_0];
+
+ max = MIN_32;
+ Tm = 0;
+ for (i = L_max; i > L_min; i--)
+ {
+ /* Compute the correlation */
+ R0 = 0;
+ p1 = wsp;
+ p2 = &wsp[-i];
+ for (j = 0; j < L_frame; j+=4)
+ {
+ R0 += vo_L_mult((*p1++), (*p2++));
+ R0 += vo_L_mult((*p1++), (*p2++));
+ R0 += vo_L_mult((*p1++), (*p2++));
+ R0 += vo_L_mult((*p1++), (*p2++));
+ }
+ /* Weighting of the correlation function. */
+ hi = R0>>16;
+ lo = (R0 & 0xffff)>>1;
+
+ R0 = Mpy_32_16(hi, lo, *ww);
+ ww--;
+
+ if ((L_0 > 0) && (wght_flg > 0))
+ {
+ /* Weight the neighbourhood of the old lag. */
+ hi = R0>>16;
+ lo = (R0 & 0xffff)>>1;
+ R0 = Mpy_32_16(hi, lo, *we);
+ we--;
+ }
+ if(R0 >= max)
+ {
+ max = R0;
+ Tm = i;
+ }
+ }
+
+ /* Hypass the wsp[] vector */
+ hp_wsp = old_hp_wsp + L_max;
+ Hp_wsp(wsp, hp_wsp, L_frame, hp_wsp_mem);
+
+ /* Compute normalize correlation at delay Tm */
+ R0 = 0;
+ R1 = 0;
+ R2 = 0;
+ p1 = hp_wsp;
+ p2 = hp_wsp - Tm;
+ for (j = 0; j < L_frame; j+=4)
+ {
+ R2 += vo_mult32(*p1, *p1);
+ R1 += vo_mult32(*p2, *p2);
+ R0 += vo_mult32(*p1++, *p2++);
+ R2 += vo_mult32(*p1, *p1);
+ R1 += vo_mult32(*p2, *p2);
+ R0 += vo_mult32(*p1++, *p2++);
+ R2 += vo_mult32(*p1, *p1);
+ R1 += vo_mult32(*p2, *p2);
+ R0 += vo_mult32(*p1++, *p2++);
+ R2 += vo_mult32(*p1, *p1);
+ R1 += vo_mult32(*p2, *p2);
+ R0 += vo_mult32(*p1++, *p2++);
+ }
+ R0 = R0 <<1;
+ R1 = (R1 <<1) + 1L;
+ R2 = (R2 <<1) + 1L;
+ /* gain = R0/ sqrt(R1*R2) */
+
+ exp_R0 = norm_l(R0);
+ R0 = (R0 << exp_R0);
+
+ exp_R1 = norm_l(R1);
+ R1 = (R1 << exp_R1);
+
+ exp_R2 = norm_l(R2);
+ R2 = (R2 << exp_R2);
+
+
+ R1 = vo_L_mult(vo_round(R1), vo_round(R2));
+
+ i = norm_l(R1);
+ R1 = (R1 << i);
+
+ exp_R1 += exp_R2;
+ exp_R1 += i;
+ exp_R1 = 62 - exp_R1;
+
+ Isqrt_n(&R1, &exp_R1);
+
+ R0 = vo_L_mult(voround(R0), voround(R1));
+ exp_R0 = 31 - exp_R0;
+ exp_R0 += exp_R1;
+
+ *gain = vo_round(L_shl(R0, exp_R0));
+
+ /* Shitf hp_wsp[] for next frame */
+
+ for (i = 0; i < L_max; i++)
+ {
+ old_hp_wsp[i] = old_hp_wsp[i + L_frame];
+ }
+
+ return (Tm);
+}
+
+/************************************************************************
+* Function: median5 *
+* *
+* Returns the median of the set {X[-2], X[-1],..., X[2]}, *
+* whose elements are 16-bit integers. *
+* *
+* Input: *
+* X[-2:2] 16-bit integers. *
+* *
+* Return: *
+* The median of {X[-2], X[-1],..., X[2]}. *
+************************************************************************/
+
+Word16 median5(Word16 x[])
+{
+ Word16 x1, x2, x3, x4, x5;
+ Word16 tmp;
+
+ x1 = x[-2];
+ x2 = x[-1];
+ x3 = x[0];
+ x4 = x[1];
+ x5 = x[2];
+
+ if (x2 < x1)
+ {
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+ if (x3 < x1)
+ {
+ tmp = x1;
+ x1 = x3;
+ x3 = tmp;
+ }
+ if (x4 < x1)
+ {
+ tmp = x1;
+ x1 = x4;
+ x4 = tmp;
+ }
+ if (x5 < x1)
+ {
+ x5 = x1;
+ }
+ if (x3 < x2)
+ {
+ tmp = x2;
+ x2 = x3;
+ x3 = tmp;
+ }
+ if (x4 < x2)
+ {
+ tmp = x2;
+ x2 = x4;
+ x4 = tmp;
+ }
+ if (x5 < x2)
+ {
+ x5 = x2;
+ }
+ if (x4 < x3)
+ {
+ x3 = x4;
+ }
+ if (x5 < x3)
+ {
+ x3 = x5;
+ }
+ return (x3);
+}
+
+
+Word16 Med_olag( /* output : median of 5 previous open-loop lags */
+ Word16 prev_ol_lag, /* input : previous open-loop lag */
+ Word16 old_ol_lag[5]
+ )
+{
+ Word32 i;
+
+ /* Use median of 5 previous open-loop lags as old lag */
+
+ for (i = 4; i > 0; i--)
+ {
+ old_ol_lag[i] = old_ol_lag[i - 1];
+ }
+
+ old_ol_lag[0] = prev_ol_lag;
+
+ i = median5(&old_ol_lag[2]);
+
+ return i;
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c b/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c
new file mode 100644
index 0000000..c8a227c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/pit_shrp.c
@@ -0,0 +1,49 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: pit_shrp.c *
+* *
+* Description: Performs Pitch sharpening routine *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Pit_shrp(
+ Word16 * x, /* in/out: impulse response (or algebraic code) */
+ Word16 pit_lag, /* input : pitch lag */
+ Word16 sharp, /* input : pitch sharpening factor (Q15) */
+ Word16 L_subfr /* input : subframe size */
+ )
+{
+ Word32 i;
+ Word32 L_tmp;
+ Word16 *x_ptr = x + pit_lag;
+
+ for (i = pit_lag; i < L_subfr; i++)
+ {
+ L_tmp = (*x_ptr << 15);
+ L_tmp += *x++ * sharp;
+ *x_ptr++ = ((L_tmp + 0x4000)>>15);
+ }
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c
new file mode 100644
index 0000000..c115b11
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/pitch_f4.c
@@ -0,0 +1,324 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: pitch_f4.c *
+* *
+* Description: Find the closed loop pitch period with *
+* 1/4 subsample resolution. *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "acelp.h"
+#include "cnst.h"
+
+#define UP_SAMP 4
+#define L_INTERPOL1 4
+
+/* Local functions */
+
+#ifdef ASM_OPT
+void Norm_corr_asm(
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 L_subfr,
+ Word16 t_min, /* (i) : minimum value of pitch lag. */
+ Word16 t_max, /* (i) : maximum value of pitch lag. */
+ Word16 corr_norm[] /* (o) Q15 : normalized correlation */
+ );
+#else
+static void Norm_Corr(
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 L_subfr,
+ Word16 t_min, /* (i) : minimum value of pitch lag. */
+ Word16 t_max, /* (i) : maximum value of pitch lag. */
+ Word16 corr_norm[] /* (o) Q15 : normalized correlation */
+ );
+#endif
+
+static Word16 Interpol_4( /* (o) : interpolated value */
+ Word16 * x, /* (i) : input vector */
+ Word32 frac /* (i) : fraction (-4..+3) */
+ );
+
+
+Word16 Pitch_fr4( /* (o) : pitch period. */
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 t0_min, /* (i) : minimum value in the searched range. */
+ Word16 t0_max, /* (i) : maximum value in the searched range. */
+ Word16 * pit_frac, /* (o) : chosen fraction (0, 1, 2 or 3). */
+ Word16 i_subfr, /* (i) : indicator for first subframe. */
+ Word16 t0_fr2, /* (i) : minimum value for resolution 1/2 */
+ Word16 t0_fr1, /* (i) : minimum value for resolution 1 */
+ Word16 L_subfr /* (i) : Length of subframe */
+ )
+{
+ Word32 fraction, i;
+ Word16 t_min, t_max;
+ Word16 max, t0, step, temp;
+ Word16 *corr;
+ Word16 corr_v[40]; /* Total length = t0_max-t0_min+1+2*L_inter */
+
+ /* Find interval to compute normalized correlation */
+
+ t_min = t0_min - L_INTERPOL1;
+ t_max = t0_max + L_INTERPOL1;
+ corr = &corr_v[-t_min];
+ /* Compute normalized correlation between target and filtered excitation */
+#ifdef ASM_OPT /* asm optimization branch */
+ Norm_corr_asm(exc, xn, h, L_subfr, t_min, t_max, corr);
+#else
+ Norm_Corr(exc, xn, h, L_subfr, t_min, t_max, corr);
+#endif
+
+ /* Find integer pitch */
+
+ max = corr[t0_min];
+ t0 = t0_min;
+ for (i = t0_min + 1; i <= t0_max; i++)
+ {
+ if (corr[i] >= max)
+ {
+ max = corr[i];
+ t0 = i;
+ }
+ }
+ /* If first subframe and t0 >= t0_fr1, do not search fractionnal pitch */
+ if ((i_subfr == 0) && (t0 >= t0_fr1))
+ {
+ *pit_frac = 0;
+ return (t0);
+ }
+ /*------------------------------------------------------------------*
+ * Search fractionnal pitch with 1/4 subsample resolution. *
+ * Test the fractions around t0 and choose the one which maximizes *
+ * the interpolated normalized correlation. *
+ *------------------------------------------------------------------*/
+
+ step = 1; /* 1/4 subsample resolution */
+ fraction = -3;
+ if ((t0_fr2 == PIT_MIN)||((i_subfr == 0) && (t0 >= t0_fr2)))
+ {
+ step = 2; /* 1/2 subsample resolution */
+ fraction = -2;
+ }
+ if(t0 == t0_min)
+ {
+ fraction = 0;
+ }
+ max = Interpol_4(&corr[t0], fraction);
+
+ for (i = fraction + step; i <= 3; i += step)
+ {
+ temp = Interpol_4(&corr[t0], i);
+ if(temp > max)
+ {
+ max = temp;
+ fraction = i;
+ }
+ }
+ /* limit the fraction value in the interval [0,1,2,3] */
+ if (fraction < 0)
+ {
+ fraction += UP_SAMP;
+ t0 -= 1;
+ }
+ *pit_frac = fraction;
+ return (t0);
+}
+
+
+/***********************************************************************************
+* Function: Norm_Corr() *
+* *
+* Description: Find the normalized correlation between the target vector and the *
+* filtered past excitation. *
+* (correlation between target and filtered excitation divided by the *
+* square root of energy of target and filtered excitation). *
+************************************************************************************/
+#ifndef ASM_OPT
+static void Norm_Corr(
+ Word16 exc[], /* (i) : excitation buffer */
+ Word16 xn[], /* (i) : target vector */
+ Word16 h[], /* (i) Q15 : impulse response of synth/wgt filters */
+ Word16 L_subfr,
+ Word16 t_min, /* (i) : minimum value of pitch lag. */
+ Word16 t_max, /* (i) : maximum value of pitch lag. */
+ Word16 corr_norm[]) /* (o) Q15 : normalized correlation */
+{
+ Word32 i, k, t;
+ Word32 corr, exp_corr, norm, exp, scale;
+ Word16 exp_norm, excf[L_SUBFR], tmp;
+ Word32 L_tmp, L_tmp1, L_tmp2;
+
+ /* compute the filtered excitation for the first delay t_min */
+ k = -t_min;
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Convolve_asm(&exc[k], h, excf, 64);
+#else
+ Convolve(&exc[k], h, excf, 64);
+#endif
+
+ /* Compute rounded down 1/sqrt(energy of xn[]) */
+ L_tmp = 0;
+ for (i = 0; i < 64; i+=4)
+ {
+ L_tmp += (xn[i] * xn[i]);
+ L_tmp += (xn[i+1] * xn[i+1]);
+ L_tmp += (xn[i+2] * xn[i+2]);
+ L_tmp += (xn[i+3] * xn[i+3]);
+ }
+
+ L_tmp = (L_tmp << 1) + 1;
+ exp = norm_l(L_tmp);
+ exp = (32 - exp);
+ //exp = exp + 2; /* energy of xn[] x 2 + rounded up */
+ scale = -(exp >> 1); /* (1<<scale) < 1/sqrt(energy rounded) */
+
+ /* loop for every possible period */
+
+ for (t = t_min; t <= t_max; t++)
+ {
+ /* Compute correlation between xn[] and excf[] */
+ L_tmp = 0;
+ L_tmp1 = 0;
+ for (i = 0; i < 64; i+=4)
+ {
+ L_tmp += (xn[i] * excf[i]);
+ L_tmp1 += (excf[i] * excf[i]);
+ L_tmp += (xn[i+1] * excf[i+1]);
+ L_tmp1 += (excf[i+1] * excf[i+1]);
+ L_tmp += (xn[i+2] * excf[i+2]);
+ L_tmp1 += (excf[i+2] * excf[i+2]);
+ L_tmp += (xn[i+3] * excf[i+3]);
+ L_tmp1 += (excf[i+3] * excf[i+3]);
+ }
+
+ L_tmp = (L_tmp << 1) + 1;
+ L_tmp1 = (L_tmp1 << 1) + 1;
+
+ exp = norm_l(L_tmp);
+ L_tmp = (L_tmp << exp);
+ exp_corr = (30 - exp);
+ corr = extract_h(L_tmp);
+
+ exp = norm_l(L_tmp1);
+ L_tmp = (L_tmp1 << exp);
+ exp_norm = (30 - exp);
+
+ Isqrt_n(&L_tmp, &exp_norm);
+ norm = extract_h(L_tmp);
+
+ /* Normalize correlation = correlation * (1/sqrt(energy)) */
+
+ L_tmp = vo_L_mult(corr, norm);
+
+ L_tmp2 = exp_corr + exp_norm + scale;
+ if(L_tmp2 < 0)
+ {
+ L_tmp2 = -L_tmp2;
+ L_tmp = L_tmp >> L_tmp2;
+ }
+ else
+ {
+ L_tmp = L_tmp << L_tmp2;
+ }
+
+ corr_norm[t] = vo_round(L_tmp);
+ /* modify the filtered excitation excf[] for the next iteration */
+
+ if(t != t_max)
+ {
+ k = -(t + 1);
+ tmp = exc[k];
+ for (i = 63; i > 0; i--)
+ {
+ excf[i] = add1(vo_mult(tmp, h[i]), excf[i - 1]);
+ }
+ excf[0] = vo_mult(tmp, h[0]);
+ }
+ }
+ return;
+}
+
+#endif
+/************************************************************************************
+* Function: Interpol_4() *
+* *
+* Description: For interpolating the normalized correlation with 1/4 resolution. *
+**************************************************************************************/
+
+/* 1/4 resolution interpolation filter (-3 dB at 0.791*fs/2) in Q14 */
+static Word16 inter4_1[4][8] =
+{
+ {-12, 420, -1732, 5429, 13418, -1242, 73, 32},
+ {-26, 455, -2142, 9910, 9910, -2142, 455, -26},
+ {32, 73, -1242, 13418, 5429, -1732, 420, -12},
+ {206, -766, 1376, 14746, 1376, -766, 206, 0}
+};
+
+/*** Coefficients in floating point
+static float inter4_1[UP_SAMP*L_INTERPOL1+1] = {
+0.900000,
+0.818959, 0.604850, 0.331379, 0.083958,
+-0.075795, -0.130717, -0.105685, -0.046774,
+0.004467, 0.027789, 0.025642, 0.012571,
+0.001927, -0.001571, -0.000753, 0.000000};
+***/
+
+static Word16 Interpol_4( /* (o) : interpolated value */
+ Word16 * x, /* (i) : input vector */
+ Word32 frac /* (i) : fraction (-4..+3) */
+ )
+{
+ Word16 sum;
+ Word32 k, L_sum;
+ Word16 *ptr;
+
+ if (frac < 0)
+ {
+ frac += UP_SAMP;
+ x--;
+ }
+ x = x - L_INTERPOL1 + 1;
+ k = UP_SAMP - 1 - frac;
+ ptr = &(inter4_1[k][0]);
+
+ L_sum = vo_mult32(x[0], (*ptr++));
+ L_sum += vo_mult32(x[1], (*ptr++));
+ L_sum += vo_mult32(x[2], (*ptr++));
+ L_sum += vo_mult32(x[3], (*ptr++));
+ L_sum += vo_mult32(x[4], (*ptr++));
+ L_sum += vo_mult32(x[5], (*ptr++));
+ L_sum += vo_mult32(x[6], (*ptr++));
+ L_sum += vo_mult32(x[7], (*ptr++));
+
+ sum = extract_h(L_add(L_shl2(L_sum, 2), 0x8000));
+ return (sum);
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c b/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c
new file mode 100644
index 0000000..ac1ff22
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/pred_lt4.c
@@ -0,0 +1,120 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: pred_lt4.c *
+* *
+* Description: Compute the result of long term prediction with *
+* fractional interpolation of resolution 1/4 *
+* on return exc[0..L_subr-1] contains the interpolated signal *
+* (adaptive codebook excitation) *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+#define UP_SAMP 4
+#define L_INTERPOL2 16
+
+/* 1/4 resolution interpolation filter (-3 dB at 0.856*fs/2) in Q14 */
+
+Word16 inter4_2[4][32] =
+{
+ {0,-2,4,-2,-10,38,-88,165,-275,424,-619,871,-1207,1699,-2598,5531,14031,-2147,780,-249,
+ -16,153,-213,226,-209,175,-133,91,-55,28,-10,2},
+
+ {1,-7,19,-33,47,-52,43,-9,-60,175,-355,626,-1044,1749,-3267,10359,10359,-3267,1749,-1044,
+ 626,-355,175,-60,-9,43,-52,47,-33,19, -7, 1},
+
+ {2,-10,28,-55,91,-133,175,-209,226,-213,153,-16,-249,780,-2147,14031,5531,-2598,1699,-1207,
+ 871,-619,424,-275,165,-88,38,-10,-2,4,-2,0},
+
+ {1,-7,22,-49,92,-153,231,-325,431,-544,656,-762,853,-923,968,15401,968,-923,853,-762,
+ 656,-544,431,-325,231,-153,92,-49,22,-7, 1, 0}
+
+};
+
+void Pred_lt4(
+ Word16 exc[], /* in/out: excitation buffer */
+ Word16 T0, /* input : integer pitch lag */
+ Word16 frac, /* input : fraction of lag */
+ Word16 L_subfr /* input : subframe size */
+ )
+{
+ Word16 j, k, *x;
+ Word32 L_sum;
+ Word16 *ptr, *ptr1;
+ Word16 *ptr2;
+
+ x = exc - T0;
+ frac = -frac;
+ if (frac < 0)
+ {
+ frac += UP_SAMP;
+ x--;
+ }
+ x -= 15; /* x = L_INTERPOL2 - 1 */
+ k = 3 - frac; /* k = UP_SAMP - 1 - frac */
+
+ ptr2 = &(inter4_2[k][0]);
+ for (j = 0; j < L_subfr; j++)
+ {
+ ptr = ptr2;
+ ptr1 = x;
+ L_sum = vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+ L_sum += vo_mult32((*ptr1++), (*ptr++));
+
+ L_sum = L_shl2(L_sum, 2);
+ exc[j] = extract_h(L_add(L_sum, 0x8000));
+ x++;
+ }
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/preemph.c b/media/libstagefright/codecs/amrwbenc/src/preemph.c
new file mode 100644
index 0000000..f5bcd33
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/preemph.c
@@ -0,0 +1,88 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: preemph.c *
+* *
+* Description: Preemphasis: filtering through 1 - g z^-1 *
+* Preemph2 --> signal is multiplied by 2 *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Preemph(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+ )
+{
+ Word16 temp;
+ Word32 i, L_tmp;
+
+ temp = x[lg - 1];
+
+ for (i = lg - 1; i > 0; i--)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp -= (x[i - 1] * mu)<<1;
+ x[i] = (L_tmp + 0x8000)>>16;
+ }
+
+ L_tmp = L_deposit_h(x[0]);
+ L_tmp -= ((*mem) * mu)<<1;
+ x[0] = (L_tmp + 0x8000)>>16;
+
+ *mem = temp;
+
+ return;
+}
+
+
+void Preemph2(
+ Word16 x[], /* (i/o) : input signal overwritten by the output */
+ Word16 mu, /* (i) Q15 : preemphasis coefficient */
+ Word16 lg, /* (i) : lenght of filtering */
+ Word16 * mem /* (i/o) : memory (x[-1]) */
+ )
+{
+ Word16 temp;
+ Word32 i, L_tmp;
+
+ temp = x[lg - 1];
+
+ for (i = (Word16) (lg - 1); i > 0; i--)
+ {
+ L_tmp = L_deposit_h(x[i]);
+ L_tmp -= (x[i - 1] * mu)<<1;
+ L_tmp = (L_tmp << 1);
+ x[i] = (L_tmp + 0x8000)>>16;
+ }
+
+ L_tmp = L_deposit_h(x[0]);
+ L_tmp -= ((*mem) * mu)<<1;
+ L_tmp = (L_tmp << 1);
+ x[0] = (L_tmp + 0x8000)>>16;
+
+ *mem = temp;
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/q_gain2.c b/media/libstagefright/codecs/amrwbenc/src/q_gain2.c
new file mode 100644
index 0000000..59eefe4
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/q_gain2.c
@@ -0,0 +1,346 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: q_gain2.c *
+* *
+* Description: *
+* Quantization of pitch and codebook gains. *
+* MA prediction is performed on the innovation energy (in dB with mean *
+* removed). *
+* An initial predicted gain, g_0, is first determined and the correction *
+* factor alpha = gain / g_0 is quantized. *
+* The pitch gain and the correction factor are vector quantized and the *
+* mean-squared weighted error criterion is used in the quantizer search. *
+****************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "log2.h"
+#include "acelp.h"
+#include "q_gain2.tab"
+
+#define MEAN_ENER 30
+#define RANGE 64
+#define PRED_ORDER 4
+
+
+/* MA prediction coeff ={0.5, 0.4, 0.3, 0.2} in Q13 */
+static Word16 pred[PRED_ORDER] = {4096, 3277, 2458, 1638};
+
+
+void Init_Q_gain2(
+ Word16 * mem /* output :static memory (2 words) */
+ )
+{
+ Word32 i;
+
+ /* 4nd order quantizer energy predictor (init to -14.0 in Q10) */
+ for (i = 0; i < PRED_ORDER; i++)
+ {
+ mem[i] = -14336; /* past_qua_en[i] */
+ }
+
+ return;
+}
+
+Word16 Q_gain2( /* Return index of quantization. */
+ Word16 xn[], /* (i) Q_xn: Target vector. */
+ Word16 y1[], /* (i) Q_xn: Adaptive codebook. */
+ Word16 Q_xn, /* (i) : xn and y1 format */
+ Word16 y2[], /* (i) Q9 : Filtered innovative vector. */
+ Word16 code[], /* (i) Q9 : Innovative vector. */
+ Word16 g_coeff[], /* (i) : Correlations <xn y1> <y1 y1> */
+ /* Compute in G_pitch(). */
+ Word16 L_subfr, /* (i) : Subframe lenght. */
+ Word16 nbits, /* (i) : number of bits (6 or 7) */
+ Word16 * gain_pit, /* (i/o)Q14: Pitch gain. */
+ Word32 * gain_cod, /* (o) Q16 : Code gain. */
+ Word16 gp_clip, /* (i) : Gp Clipping flag */
+ Word16 * mem /* (i/o) : static memory (2 words) */
+ )
+{
+ Word16 index, *p, min_ind, size;
+ Word16 exp, frac, gcode0, exp_gcode0, e_max, exp_code, qua_ener;
+ Word16 g_pitch, g2_pitch, g_code, g_pit_cod, g2_code, g2_code_lo;
+ Word16 coeff[5], coeff_lo[5], exp_coeff[5];
+ Word16 exp_max[5];
+ Word32 i, j, L_tmp, dist_min;
+ Word16 *past_qua_en, *t_qua_gain;
+
+ past_qua_en = mem;
+
+ /*-----------------------------------------------------------------*
+ * - Find the initial quantization pitch index *
+ * - Set gains search range *
+ *-----------------------------------------------------------------*/
+ if (nbits == 6)
+ {
+ t_qua_gain = t_qua_gain6b;
+ min_ind = 0;
+ size = RANGE;
+
+ if(gp_clip == 1)
+ {
+ size = size - 16; /* limit gain pitch to 1.0 */
+ }
+ } else
+ {
+ t_qua_gain = t_qua_gain7b;
+
+ p = t_qua_gain7b + RANGE; /* pt at 1/4th of table */
+
+ j = nb_qua_gain7b - RANGE;
+
+ if (gp_clip == 1)
+ {
+ j = j - 27; /* limit gain pitch to 1.0 */
+ }
+ min_ind = 0;
+ g_pitch = *gain_pit;
+
+ for (i = 0; i < j; i++, p += 2)
+ {
+ if (g_pitch > *p)
+ {
+ min_ind = min_ind + 1;
+ }
+ }
+ size = RANGE;
+ }
+
+ /*------------------------------------------------------------------*
+ * Compute coefficient need for the quantization. *
+ * *
+ * coeff[0] = y1 y1 *
+ * coeff[1] = -2 xn y1 *
+ * coeff[2] = y2 y2 *
+ * coeff[3] = -2 xn y2 *
+ * coeff[4] = 2 y1 y2 *
+ * *
+ * Product <y1 y1> and <xn y1> have been compute in G_pitch() and *
+ * are in vector g_coeff[]. *
+ *------------------------------------------------------------------*/
+
+ coeff[0] = g_coeff[0];
+ exp_coeff[0] = g_coeff[1];
+ coeff[1] = negate(g_coeff[2]); /* coeff[1] = -2 xn y1 */
+ exp_coeff[1] = g_coeff[3] + 1;
+
+ /* Compute scalar product <y2[],y2[]> */
+#ifdef ASM_OPT /* asm optimization branch */
+ coeff[2] = extract_h(Dot_product12_asm(y2, y2, L_subfr, &exp));
+#else
+ coeff[2] = extract_h(Dot_product12(y2, y2, L_subfr, &exp));
+#endif
+ exp_coeff[2] = (exp - 18) + (Q_xn << 1); /* -18 (y2 Q9) */
+
+ /* Compute scalar product -2*<xn[],y2[]> */
+#ifdef ASM_OPT /* asm optimization branch */
+ coeff[3] = extract_h(L_negate(Dot_product12_asm(xn, y2, L_subfr, &exp)));
+#else
+ coeff[3] = extract_h(L_negate(Dot_product12(xn, y2, L_subfr, &exp)));
+#endif
+
+ exp_coeff[3] = (exp - 8) + Q_xn; /* -9 (y2 Q9), +1 (2 xn y2) */
+
+ /* Compute scalar product 2*<y1[],y2[]> */
+#ifdef ASM_OPT /* asm optimization branch */
+ coeff[4] = extract_h(Dot_product12_asm(y1, y2, L_subfr, &exp));
+#else
+ coeff[4] = extract_h(Dot_product12(y1, y2, L_subfr, &exp));
+#endif
+ exp_coeff[4] = (exp - 8) + Q_xn; /* -9 (y2 Q9), +1 (2 y1 y2) */
+
+ /*-----------------------------------------------------------------*
+ * Find energy of code and compute: *
+ * *
+ * L_tmp = MEAN_ENER - 10log10(energy of code/ L_subfr) *
+ * = MEAN_ENER - 3.0103*log2(energy of code/ L_subfr) *
+ *-----------------------------------------------------------------*/
+#ifdef ASM_OPT /* asm optimization branch */
+ L_tmp = Dot_product12_asm(code, code, L_subfr, &exp_code);
+#else
+ L_tmp = Dot_product12(code, code, L_subfr, &exp_code);
+#endif
+ /* exp_code: -18 (code in Q9), -6 (/L_subfr), -31 (L_tmp Q31->Q0) */
+ exp_code = (exp_code - (18 + 6 + 31));
+
+ Log2(L_tmp, &exp, &frac);
+ exp += exp_code;
+ L_tmp = Mpy_32_16(exp, frac, -24660); /* x -3.0103(Q13) -> Q14 */
+
+ L_tmp += (MEAN_ENER * 8192)<<1; /* + MEAN_ENER in Q14 */
+
+ /*-----------------------------------------------------------------*
+ * Compute gcode0. *
+ * = Sum(i=0,1) pred[i]*past_qua_en[i] + mean_ener - ener_code *
+ *-----------------------------------------------------------------*/
+ L_tmp = (L_tmp << 10); /* From Q14 to Q24 */
+ L_tmp += (pred[0] * past_qua_en[0])<<1; /* Q13*Q10 -> Q24 */
+ L_tmp += (pred[1] * past_qua_en[1])<<1; /* Q13*Q10 -> Q24 */
+ L_tmp += (pred[2] * past_qua_en[2])<<1; /* Q13*Q10 -> Q24 */
+ L_tmp += (pred[3] * past_qua_en[3])<<1; /* Q13*Q10 -> Q24 */
+
+ gcode0 = extract_h(L_tmp); /* From Q24 to Q8 */
+
+ /*-----------------------------------------------------------------*
+ * gcode0 = pow(10.0, gcode0/20) *
+ * = pow(2, 3.321928*gcode0/20) *
+ * = pow(2, 0.166096*gcode0) *
+ *-----------------------------------------------------------------*/
+
+ L_tmp = vo_L_mult(gcode0, 5443); /* *0.166096 in Q15 -> Q24 */
+ L_tmp = L_tmp >> 8; /* From Q24 to Q16 */
+ VO_L_Extract(L_tmp, &exp_gcode0, &frac); /* Extract exponent of gcode0 */
+
+ gcode0 = (Word16)(Pow2(14, frac)); /* Put 14 as exponent so that */
+ /* output of Pow2() will be: */
+ /* 16384 < Pow2() <= 32767 */
+ exp_gcode0 -= 14;
+
+ /*-------------------------------------------------------------------------*
+ * Find the best quantizer *
+ * ~~~~~~~~~~~~~~~~~~~~~~~ *
+ * Before doing the computation we need to aling exponents of coeff[] *
+ * to be sure to have the maximum precision. *
+ * *
+ * In the table the pitch gains are in Q14, the code gains are in Q11 and *
+ * are multiply by gcode0 which have been multiply by 2^exp_gcode0. *
+ * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code *
+ * we divide by 2^15. *
+ * Considering all the scaling above we have: *
+ * *
+ * exp_code = exp_gcode0-11+15 = exp_gcode0+4 *
+ * *
+ * g_pitch*g_pitch = -14-14+15 *
+ * g_pitch = -14 *
+ * g_code*g_code = (2*exp_code)+15 *
+ * g_code = exp_code *
+ * g_pitch*g_code = -14 + exp_code +15 *
+ * *
+ * g_pitch*g_pitch * coeff[0] ;exp_max0 = exp_coeff[0] - 13 *
+ * g_pitch * coeff[1] ;exp_max1 = exp_coeff[1] - 14 *
+ * g_code*g_code * coeff[2] ;exp_max2 = exp_coeff[2] +15+(2*exp_code) *
+ * g_code * coeff[3] ;exp_max3 = exp_coeff[3] + exp_code *
+ * g_pitch*g_code * coeff[4] ;exp_max4 = exp_coeff[4] + 1 + exp_code *
+ *-------------------------------------------------------------------------*/
+
+ exp_code = (exp_gcode0 + 4);
+ exp_max[0] = (exp_coeff[0] - 13);
+ exp_max[1] = (exp_coeff[1] - 14);
+ exp_max[2] = (exp_coeff[2] + (15 + (exp_code << 1)));
+ exp_max[3] = (exp_coeff[3] + exp_code);
+ exp_max[4] = (exp_coeff[4] + (1 + exp_code));
+
+ /* Find maximum exponant */
+
+ e_max = exp_max[0];
+ for (i = 1; i < 5; i++)
+ {
+ if(exp_max[i] > e_max)
+ {
+ e_max = exp_max[i];
+ }
+ }
+
+ /* align coeff[] and save in special 32 bit double precision */
+
+ for (i = 0; i < 5; i++)
+ {
+ j = add1(vo_sub(e_max, exp_max[i]), 2);/* /4 to avoid overflow */
+ L_tmp = L_deposit_h(coeff[i]);
+ L_tmp = L_shr(L_tmp, j);
+ VO_L_Extract(L_tmp, &coeff[i], &coeff_lo[i]);
+ coeff_lo[i] = (coeff_lo[i] >> 3); /* lo >> 3 */
+ }
+
+ /* Codebook search */
+ dist_min = MAX_32;
+ p = &t_qua_gain[min_ind << 1];
+
+ index = 0;
+ for (i = 0; i < size; i++)
+ {
+ g_pitch = *p++;
+ g_code = *p++;
+
+ g_code = ((g_code * gcode0) + 0x4000)>>15;
+ g2_pitch = ((g_pitch * g_pitch) + 0x4000)>>15;
+ g_pit_cod = ((g_code * g_pitch) + 0x4000)>>15;
+ L_tmp = (g_code * g_code)<<1;
+ VO_L_Extract(L_tmp, &g2_code, &g2_code_lo);
+
+ L_tmp = (coeff[2] * g2_code_lo)<<1;
+ L_tmp = (L_tmp >> 3);
+ L_tmp += (coeff_lo[0] * g2_pitch)<<1;
+ L_tmp += (coeff_lo[1] * g_pitch)<<1;
+ L_tmp += (coeff_lo[2] * g2_code)<<1;
+ L_tmp += (coeff_lo[3] * g_code)<<1;
+ L_tmp += (coeff_lo[4] * g_pit_cod)<<1;
+ L_tmp = (L_tmp >> 12);
+ L_tmp += (coeff[0] * g2_pitch)<<1;
+ L_tmp += (coeff[1] * g_pitch)<<1;
+ L_tmp += (coeff[2] * g2_code)<<1;
+ L_tmp += (coeff[3] * g_code)<<1;
+ L_tmp += (coeff[4] * g_pit_cod)<<1;
+
+ if(L_tmp < dist_min)
+ {
+ dist_min = L_tmp;
+ index = i;
+ }
+ }
+
+ /* Read the quantized gains */
+ index = index + min_ind;
+ p = &t_qua_gain[(index + index)];
+ *gain_pit = *p++; /* selected pitch gain in Q14 */
+ g_code = *p++; /* selected code gain in Q11 */
+
+ L_tmp = vo_L_mult(g_code, gcode0); /* Q11*Q0 -> Q12 */
+ L_tmp = L_shl(L_tmp, (exp_gcode0 + 4)); /* Q12 -> Q16 */
+
+ *gain_cod = L_tmp; /* gain of code in Q16 */
+
+ /*---------------------------------------------------*
+ * qua_ener = 20*log10(g_code) *
+ * = 6.0206*log2(g_code) *
+ * = 6.0206*(log2(g_codeQ11) - 11) *
+ *---------------------------------------------------*/
+
+ L_tmp = L_deposit_l(g_code);
+ Log2(L_tmp, &exp, &frac);
+ exp -= 11;
+ L_tmp = Mpy_32_16(exp, frac, 24660); /* x 6.0206 in Q12 */
+
+ qua_ener = (Word16)(L_tmp >> 3); /* result in Q10 */
+
+ /* update table of past quantized energies */
+
+ past_qua_en[3] = past_qua_en[2];
+ past_qua_en[2] = past_qua_en[1];
+ past_qua_en[1] = past_qua_en[0];
+ past_qua_en[0] = qua_ener;
+
+ return (index);
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/q_pulse.c b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
new file mode 100644
index 0000000..a28ba40
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/q_pulse.c
@@ -0,0 +1,400 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: q_pulse.c *
+* *
+* Description: Coding and decoding of algebraic codebook *
+* *
+************************************************************************/
+
+#include <stdio.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "q_pulse.h"
+
+#define NB_POS 16 /* pos in track, mask for sign bit */
+
+Word32 quant_1p_N1( /* (o) return N+1 bits */
+ Word16 pos, /* (i) position of the pulse */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 mask;
+ Word32 index;
+
+ mask = (1 << N) - 1; /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Quantization of 1 pulse with N+1 bits: *
+ *-------------------------------------------------------*/
+ index = L_deposit_l((Word16) (pos & mask));
+ if ((pos & NB_POS) != 0)
+ {
+ index = vo_L_add(index, L_deposit_l(1 << N)); /* index += 1 << N; */
+ }
+ return (index);
+}
+
+
+Word32 quant_2p_2N1( /* (o) return (2*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 mask, tmp;
+ Word32 index;
+ mask = (1 << N) - 1; /* mask = ((1<<N)-1); */
+ /*-------------------------------------------------------*
+ * Quantization of 2 pulses with 2*N+1 bits: *
+ *-------------------------------------------------------*/
+ if (((pos2 ^ pos1) & NB_POS) == 0)
+ {
+ /* sign of 1st pulse == sign of 2th pulse */
+ if(pos1 <= pos2) /* ((pos1 - pos2) <= 0) */
+ {
+ /* index = ((pos1 & mask) << N) + (pos2 & mask); */
+ index = L_deposit_l(add1((((Word16) (pos1 & mask)) << N), ((Word16) (pos2 & mask))));
+ } else
+ {
+ /* ((pos2 & mask) << N) + (pos1 & mask); */
+ index = L_deposit_l(add1((((Word16) (pos2 & mask)) << N), ((Word16) (pos1 & mask))));
+ }
+ if ((pos1 & NB_POS) != 0)
+ {
+ tmp = (N << 1);
+ index = vo_L_add(index, (1L << tmp)); /* index += 1 << (2*N); */
+ }
+ } else
+ {
+ /* sign of 1st pulse != sign of 2th pulse */
+ if (vo_sub((Word16) (pos1 & mask), (Word16) (pos2 & mask)) <= 0)
+ {
+ /* index = ((pos2 & mask) << N) + (pos1 & mask); */
+ index = L_deposit_l(add1((((Word16) (pos2 & mask)) << N), ((Word16) (pos1 & mask))));
+ if ((pos2 & NB_POS) != 0)
+ {
+ tmp = (N << 1); /* index += 1 << (2*N); */
+ index = vo_L_add(index, (1L << tmp));
+ }
+ } else
+ {
+ /* index = ((pos1 & mask) << N) + (pos2 & mask); */
+ index = L_deposit_l(add1((((Word16) (pos1 & mask)) << N), ((Word16) (pos2 & mask))));
+ if ((pos1 & NB_POS) != 0)
+ {
+ tmp = (N << 1);
+ index = vo_L_add(index, (1 << tmp)); /* index += 1 << (2*N); */
+ }
+ }
+ }
+ return (index);
+}
+
+
+Word32 quant_3p_3N1( /* (o) return (3*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos;
+ Word32 index;
+
+ nb_pos =(1 <<(N - 1)); /* nb_pos = (1<<(N-1)); */
+ /*-------------------------------------------------------*
+ * Quantization of 3 pulses with 3*N+1 bits: *
+ *-------------------------------------------------------*/
+ if (((pos1 ^ pos2) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos2, sub(N, 1)); /* index = quant_2p_2N1(pos1, pos2, (N-1)); */
+ /* index += (pos1 & nb_pos) << N; */
+ index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));
+ /* index += quant_1p_N1(pos3, N) << (2*N); */
+ index = vo_L_add(index, (quant_1p_N1(pos3, N)<<(N << 1)));
+
+ } else if (((pos1 ^ pos3) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos3, sub(N, 1)); /* index = quant_2p_2N1(pos1, pos3, (N-1)); */
+ index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));
+ /* index += (pos1 & nb_pos) << N; */
+ index = vo_L_add(index, (quant_1p_N1(pos2, N) << (N << 1)));
+ /* index += quant_1p_N1(pos2, N) <<
+ * (2*N); */
+ } else
+ {
+ index = quant_2p_2N1(pos2, pos3, (N - 1)); /* index = quant_2p_2N1(pos2, pos3, (N-1)); */
+ /* index += (pos2 & nb_pos) << N; */
+ index = vo_L_add(index, (L_deposit_l((Word16) (pos2 & nb_pos)) << N));
+ /* index += quant_1p_N1(pos1, N) << (2*N); */
+ index = vo_L_add(index, (quant_1p_N1(pos1, N) << (N << 1)));
+ }
+ return (index);
+}
+
+
+Word32 quant_4p_4N1( /* (o) return (4*N)+1 bits */
+ Word16 pos1, /* (i) position of the pulse 1 */
+ Word16 pos2, /* (i) position of the pulse 2 */
+ Word16 pos3, /* (i) position of the pulse 3 */
+ Word16 pos4, /* (i) position of the pulse 4 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos;
+ Word32 index;
+
+ nb_pos = 1 << (N - 1); /* nb_pos = (1<<(N-1)); */
+ /*-------------------------------------------------------*
+ * Quantization of 4 pulses with 4*N+1 bits: *
+ *-------------------------------------------------------*/
+ if (((pos1 ^ pos2) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos2, sub(N, 1)); /* index = quant_2p_2N1(pos1, pos2, (N-1)); */
+ /* index += (pos1 & nb_pos) << N; */
+ index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));
+ /* index += quant_2p_2N1(pos3, pos4, N) << (2*N); */
+ index = vo_L_add(index, (quant_2p_2N1(pos3, pos4, N) << (N << 1)));
+ } else if (((pos1 ^ pos3) & nb_pos) == 0)
+ {
+ index = quant_2p_2N1(pos1, pos3, (N - 1));
+ /* index += (pos1 & nb_pos) << N; */
+ index = vo_L_add(index, (L_deposit_l((Word16) (pos1 & nb_pos)) << N));
+ /* index += quant_2p_2N1(pos2, pos4, N) << (2*N); */
+ index = vo_L_add(index, (quant_2p_2N1(pos2, pos4, N) << (N << 1)));
+ } else
+ {
+ index = quant_2p_2N1(pos2, pos3, (N - 1));
+ /* index += (pos2 & nb_pos) << N; */
+ index = vo_L_add(index, (L_deposit_l((Word16) (pos2 & nb_pos)) << N));
+ /* index += quant_2p_2N1(pos1, pos4, N) << (2*N); */
+ index = vo_L_add(index, (quant_2p_2N1(pos1, pos4, N) << (N << 1)));
+ }
+ return (index);
+}
+
+
+Word32 quant_4p_4N( /* (o) return 4*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..4 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos, mask, n_1, tmp;
+ Word16 posA[4], posB[4];
+ Word32 i, j, k, index;
+
+ n_1 = (Word16) (N - 1);
+ nb_pos = (1 << n_1); /* nb_pos = (1<<n_1); */
+ mask = vo_sub((1 << N), 1); /* mask = ((1<<N)-1); */
+
+ i = 0;
+ j = 0;
+ for (k = 0; k < 4; k++)
+ {
+ if ((pos[k] & nb_pos) == 0)
+ {
+ posA[i++] = pos[k];
+ } else
+ {
+ posB[j++] = pos[k];
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ tmp = vo_sub((N << 2), 3); /* index = 1 << ((4*N)-3); */
+ index = (1L << tmp);
+ /* index += quant_4p_4N1(posB[0], posB[1], posB[2], posB[3], n_1); */
+ index = vo_L_add(index, quant_4p_4N1(posB[0], posB[1], posB[2], posB[3], n_1));
+ break;
+ case 1:
+ /* index = quant_1p_N1(posA[0], n_1) << ((3*n_1)+1); */
+ tmp = add1((Word16)((vo_L_mult(3, n_1) >> 1)), 1);
+ index = L_shl(quant_1p_N1(posA[0], n_1), tmp);
+ /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */
+ index = vo_L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1));
+ break;
+ case 2:
+ tmp = ((n_1 << 1) + 1); /* index = quant_2p_2N1(posA[0], posA[1], n_1) << ((2*n_1)+1); */
+ index = L_shl(quant_2p_2N1(posA[0], posA[1], n_1), tmp);
+ /* index += quant_2p_2N1(posB[0], posB[1], n_1); */
+ index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], n_1));
+ break;
+ case 3:
+ /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << N; */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), N);
+ index = vo_L_add(index, quant_1p_N1(posB[0], n_1)); /* index += quant_1p_N1(posB[0], n_1); */
+ break;
+ case 4:
+ index = quant_4p_4N1(posA[0], posA[1], posA[2], posA[3], n_1);
+ break;
+ default:
+ index = 0;
+ fprintf(stderr, "Error in function quant_4p_4N\n");
+ }
+ tmp = ((N << 2) - 2); /* index += (i & 3) << ((4*N)-2); */
+ index = vo_L_add(index, L_shl((L_deposit_l(i) & (3L)), tmp));
+
+ return (index);
+}
+
+
+
+Word32 quant_5p_5N( /* (o) return 5*N bits */
+ Word16 pos[], /* (i) position of the pulse 1..5 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos, n_1, tmp;
+ Word16 posA[5], posB[5];
+ Word32 i, j, k, index, tmp2;
+
+ n_1 = (Word16) (N - 1);
+ nb_pos = (1 << n_1); /* nb_pos = (1<<n_1); */
+
+ i = 0;
+ j = 0;
+ for (k = 0; k < 5; k++)
+ {
+ if ((pos[k] & nb_pos) == 0)
+ {
+ posA[i++] = pos[k];
+ } else
+ {
+ posB[j++] = pos[k];
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1); /* ((5*N)-1)) */
+ index = L_shl(1L, tmp); /* index = 1 << ((5*N)-1); */
+ tmp = add1((N << 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1);*/
+ tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);
+ index = vo_L_add(index, tmp2);
+ index = vo_L_add(index, quant_2p_2N1(posB[3], posB[4], N)); /* index += quant_2p_2N1(posB[3], posB[4], N); */
+ break;
+ case 1:
+ tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1); /* index = 1 << ((5*N)-1); */
+ index = L_shl(1L, tmp);
+ tmp = add1((N << 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) <<((2*N)+1); */
+ tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);
+ index = vo_L_add(index, tmp2);
+ index = vo_L_add(index, quant_2p_2N1(posB[3], posA[0], N)); /* index += quant_2p_2N1(posB[3], posA[0], N); */
+ break;
+ case 2:
+ tmp = vo_sub((Word16)((vo_L_mult(5, N) >> 1)), 1); /* ((5*N)-1)) */
+ index = L_shl(1L, tmp); /* index = 1 << ((5*N)-1); */
+ tmp = add1((N << 1), 1); /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1) << ((2*N)+1); */
+ tmp2 = L_shl(quant_3p_3N1(posB[0], posB[1], posB[2], n_1), tmp);
+ index = vo_L_add(index, tmp2);
+ index = vo_L_add(index, quant_2p_2N1(posA[0], posA[1], N)); /* index += quant_2p_2N1(posA[0], posA[1], N); */
+ break;
+ case 3:
+ tmp = add1((N << 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);
+ index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], N)); /* index += quant_2p_2N1(posB[0], posB[1], N); */
+ break;
+ case 4:
+ tmp = add1((N << 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);
+ index = vo_L_add(index, quant_2p_2N1(posA[3], posB[0], N)); /* index += quant_2p_2N1(posA[3], posB[0], N); */
+ break;
+ case 5:
+ tmp = add1((N << 1), 1); /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((2*N)+1); */
+ index = L_shl(quant_3p_3N1(posA[0], posA[1], posA[2], n_1), tmp);
+ index = vo_L_add(index, quant_2p_2N1(posA[3], posA[4], N)); /* index += quant_2p_2N1(posA[3], posA[4], N); */
+ break;
+ default:
+ index = 0;
+ fprintf(stderr, "Error in function quant_5p_5N\n");
+ }
+
+ return (index);
+}
+
+
+Word32 quant_6p_6N_2( /* (o) return (6*N)-2 bits */
+ Word16 pos[], /* (i) position of the pulse 1..6 */
+ Word16 N) /* (i) number of bits for position */
+{
+ Word16 nb_pos, n_1;
+ Word16 posA[6], posB[6];
+ Word32 i, j, k, index;
+
+ /* !! N and n_1 are constants -> it doesn't need to be operated by Basic Operators */
+ n_1 = (Word16) (N - 1);
+ nb_pos = (1 << n_1); /* nb_pos = (1<<n_1); */
+
+ i = 0;
+ j = 0;
+ for (k = 0; k < 6; k++)
+ {
+ if ((pos[k] & nb_pos) == 0)
+ {
+ posA[i++] = pos[k];
+ } else
+ {
+ posB[j++] = pos[k];
+ }
+ }
+
+ switch (i)
+ {
+ case 0:
+ index = (1 << (Word16) (6 * N - 5)); /* index = 1 << ((6*N)-5); */
+ index = vo_L_add(index, (quant_5p_5N(posB, n_1) << N)); /* index += quant_5p_5N(posB, n_1) << N; */
+ index = vo_L_add(index, quant_1p_N1(posB[5], n_1)); /* index += quant_1p_N1(posB[5], n_1); */
+ break;
+ case 1:
+ index = (1L << (Word16) (6 * N - 5)); /* index = 1 << ((6*N)-5); */
+ index = vo_L_add(index, (quant_5p_5N(posB, n_1) << N)); /* index += quant_5p_5N(posB, n_1) << N; */
+ index = vo_L_add(index, quant_1p_N1(posA[0], n_1)); /* index += quant_1p_N1(posA[0], n_1); */
+ break;
+ case 2:
+ index = (1L << (Word16) (6 * N - 5)); /* index = 1 << ((6*N)-5); */
+ /* index += quant_4p_4N(posB, n_1) << ((2*n_1)+1); */
+ index = vo_L_add(index, (quant_4p_4N(posB, n_1) << (Word16) (2 * n_1 + 1)));
+ index = vo_L_add(index, quant_2p_2N1(posA[0], posA[1], n_1)); /* index += quant_2p_2N1(posA[0], posA[1], n_1); */
+ break;
+ case 3:
+ index = (quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << (Word16) (3 * n_1 + 1));
+ /* index = quant_3p_3N1(posA[0], posA[1], posA[2], n_1) << ((3*n_1)+1); */
+ index =vo_L_add(index, quant_3p_3N1(posB[0], posB[1], posB[2], n_1));
+ /* index += quant_3p_3N1(posB[0], posB[1], posB[2], n_1); */
+ break;
+ case 4:
+ i = 2;
+ index = (quant_4p_4N(posA, n_1) << (Word16) (2 * n_1 + 1)); /* index = quant_4p_4N(posA, n_1) << ((2*n_1)+1); */
+ index = vo_L_add(index, quant_2p_2N1(posB[0], posB[1], n_1)); /* index += quant_2p_2N1(posB[0], posB[1], n_1); */
+ break;
+ case 5:
+ i = 1;
+ index = (quant_5p_5N(posA, n_1) << N); /* index = quant_5p_5N(posA, n_1) << N; */
+ index = vo_L_add(index, quant_1p_N1(posB[0], n_1)); /* index += quant_1p_N1(posB[0], n_1); */
+ break;
+ case 6:
+ i = 0;
+ index = (quant_5p_5N(posA, n_1) << N); /* index = quant_5p_5N(posA, n_1) << N; */
+ index = vo_L_add(index, quant_1p_N1(posA[5], n_1)); /* index += quant_1p_N1(posA[5], n_1); */
+ break;
+ default:
+ index = 0;
+ fprintf(stderr, "Error in function quant_6p_6N_2\n");
+ }
+ index = vo_L_add(index, ((L_deposit_l(i) & 3L) << (Word16) (6 * N - 4))); /* index += (i & 3) << ((6*N)-4); */
+
+ return (index);
+}
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c b/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c
new file mode 100644
index 0000000..00b0a53
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/qisf_ns.c
@@ -0,0 +1,111 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: qisf_ns.c *
+* *
+* Description: Coding/Decoding of ISF parameters for background noise.*
+* The ISF vector is quantized using VQ with split-by-5 *
+* *
+****************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "acelp.h"
+#include "qisf_ns.tab" /* Codebooks of ISFs */
+
+/*------------------------------------------------------------------*
+* routine: Qisf_ns() *
+* ~~~~~~~~~ *
+*------------------------------------------------------------------*/
+
+void Qisf_ns(
+ Word16 * isf1, /* input : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* output: quantized ISF */
+ Word16 * indice /* output: quantization indices */
+ )
+{
+ Word16 i;
+ Word32 tmp;
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = sub(isf1[i], mean_isf_noise[i]);
+ }
+
+ indice[0] = Sub_VQ(&isf_q[0], dico1_isf_noise, 2, SIZE_BK_NOISE1, &tmp);
+ indice[1] = Sub_VQ(&isf_q[2], dico2_isf_noise, 3, SIZE_BK_NOISE2, &tmp);
+ indice[2] = Sub_VQ(&isf_q[5], dico3_isf_noise, 3, SIZE_BK_NOISE3, &tmp);
+ indice[3] = Sub_VQ(&isf_q[8], dico4_isf_noise, 4, SIZE_BK_NOISE4, &tmp);
+ indice[4] = Sub_VQ(&isf_q[12], dico5_isf_noise, 4, SIZE_BK_NOISE5, &tmp);
+
+ /* decoding the ISFs */
+
+ Disf_ns(indice, isf_q);
+
+ return;
+}
+
+/********************************************************************
+* Function: Disf_ns() *
+* ~~~~~~~~~ *
+* Decoding of ISF parameters *
+*-------------------------------------------------------------------*
+* Arguments: *
+* indice[] : indices of the selected codebook entries *
+* isf[] : quantized ISFs (in frequency domain) *
+*********************************************************************/
+
+void Disf_ns(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q /* input : ISF in the frequency domain (0..0.5) */
+ )
+{
+ Word16 i;
+
+ for (i = 0; i < 2; i++)
+ {
+ isf_q[i] = dico1_isf_noise[indice[0] * 2 + i];
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 2] = dico2_isf_noise[indice[1] * 3 + i];
+ }
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i + 5] = dico3_isf_noise[indice[2] * 3 + i];
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 8] = dico4_isf_noise[indice[3] * 4 + i];
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 12] = dico5_isf_noise[indice[4] * 4 + i];
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add(isf_q[i], mean_isf_noise[i]);
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c b/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c
new file mode 100644
index 0000000..ccedb5c
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/qpisf_2s.c
@@ -0,0 +1,542 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: apisf_2s.c *
+* *
+* Description: Coding/Decodeing of ISF parameters with predication
+* The ISF vector is quantized using two-stage VQ with split-by-2 *
+* in 1st stage and split-by-5(or 3) in the second stage *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "qpisf_2s.tab" /* Codebooks of isfs */
+
+#define MU 10923 /* Prediction factor (1.0/3.0) in Q15 */
+#define N_SURV_MAX 4 /* 4 survivors max */
+#define ALPHA 29491 /* 0. 9 in Q15 */
+#define ONE_ALPHA (32768-ALPHA) /* (1.0 - ALPHA) in Q15 */
+
+/* private functions */
+static void VQ_stage1(
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word16 * index, /* output: indices of survivors */
+ Word16 surv /* input : number of survivor */
+ );
+
+/**************************************************************************
+* Function: Qpisf_2s_46B() *
+* *
+* Description: Quantization of isf parameters with prediction. (46 bits) *
+* *
+* The isf vector is quantized using two-stage VQ with split-by-2 in *
+* 1st stage and split-by-5 in the second stage. *
+***************************************************************************/
+
+void Qpisf_2s_46b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+ )
+{
+ Word16 tmp_ind[5];
+ Word16 surv1[N_SURV_MAX]; /* indices of survivors from 1st stage */
+ Word32 i, k, temp, min_err, distance;
+ Word16 isf[ORDER];
+ Word16 isf_stage2[ORDER];
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf[i] = vo_sub(isf1[i], mean_isf[i]);
+ isf[i] = vo_sub(isf[i], vo_mult(MU, past_isfq[i]));
+ }
+
+ VQ_stage1(&isf[0], dico1_isf, 9, SIZE_BK1, surv1, nb_surv);
+
+ distance = MAX_32;
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_stage2[i] = vo_sub(isf[i], dico1_isf[i + surv1[k] * 9]);
+ }
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico21_isf, 3, SIZE_BK21, &min_err);
+ temp = min_err;
+ tmp_ind[1] = Sub_VQ(&isf_stage2[3], dico22_isf, 3, SIZE_BK22, &min_err);
+ temp = vo_L_add(temp, min_err);
+ tmp_ind[2] = Sub_VQ(&isf_stage2[6], dico23_isf, 3, SIZE_BK23, &min_err);
+ temp = vo_L_add(temp, min_err);
+
+ if(temp < distance)
+ {
+ distance = temp;
+ indice[0] = surv1[k];
+ for (i = 0; i < 3; i++)
+ {
+ indice[i + 2] = tmp_ind[i];
+ }
+ }
+ }
+
+
+ VQ_stage1(&isf[9], dico2_isf, 7, SIZE_BK2, surv1, nb_surv);
+
+ distance = MAX_32;
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 7; i++)
+ {
+ isf_stage2[i] = vo_sub(isf[9 + i], dico2_isf[i + surv1[k] * 7]);
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico24_isf, 3, SIZE_BK24, &min_err);
+ temp = min_err;
+ tmp_ind[1] = Sub_VQ(&isf_stage2[3], dico25_isf, 4, SIZE_BK25, &min_err);
+ temp = vo_L_add(temp, min_err);
+
+ if(temp < distance)
+ {
+ distance = temp;
+ indice[1] = surv1[k];
+ for (i = 0; i < 2; i++)
+ {
+ indice[i + 5] = tmp_ind[i];
+ }
+ }
+ }
+
+ Dpisf_2s_46b(indice, isf_q, past_isfq, isf_q, isf_q, 0, 0);
+
+ return;
+}
+
+/*****************************************************************************
+* Function: Qpisf_2s_36B() *
+* *
+* Description: Quantization of isf parameters with prediction. (36 bits) *
+* *
+* The isf vector is quantized using two-stage VQ with split-by-2 in *
+* 1st stage and split-by-3 in the second stage. *
+******************************************************************************/
+
+void Qpisf_2s_36b(
+ Word16 * isf1, /* (i) Q15 : ISF in the frequency domain (0..0.5) */
+ Word16 * isf_q, /* (o) Q15 : quantized ISF (0..0.5) */
+ Word16 * past_isfq, /* (io)Q15 : past ISF quantizer */
+ Word16 * indice, /* (o) : quantization indices */
+ Word16 nb_surv /* (i) : number of survivor (1, 2, 3 or 4) */
+ )
+{
+ Word16 i, k, tmp_ind[5];
+ Word16 surv1[N_SURV_MAX]; /* indices of survivors from 1st stage */
+ Word32 temp, min_err, distance;
+ Word16 isf[ORDER];
+ Word16 isf_stage2[ORDER];
+
+ for (i = 0; i < ORDER; i++)
+ {
+ isf[i] = vo_sub(isf1[i], mean_isf[i]);
+ isf[i] = vo_sub(isf[i], vo_mult(MU, past_isfq[i]));
+ }
+
+ VQ_stage1(&isf[0], dico1_isf, 9, SIZE_BK1, surv1, nb_surv);
+
+ distance = MAX_32;
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_stage2[i] = vo_sub(isf[i], dico1_isf[i + surv1[k] * 9]);
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico21_isf_36b, 5, SIZE_BK21_36b, &min_err);
+ temp = min_err;
+ tmp_ind[1] = Sub_VQ(&isf_stage2[5], dico22_isf_36b, 4, SIZE_BK22_36b, &min_err);
+ temp = vo_L_add(temp, min_err);
+
+ if(temp < distance)
+ {
+ distance = temp;
+ indice[0] = surv1[k];
+ for (i = 0; i < 2; i++)
+ {
+ indice[i + 2] = tmp_ind[i];
+ }
+ }
+ }
+
+ VQ_stage1(&isf[9], dico2_isf, 7, SIZE_BK2, surv1, nb_surv);
+ distance = MAX_32;
+
+ for (k = 0; k < nb_surv; k++)
+ {
+ for (i = 0; i < 7; i++)
+ {
+ isf_stage2[i] = vo_sub(isf[9 + i], dico2_isf[i + surv1[k] * 7]);
+ }
+
+ tmp_ind[0] = Sub_VQ(&isf_stage2[0], dico23_isf_36b, 7, SIZE_BK23_36b, &min_err);
+ temp = min_err;
+
+ if(temp < distance)
+ {
+ distance = temp;
+ indice[1] = surv1[k];
+ indice[4] = tmp_ind[0];
+ }
+ }
+
+ Dpisf_2s_36b(indice, isf_q, past_isfq, isf_q, isf_q, 0, 0);
+
+ return;
+}
+
+/*********************************************************************
+* Function: Dpisf_2s_46b() *
+* *
+* Description: Decoding of ISF parameters *
+**********************************************************************/
+
+void Dpisf_2s_46b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+ )
+{
+ Word16 ref_isf[M], tmp;
+ Word32 i, j, L_tmp;
+
+ if (bfi == 0) /* Good frame */
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_q[i] = dico1_isf[indice[0] * 9 + i];
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = dico2_isf[indice[1] * 7 + i];
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ isf_q[i] = add1(isf_q[i], dico21_isf[indice[2] * 3 + i]);
+ isf_q[i + 3] = add1(isf_q[i + 3], dico22_isf[indice[3] * 3 + i]);
+ isf_q[i + 6] = add1(isf_q[i + 6], dico23_isf[indice[4] * 3 + i]);
+ isf_q[i + 9] = add1(isf_q[i + 9], dico24_isf[indice[5] * 3 + i]);
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 12] = add1(isf_q[i + 12], dico25_isf[indice[6] * 4 + i]);
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = isf_q[i];
+ isf_q[i] = add1(tmp, mean_isf[i]);
+ isf_q[i] = add1(isf_q[i], vo_mult(MU, past_isfq[i]));
+ past_isfq[i] = tmp;
+ }
+
+ if (enc_dec)
+ {
+ for (i = 0; i < M; i++)
+ {
+ for (j = (L_MEANBUF - 1); j > 0; j--)
+ {
+ isf_buf[j * M + i] = isf_buf[(j - 1) * M + i];
+ }
+ isf_buf[i] = isf_q[i];
+ }
+ }
+ } else
+ { /* bad frame */
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = mean_isf[i] << 14;
+ for (j = 0; j < L_MEANBUF; j++)
+ {
+ L_tmp += (isf_buf[j * M + i] << 14);
+ }
+ ref_isf[i] = vo_round(L_tmp);
+ }
+
+ /* use the past ISFs slightly shifted towards their mean */
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add1(vo_mult(ALPHA, isfold[i]), vo_mult(ONE_ALPHA, ref_isf[i]));
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = add1(ref_isf[i], vo_mult(past_isfq[i], MU)); /* predicted ISF */
+ past_isfq[i] = vo_sub(isf_q[i], tmp);
+ past_isfq[i] = (past_isfq[i] >> 1); /* past_isfq[i] *= 0.5 */
+ }
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+ return;
+}
+
+/*********************************************************************
+* Function: Disf_2s_36b() *
+* *
+* Description: Decoding of ISF parameters *
+*********************************************************************/
+
+void Dpisf_2s_36b(
+ Word16 * indice, /* input: quantization indices */
+ Word16 * isf_q, /* output: quantized ISF in frequency domain (0..0.5) */
+ Word16 * past_isfq, /* i/0 : past ISF quantizer */
+ Word16 * isfold, /* input : past quantized ISF */
+ Word16 * isf_buf, /* input : isf buffer */
+ Word16 bfi, /* input : Bad frame indicator */
+ Word16 enc_dec
+ )
+{
+ Word16 ref_isf[M], tmp;
+ Word32 i, j, L_tmp;
+
+ if (bfi == 0) /* Good frame */
+ {
+ for (i = 0; i < 9; i++)
+ {
+ isf_q[i] = dico1_isf[indice[0] * 9 + i];
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = dico2_isf[indice[1] * 7 + i];
+ }
+
+ for (i = 0; i < 5; i++)
+ {
+ isf_q[i] = add1(isf_q[i], dico21_isf_36b[indice[2] * 5 + i]);
+ }
+ for (i = 0; i < 4; i++)
+ {
+ isf_q[i + 5] = add1(isf_q[i + 5], dico22_isf_36b[indice[3] * 4 + i]);
+ }
+ for (i = 0; i < 7; i++)
+ {
+ isf_q[i + 9] = add1(isf_q[i + 9], dico23_isf_36b[indice[4] * 7 + i]);
+ }
+
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = isf_q[i];
+ isf_q[i] = add1(tmp, mean_isf[i]);
+ isf_q[i] = add1(isf_q[i], vo_mult(MU, past_isfq[i]));
+ past_isfq[i] = tmp;
+ }
+
+
+ if (enc_dec)
+ {
+ for (i = 0; i < M; i++)
+ {
+ for (j = (L_MEANBUF - 1); j > 0; j--)
+ {
+ isf_buf[j * M + i] = isf_buf[(j - 1) * M + i];
+ }
+ isf_buf[i] = isf_q[i];
+ }
+ }
+ } else
+ { /* bad frame */
+ for (i = 0; i < M; i++)
+ {
+ L_tmp = (mean_isf[i] << 14);
+ for (j = 0; j < L_MEANBUF; j++)
+ {
+ L_tmp += (isf_buf[j * M + i] << 14);
+ }
+ ref_isf[i] = vo_round(L_tmp);
+ }
+
+ /* use the past ISFs slightly shifted towards their mean */
+ for (i = 0; i < ORDER; i++)
+ {
+ isf_q[i] = add1(vo_mult(ALPHA, isfold[i]), vo_mult(ONE_ALPHA, ref_isf[i]));
+ }
+
+ /* estimate past quantized residual to be used in next frame */
+ for (i = 0; i < ORDER; i++)
+ {
+ tmp = add1(ref_isf[i], vo_mult(past_isfq[i], MU)); /* predicted ISF */
+ past_isfq[i] = vo_sub(isf_q[i], tmp);
+ past_isfq[i] = past_isfq[i] >> 1; /* past_isfq[i] *= 0.5 */
+ }
+ }
+
+ Reorder_isf(isf_q, ISF_GAP, ORDER);
+
+ return;
+}
+
+
+/***************************************************************************
+* Function: Reorder_isf() *
+* *
+* Description: To make sure that the isfs are properly order and to *
+* keep a certain minimum distance between consecutive isfs. *
+*--------------------------------------------------------------------------*
+* Argument description in/out *
+* *
+* isf[] vector of isfs i/o *
+* min_dist minimum required distance i *
+* n LPC order i *
+****************************************************************************/
+
+void Reorder_isf(
+ Word16 * isf, /* (i/o) Q15: ISF in the frequency domain (0..0.5) */
+ Word16 min_dist, /* (i) Q15 : minimum distance to keep */
+ Word16 n /* (i) : number of ISF */
+ )
+{
+ Word32 i;
+ Word16 isf_min;
+
+ isf_min = min_dist;
+ for (i = 0; i < n - 1; i++)
+ {
+ if(isf[i] < isf_min)
+ {
+ isf[i] = isf_min;
+ }
+ isf_min = (isf[i] + min_dist);
+ }
+ return;
+}
+
+
+Word16 Sub_VQ( /* output: return quantization index */
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word32 * distance /* output: error of quantization */
+ )
+{
+ Word16 temp, *p_dico;
+ Word32 i, j, index;
+ Word32 dist_min, dist;
+
+ dist_min = MAX_32;
+ p_dico = dico;
+
+ index = 0;
+ for (i = 0; i < dico_size; i++)
+ {
+ dist = 0;
+
+ for (j = 0; j < dim; j++)
+ {
+ temp = x[j] - (*p_dico++);
+ dist += (temp * temp)<<1;
+ }
+
+ if(dist < dist_min)
+ {
+ dist_min = dist;
+ index = i;
+ }
+ }
+
+ *distance = dist_min;
+
+ /* Reading the selected vector */
+ p_dico = &dico[index * dim];
+ for (j = 0; j < dim; j++)
+ {
+ x[j] = *p_dico++;
+ }
+
+ return index;
+}
+
+
+static void VQ_stage1(
+ Word16 * x, /* input : ISF residual vector */
+ Word16 * dico, /* input : quantization codebook */
+ Word16 dim, /* input : dimention of vector */
+ Word16 dico_size, /* input : size of quantization codebook */
+ Word16 * index, /* output: indices of survivors */
+ Word16 surv /* input : number of survivor */
+ )
+{
+ Word16 temp, *p_dico;
+ Word32 i, j, k, l;
+ Word32 dist_min[N_SURV_MAX], dist;
+
+ dist_min[0] = MAX_32;
+ dist_min[1] = MAX_32;
+ dist_min[2] = MAX_32;
+ dist_min[3] = MAX_32;
+ index[0] = 0;
+ index[1] = 1;
+ index[2] = 2;
+ index[3] = 3;
+
+ p_dico = dico;
+
+ for (i = 0; i < dico_size; i++)
+ {
+ dist = 0;
+ for (j = 0; j < dim; j++)
+ {
+ temp = x[j] - (*p_dico++);
+ dist += (temp * temp)<<1;
+ }
+
+ for (k = 0; k < surv; k++)
+ {
+ if(dist < dist_min[k])
+ {
+ for (l = surv - 1; l > k; l--)
+ {
+ dist_min[l] = dist_min[l - 1];
+ index[l] = index[l - 1];
+ }
+ dist_min[k] = dist;
+ index[k] = i;
+ break;
+ }
+ }
+ }
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/random.c b/media/libstagefright/codecs/amrwbenc/src/random.c
new file mode 100644
index 0000000..8baa8bf
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/random.c
@@ -0,0 +1,33 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: random.c *
+* *
+* Description: Signed 16 bits random generator *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+Word16 Random(Word16 * seed)
+{
+ /* static Word16 seed = 21845; */
+ *seed = (Word16)(L_add((L_mult(*seed, 31821) >> 1), 13849L));
+ return (*seed);
+}
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/residu.c b/media/libstagefright/codecs/amrwbenc/src/residu.c
new file mode 100644
index 0000000..6829882
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/residu.c
@@ -0,0 +1,67 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: residu.c *
+* *
+* Description: Compute the LPC residual by filtering *
+* the input speech through A(z) *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Residu(
+ Word16 a[], /* (i) Q12 : prediction coefficients */
+ Word16 x[], /* (i) : speech (values x[-m..-1] are needed */
+ Word16 y[], /* (o) x2 : residual signal */
+ Word16 lg /* (i) : size of filtering */
+ )
+{
+ Word16 i,*p1, *p2;
+ Word32 s;
+ for (i = 0; i < lg; i++)
+ {
+ p1 = a;
+ p2 = &x[i];
+ s = vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1++), (*p2--));
+ s += vo_mult32((*p1), (*p2));
+
+ s = L_shl2(s, 5);
+ y[i] = extract_h(L_add(s, 0x8000));
+ }
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/scale.c b/media/libstagefright/codecs/amrwbenc/src/scale.c
new file mode 100644
index 0000000..af40121
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/scale.c
@@ -0,0 +1,57 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: scale.c *
+* *
+* Description: Scale signal to get maximum of dynamic *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Scale_sig(
+ Word16 x[], /* (i/o) : signal to scale */
+ Word16 lg, /* (i) : size of x[] */
+ Word16 exp /* (i) : exponent: x = round(x << exp) */
+ )
+{
+ Word32 i;
+ Word32 L_tmp;
+ if(exp > 0)
+ {
+ for (i = lg - 1 ; i >= 0; i--)
+ {
+ L_tmp = L_shl2(x[i], 16 + exp);
+ x[i] = extract_h(L_add(L_tmp, 0x8000));
+ }
+ }
+ else
+ {
+ exp = -exp;
+ for (i = lg - 1; i >= 0; i--)
+ {
+ L_tmp = x[i] << 16;
+ L_tmp >>= exp;
+ x[i] = (L_tmp + 0x8000)>>16;
+ }
+ }
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/stream.c b/media/libstagefright/codecs/amrwbenc/src/stream.c
new file mode 100644
index 0000000..a708235
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/stream.c
@@ -0,0 +1,58 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: stream.c *
+* *
+* Description: VOME API Buffer Operator Implement Code *
+* *
+************************************************************************/
+
+#include "stream.h"
+
+void voAWB_InitFrameBuffer(FrameStream *stream)
+{
+ stream->set_ptr = NULL;
+ stream->frame_ptr_bk = stream->frame_ptr;
+ stream->set_len = 0;
+ stream->framebuffer_len = 0;
+ stream->frame_storelen = 0;
+}
+
+void voAWB_UpdateFrameBuffer(
+ FrameStream *stream,
+ VO_MEM_OPERATOR *pMemOP
+ )
+{
+ int len;
+ len = MIN(Frame_Maxsize - stream->frame_storelen, stream->set_len);
+ pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk + stream->frame_storelen , stream->set_ptr, len);
+ stream->set_len -= len;
+ stream->set_ptr += len;
+ stream->framebuffer_len = stream->frame_storelen + len;
+ stream->frame_ptr = stream->frame_ptr_bk;
+ stream->used_len += len;
+}
+
+void voAWB_FlushFrameBuffer(FrameStream *stream)
+{
+ stream->set_ptr = NULL;
+ stream->frame_ptr_bk = stream->frame_ptr;
+ stream->set_len = 0;
+ stream->framebuffer_len = 0;
+ stream->frame_storelen = 0;
+}
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/syn_filt.c b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c
new file mode 100644
index 0000000..6c1fb8e
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/syn_filt.c
@@ -0,0 +1,160 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: syn_filt.c *
+* *
+* Description: Do the synthesis filtering 1/A(z) *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "cnst.h"
+
+void Syn_filt(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 x[], /* (i) : input signal */
+ Word16 y[], /* (o) : output signal */
+ Word16 lg, /* (i) : size of filtering */
+ Word16 mem[], /* (i/o) : memory associated with this filtering. */
+ Word16 update /* (i) : 0=no update, 1=update of memory. */
+ )
+{
+ Word32 i, a0;
+ Word16 y_buf[L_SUBFR16k + M16k];
+ Word32 L_tmp;
+ Word16 *yy, *p1, *p2;
+ yy = &y_buf[0];
+ /* copy initial filter states into synthesis buffer */
+ for (i = 0; i < 16; i++)
+ {
+ *yy++ = mem[i];
+ }
+ a0 = (a[0] >> 1); /* input / 2 */
+ /* Do the filtering. */
+ for (i = 0; i < lg; i++)
+ {
+ p1 = &a[1];
+ p2 = &yy[i-1];
+ L_tmp = vo_mult32(a0, x[i]);
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1++), (*p2--));
+ L_tmp -= vo_mult32((*p1), (*p2));
+
+ L_tmp = L_shl2(L_tmp, 4);
+ y[i] = yy[i] = extract_h(L_add(L_tmp, 0x8000));
+ }
+ /* Update memory if required */
+ if (update)
+ for (i = 0; i < 16; i++)
+ {
+ mem[i] = yy[lg - 16 + i];
+ }
+ return;
+}
+
+
+void Syn_filt_32(
+ Word16 a[], /* (i) Q12 : a[m+1] prediction coefficients */
+ Word16 m, /* (i) : order of LP filter */
+ Word16 exc[], /* (i) Qnew: excitation (exc[i] >> Qnew) */
+ Word16 Qnew, /* (i) : exc scaling = 0(min) to 8(max) */
+ Word16 sig_hi[], /* (o) /16 : synthesis high */
+ Word16 sig_lo[], /* (o) /16 : synthesis low */
+ Word16 lg /* (i) : size of filtering */
+ )
+{
+ Word32 i,a0;
+ Word32 L_tmp, L_tmp1;
+ Word16 *p1, *p2, *p3;
+ a0 = a[0] >> (4 + Qnew); /* input / 16 and >>Qnew */
+ /* Do the filtering. */
+ for (i = 0; i < lg; i++)
+ {
+ L_tmp = 0;
+ L_tmp1 = 0;
+ p1 = a;
+ p2 = &sig_lo[i - 1];
+ p3 = &sig_hi[i - 1];
+
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+ L_tmp -= vo_mult32((*p2--), (*p1));
+ L_tmp1 -= vo_mult32((*p3--), (*p1++));
+
+ L_tmp = L_tmp >> 11;
+ L_tmp += vo_L_mult(exc[i], a0);
+
+ /* sig_hi = bit16 to bit31 of synthesis */
+ L_tmp = L_tmp - (L_tmp1<<1);
+
+ L_tmp = L_tmp >> 3; /* ai in Q12 */
+ sig_hi[i] = extract_h(L_tmp);
+
+ /* sig_lo = bit4 to bit15 of synthesis */
+ L_tmp >>= 4; /* 4 : sig_lo[i] >> 4 */
+ sig_lo[i] = (Word16)((L_tmp - (sig_hi[i] << 13)));
+ }
+
+ return;
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/updt_tar.c b/media/libstagefright/codecs/amrwbenc/src/updt_tar.c
new file mode 100644
index 0000000..f3e5650
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/updt_tar.c
@@ -0,0 +1,49 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: updt_tar.c *
+* *
+* Description: Update the target vector for codebook search *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Updt_tar(
+ Word16 * x, /* (i) Q0 : old target (for pitch search) */
+ Word16 * x2, /* (o) Q0 : new target (for codebook search) */
+ Word16 * y, /* (i) Q0 : filtered adaptive codebook vector */
+ Word16 gain, /* (i) Q14 : adaptive codebook gain */
+ Word16 L /* (i) : subframe size */
+ )
+{
+ Word32 i;
+ Word32 L_tmp;
+
+ for (i = 0; i < L; i++)
+ {
+ L_tmp = x[i] << 15;
+ L_tmp -= (y[i] * gain)<<1;
+ x2[i] = extract_h(L_shl2(L_tmp, 1));
+ }
+
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/util.c b/media/libstagefright/codecs/amrwbenc/src/util.c
new file mode 100644
index 0000000..78141dd
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/util.c
@@ -0,0 +1,74 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: util.c *
+* *
+* Description: Reset and Copy buffer *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+/***********************************************************************
+* Function: Set_zero() *
+* Description: Set vector x[] to zero *
+************************************************************************/
+
+void Set_zero(
+ Word16 x[], /* (o) : vector to clear */
+ Word16 L /* (i) : length of vector */
+ )
+{
+ Word32 num = (Word32)L;
+ do{
+ *x++ = 0;
+ }while(--num !=0);
+}
+
+
+/*********************************************************************
+* Function: Copy() *
+* *
+* Description: Copy vector x[] to y[] *
+*********************************************************************/
+
+void Copy(
+ Word16 x[], /* (i) : input vector */
+ Word16 y[], /* (o) : output vector */
+ Word16 L /* (i) : vector length */
+ )
+{
+ Word32 temp1,temp2,num;
+ if(L&1)
+ {
+ temp1 = *x++;
+ *y++ = temp1;
+ }
+ num = (Word32)(L>>1);
+ temp1 = *x++;
+ temp2 = *x++;
+ do{
+ *y++ = temp1;
+ *y++ = temp2;
+ temp1 = *x++;
+ temp2 = *x++;
+ }while(--num!=0);
+}
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c
new file mode 100644
index 0000000..d0d99a7
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/voAMRWBEnc.c
@@ -0,0 +1,1941 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voAMRWBEnc.c *
+* *
+* Description: Performs the main encoder routine *
+* Fixed-point C simulation of AMR WB ACELP coding *
+* algorithm with 20 msspeech frames for *
+* wideband speech signals. *
+* *
+************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "typedef.h"
+#include "basic_op.h"
+#include "oper_32b.h"
+#include "math_op.h"
+#include "cnst.h"
+#include "acelp.h"
+#include "cod_main.h"
+#include "bits.h"
+#include "main.h"
+#include "voAMRWB.h"
+#include "mem_align.h"
+#include "cmnMemory.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */
+static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767};
+
+/* isp tables for initialization */
+static Word16 isp_init[M] =
+{
+ 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0,
+ -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475
+};
+
+static Word16 isf_init[M] =
+{
+ 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192,
+ 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840
+};
+
+/* High Band encoding */
+static const Word16 HP_gain[16] =
+{
+ 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264,
+ 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728
+};
+
+/* Private function declaration */
+static Word16 synthesis(
+ Word16 Aq[], /* A(z) : quantized Az */
+ Word16 exc[], /* (i) : excitation at 12kHz */
+ Word16 Q_new, /* (i) : scaling performed on exc */
+ Word16 synth16k[], /* (o) : 16kHz synthesis signal */
+ Coder_State * st /* (i/o) : State structure */
+ );
+
+/* Codec some parameters initialization */
+void Reset_encoder(void *st, Word16 reset_all)
+{
+ Word16 i;
+ Coder_State *cod_state;
+ cod_state = (Coder_State *) st;
+ Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL);
+ Set_zero(cod_state->mem_syn, M);
+ Set_zero(cod_state->past_isfq, M);
+ cod_state->mem_w0 = 0;
+ cod_state->tilt_code = 0;
+ cod_state->first_frame = 1;
+ Init_gp_clip(cod_state->gp_clip);
+ cod_state->L_gc_thres = 0;
+ if (reset_all != 0)
+ {
+ /* Static vectors to zero */
+ Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME);
+ Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM));
+ Set_zero(cod_state->mem_decim2, 3);
+ /* routines initialization */
+ Init_Decim_12k8(cod_state->mem_decim);
+ Init_HP50_12k8(cod_state->mem_sig_in);
+ Init_Levinson(cod_state->mem_levinson);
+ Init_Q_gain2(cod_state->qua_gain);
+ Init_Hp_wsp(cod_state->hp_wsp_mem);
+ /* isp initialization */
+ Copy(isp_init, cod_state->ispold, M);
+ Copy(isp_init, cod_state->ispold_q, M);
+ /* variable initialization */
+ cod_state->mem_preemph = 0;
+ cod_state->mem_wsp = 0;
+ cod_state->Q_old = 15;
+ cod_state->Q_max[0] = 15;
+ cod_state->Q_max[1] = 15;
+ cod_state->old_wsp_max = 0;
+ cod_state->old_wsp_shift = 0;
+ /* pitch ol initialization */
+ cod_state->old_T0_med = 40;
+ cod_state->ol_gain = 0;
+ cod_state->ada_w = 0;
+ cod_state->ol_wght_flg = 0;
+ for (i = 0; i < 5; i++)
+ {
+ cod_state->old_ol_lag[i] = 40;
+ }
+ Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM));
+ Set_zero(cod_state->mem_syn_hf, M);
+ Set_zero(cod_state->mem_syn_hi, M);
+ Set_zero(cod_state->mem_syn_lo, M);
+ Init_HP50_12k8(cod_state->mem_sig_out);
+ Init_Filt_6k_7k(cod_state->mem_hf);
+ Init_HP400_12k8(cod_state->mem_hp400);
+ Copy(isf_init, cod_state->isfold, M);
+ cod_state->mem_deemph = 0;
+ cod_state->seed2 = 21845;
+ Init_Filt_6k_7k(cod_state->mem_hf2);
+ cod_state->gain_alpha = 32767;
+ cod_state->vad_hist = 0;
+ wb_vad_reset(cod_state->vadSt);
+ dtx_enc_reset(cod_state->dtx_encSt, isf_init);
+ }
+ return;
+}
+
+/*-----------------------------------------------------------------*
+* Funtion coder *
+* ~~~~~ *
+* ->Main coder routine. *
+* *
+*-----------------------------------------------------------------*/
+void coder(
+ Word16 * mode, /* input : used mode */
+ Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */
+ Word16 prms[], /* output: output parameters */
+ Word16 * ser_size, /* output: bit rate of the used mode */
+ void *spe_state, /* i/o : State structure */
+ Word16 allow_dtx /* input : DTX ON/OFF */
+ )
+{
+ /* Coder states */
+ Coder_State *st;
+ /* Speech vector */
+ Word16 old_speech[L_TOTAL];
+ Word16 *new_speech, *speech, *p_window;
+
+ /* Weighted speech vector */
+ Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)];
+ Word16 *wsp;
+
+ /* Excitation vector */
+ Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL];
+ Word16 *exc;
+
+ /* LPC coefficients */
+ Word16 r_h[M + 1], r_l[M + 1]; /* Autocorrelations of windowed speech */
+ Word16 rc[M]; /* Reflection coefficients. */
+ Word16 Ap[M + 1]; /* A(z) with spectral expansion */
+ Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */
+ Word16 ispnew_q[M]; /* quantized ISPs at 4nd subframe */
+ Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */
+ Word16 *p_A, *p_Aq; /* ptr to A(z) for the 4 subframes */
+ Word16 A[NB_SUBFR * (M + 1)]; /* A(z) unquantized for the 4 subframes */
+ Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */
+
+ /* Other vectors */
+ Word16 xn[L_SUBFR]; /* Target vector for pitch search */
+ Word16 xn2[L_SUBFR]; /* Target vector for codebook search */
+ Word16 dn[L_SUBFR]; /* Correlation between xn2 and h1 */
+ Word16 cn[L_SUBFR]; /* Target vector in residual domain */
+ Word16 h1[L_SUBFR]; /* Impulse response vector */
+ Word16 h2[L_SUBFR]; /* Impulse response vector */
+ Word16 code[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */
+ Word16 error[M + L_SUBFR]; /* error of quantization */
+ Word16 synth[L_SUBFR]; /* 12.8kHz synthesis vector */
+ Word16 exc2[L_FRAME]; /* excitation vector */
+ Word16 buf[L_FRAME]; /* VAD buffer */
+
+ /* Scalars */
+ Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag;
+ Word16 codec_mode;
+ Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index;
+ Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4];
+ Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max;
+ Word16 voice_fac;
+ Word16 indice[8];
+ Word32 L_tmp, L_gain_code, L_max, L_tmp1;
+ Word16 code2[L_SUBFR]; /* Fixed codebook excitation */
+ Word16 stab_fac, fac, gain_code_lo;
+
+ Word16 corr_gain;
+ Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3;
+
+ st = (Coder_State *) spe_state;
+
+ *ser_size = nb_of_bits[*mode];
+ codec_mode = *mode;
+
+ /*--------------------------------------------------------------------------*
+ * Initialize pointers to speech vector. *
+ * *
+ * *
+ * |-------|-------|-------|-------|-------|-------| *
+ * past sp sf1 sf2 sf3 sf4 L_NEXT *
+ * <------- Total speech buffer (L_TOTAL) ------> *
+ * old_speech *
+ * <------- LPC analysis window (L_WINDOW) ------> *
+ * | <-- present frame (L_FRAME) ----> *
+ * p_window | <----- new speech (L_FRAME) ----> *
+ * | | *
+ * speech | *
+ * new_speech *
+ *--------------------------------------------------------------------------*/
+
+ new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT; /* New speech */
+ speech = old_speech + L_TOTAL - L_FRAME - L_NEXT; /* Present frame */
+ p_window = old_speech + L_TOTAL - L_WINDOW;
+
+ exc = old_exc + PIT_MAX + L_INTERPOL;
+ wsp = old_wsp + (PIT_MAX / OPL_DECIM);
+
+ /* copy coder memory state into working space */
+ Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME);
+ Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM);
+ Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL);
+
+ /*---------------------------------------------------------------*
+ * Down sampling signal from 16kHz to 12.8kHz *
+ * -> The signal is extended by L_FILT samples (padded to zero) *
+ * to avoid additional delay (L_FILT samples) in the coder. *
+ * The last L_FILT samples are approximated after decimation and *
+ * are used (and windowed) only in autocorrelations. *
+ *---------------------------------------------------------------*/
+
+ Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim);
+
+ /* last L_FILT samples for autocorrelation window */
+ Copy(st->mem_decim, code, 2 * L_FILT16k);
+ Set_zero(error, L_FILT16k); /* set next sample to zero */
+ Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code);
+
+ /*---------------------------------------------------------------*
+ * Perform 50Hz HP filtering of input signal. *
+ *---------------------------------------------------------------*/
+
+ HP50_12k8(new_speech, L_FRAME, st->mem_sig_in);
+
+ /* last L_FILT samples for autocorrelation window */
+ Copy(st->mem_sig_in, code, 6);
+ HP50_12k8(new_speech + L_FRAME, L_FILT, code);
+
+ /*---------------------------------------------------------------*
+ * Perform fixed preemphasis through 1 - g z^-1 *
+ * Scale signal to get maximum of precision in filtering *
+ *---------------------------------------------------------------*/
+
+ mu = PREEMPH_FAC >> 1; /* Q15 --> Q14 */
+
+ /* get max of new preemphased samples (L_FRAME+L_FILT) */
+ L_tmp = new_speech[0] << 15;
+ L_tmp -= (st->mem_preemph * mu)<<1;
+ L_max = L_abs(L_tmp);
+
+ for (i = 1; i < L_FRAME + L_FILT; i++)
+ {
+ L_tmp = new_speech[i] << 15;
+ L_tmp -= (new_speech[i - 1] * mu)<<1;
+ L_tmp = L_abs(L_tmp);
+ if(L_tmp > L_max)
+ {
+ L_max = L_tmp;
+ }
+ }
+
+ /* get scaling factor for new and previous samples */
+ /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */
+ /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */
+ tmp = extract_h(L_max);
+ if (tmp == 0)
+ {
+ shift = Q_MAX;
+ } else
+ {
+ shift = norm_s(tmp) - 1;
+ if (shift < 0)
+ {
+ shift = 0;
+ }
+ if (shift > Q_MAX)
+ {
+ shift = Q_MAX;
+ }
+ }
+ Q_new = shift;
+ if (Q_new > st->Q_max[0])
+ {
+ Q_new = st->Q_max[0];
+ }
+ if (Q_new > st->Q_max[1])
+ {
+ Q_new = st->Q_max[1];
+ }
+ exp = (Q_new - st->Q_old);
+ st->Q_old = Q_new;
+ st->Q_max[1] = st->Q_max[0];
+ st->Q_max[0] = shift;
+
+ /* preemphasis with scaling (L_FRAME+L_FILT) */
+ tmp = new_speech[L_FRAME - 1];
+
+ for (i = L_FRAME + L_FILT - 1; i > 0; i--)
+ {
+ L_tmp = new_speech[i] << 15;
+ L_tmp -= (new_speech[i - 1] * mu)<<1;
+ L_tmp = (L_tmp << Q_new);
+ new_speech[i] = vo_round(L_tmp);
+ }
+
+ L_tmp = new_speech[0] << 15;
+ L_tmp -= (st->mem_preemph * mu)<<1;
+ L_tmp = (L_tmp << Q_new);
+ new_speech[0] = vo_round(L_tmp);
+
+ st->mem_preemph = tmp;
+
+ /* scale previous samples and memory */
+
+ Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp);
+ Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp);
+ Scale_sig(st->mem_syn, M, exp);
+ Scale_sig(st->mem_decim2, 3, exp);
+ Scale_sig(&(st->mem_wsp), 1, exp);
+ Scale_sig(&(st->mem_w0), 1, exp);
+
+ /*------------------------------------------------------------------------*
+ * Call VAD *
+ * Preemphesis scale down signal in low frequency and keep dynamic in HF.*
+ * Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT). *
+ *------------------------------------------------------------------------*/
+ Copy(new_speech, buf, L_FRAME);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Scale_sig_opt(buf, L_FRAME, 1 - Q_new);
+#else
+ Scale_sig(buf, L_FRAME, 1 - Q_new);
+#endif
+
+ vad_flag = wb_vad(st->vadSt, buf); /* Voice Activity Detection */
+ if (vad_flag == 0)
+ {
+ st->vad_hist = (st->vad_hist + 1);
+ } else
+ {
+ st->vad_hist = 0;
+ }
+
+ /* DTX processing */
+ if (allow_dtx != 0)
+ {
+ /* Note that mode may change here */
+ tx_dtx_handler(st->dtx_encSt, vad_flag, mode);
+ *ser_size = nb_of_bits[*mode];
+ }
+
+ if(*mode != MRDTX)
+ {
+ Parm_serial(vad_flag, 1, &prms);
+ }
+ /*------------------------------------------------------------------------*
+ * Perform LPC analysis *
+ * ~~~~~~~~~~~~~~~~~~~~ *
+ * - autocorrelation + lag windowing *
+ * - Levinson-durbin algorithm to find a[] *
+ * - convert a[] to isp[] *
+ * - convert isp[] to isf[] for quantization *
+ * - quantize and code the isf[] *
+ * - convert isf[] to isp[] for interpolation *
+ * - find the interpolated ISPs and convert to a[] for the 4 subframes *
+ *------------------------------------------------------------------------*/
+
+ /* LP analysis centered at 4nd subframe */
+ Autocorr(p_window, M, r_h, r_l); /* Autocorrelations */
+ Lag_window(r_h, r_l); /* Lag windowing */
+ Levinson(r_h, r_l, A, rc, st->mem_levinson); /* Levinson Durbin */
+ Az_isp(A, ispnew, st->ispold); /* From A(z) to ISP */
+
+ /* Find the interpolated ISPs and convert to a[] for all subframes */
+ Int_isp(st->ispold, ispnew, interpol_frac, A);
+
+ /* update ispold[] for the next frame */
+ Copy(ispnew, st->ispold, M);
+
+ /* Convert ISPs to frequency domain 0..6400 */
+ Isp_isf(ispnew, isf, M);
+
+ /* check resonance for pitch clipping algorithm */
+ Gp_clip_test_isf(isf, st->gp_clip);
+
+ /*----------------------------------------------------------------------*
+ * Perform PITCH_OL analysis *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * - Find the residual res[] for the whole speech frame *
+ * - Find the weighted input speech wsp[] for the whole speech frame *
+ * - scale wsp[] to avoid overflow in pitch estimation *
+ * - Find open loop pitch lag for whole speech frame *
+ *----------------------------------------------------------------------*/
+ p_A = A;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ /* Weighting of LPC coefficients */
+ Weight_a(p_A, Ap, GAMMA1, M);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
+#else
+ Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR);
+#endif
+
+ p_A += (M + 1);
+ }
+
+ Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp));
+
+ /* find maximum value on wsp[] for 12 bits scaling */
+ max = 0;
+ for (i = 0; i < L_FRAME; i++)
+ {
+ tmp = abs_s(wsp[i]);
+ if(tmp > max)
+ {
+ max = tmp;
+ }
+ }
+ tmp = st->old_wsp_max;
+ if(max > tmp)
+ {
+ tmp = max; /* tmp = max(wsp_max, old_wsp_max) */
+ }
+ st->old_wsp_max = max;
+
+ shift = norm_s(tmp) - 3;
+ if (shift > 0)
+ {
+ shift = 0; /* shift = 0..-3 */
+ }
+ /* decimation of wsp[] to search pitch in LF and to reduce complexity */
+ LP_Decim2(wsp, L_FRAME, st->mem_decim2);
+
+ /* scale wsp[] in 12 bits to avoid overflow */
+#ifdef ASM_OPT /* asm optimization branch */
+ Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift);
+#else
+ Scale_sig(wsp, L_FRAME / OPL_DECIM, shift);
+#endif
+ /* scale old_wsp (warning: exp must be Q_new-Q_old) */
+ exp = exp + (shift - st->old_wsp_shift);
+ st->old_wsp_shift = shift;
+
+ Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp);
+ Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp);
+
+ scale_mem_Hp_wsp(st->hp_wsp_mem, exp);
+
+ /* Find open loop pitch lag for whole speech frame */
+
+ if(*ser_size == NBBITS_7k)
+ {
+ /* Find open loop pitch lag for whole speech frame */
+ T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM);
+ } else
+ {
+ /* Find open loop pitch lag for first 1/2 frame */
+ T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM);
+ }
+
+ if(st->ol_gain > 19661) /* 0.6 in Q15 */
+ {
+ st->old_T0_med = Med_olag(T_op, st->old_ol_lag);
+ st->ada_w = 32767;
+ } else
+ {
+ st->ada_w = vo_mult(st->ada_w, 29491);
+ }
+
+ if(st->ada_w < 26214)
+ st->ol_wght_flg = 0;
+ else
+ st->ol_wght_flg = 1;
+
+ wb_vad_tone_detection(st->vadSt, st->ol_gain);
+ T_op *= OPL_DECIM;
+
+ if(*ser_size != NBBITS_7k)
+ {
+ /* Find open loop pitch lag for second 1/2 frame */
+ T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM);
+
+ if(st->ol_gain > 19661) /* 0.6 in Q15 */
+ {
+ st->old_T0_med = Med_olag(T_op2, st->old_ol_lag);
+ st->ada_w = 32767;
+ } else
+ {
+ st->ada_w = mult(st->ada_w, 29491);
+ }
+
+ if(st->ada_w < 26214)
+ st->ol_wght_flg = 0;
+ else
+ st->ol_wght_flg = 1;
+
+ wb_vad_tone_detection(st->vadSt, st->ol_gain);
+
+ T_op2 *= OPL_DECIM;
+
+ } else
+ {
+ T_op2 = T_op;
+ }
+ /*----------------------------------------------------------------------*
+ * DTX-CNG *
+ *----------------------------------------------------------------------*/
+ if(*mode == MRDTX) /* CNG mode */
+ {
+ /* Buffer isf's and energy */
+#ifdef ASM_OPT /* asm optimization branch */
+ Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME);
+#else
+ Residu(&A[3 * (M + 1)], speech, exc, L_FRAME);
+#endif
+
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = shr(exc[i], Q_new);
+ }
+
+ L_tmp = 0;
+ for (i = 0; i < L_FRAME; i++)
+ L_tmp += (exc2[i] * exc2[i])<<1;
+
+ L_tmp >>= 1;
+
+ dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
+
+ /* Quantize and code the ISFs */
+ dtx_enc(st->dtx_encSt, isf, exc2, &prms);
+
+ /* Convert ISFs to the cosine domain */
+ Isf_isp(isf, ispnew_q, M);
+ Isp_Az(ispnew_q, Aq, M, 0);
+
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st);
+ }
+ Copy(isf, st->isfold, M);
+
+ /* reset speech coder memories */
+ Reset_encoder(st, 0);
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> save past of speech[] and wsp[]. *
+ *--------------------------------------------------*/
+
+ Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
+ Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
+
+ return;
+ }
+ /*----------------------------------------------------------------------*
+ * ACELP *
+ *----------------------------------------------------------------------*/
+
+ /* Quantize and code the ISFs */
+
+ if (*ser_size <= NBBITS_7k)
+ {
+ Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4);
+
+ Parm_serial(indice[0], 8, &prms);
+ Parm_serial(indice[1], 8, &prms);
+ Parm_serial(indice[2], 7, &prms);
+ Parm_serial(indice[3], 7, &prms);
+ Parm_serial(indice[4], 6, &prms);
+ } else
+ {
+ Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4);
+
+ Parm_serial(indice[0], 8, &prms);
+ Parm_serial(indice[1], 8, &prms);
+ Parm_serial(indice[2], 6, &prms);
+ Parm_serial(indice[3], 7, &prms);
+ Parm_serial(indice[4], 7, &prms);
+ Parm_serial(indice[5], 5, &prms);
+ Parm_serial(indice[6], 5, &prms);
+ }
+
+ /* Check stability on isf : distance between old isf and current isf */
+
+ L_tmp = 0;
+ for (i = 0; i < M - 1; i++)
+ {
+ tmp = vo_sub(isf[i], st->isfold[i]);
+ L_tmp += (tmp * tmp)<<1;
+ }
+
+ tmp = extract_h(L_shl2(L_tmp, 8));
+
+ tmp = vo_mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */
+ tmp = vo_sub(20480, tmp); /* 1.25 - tmp (in Q14) */
+
+ stab_fac = shl(tmp, 1);
+
+ if (stab_fac < 0)
+ {
+ stab_fac = 0;
+ }
+ Copy(isf, st->isfold, M);
+
+ /* Convert ISFs to the cosine domain */
+ Isf_isp(isf, ispnew_q, M);
+
+ if (st->first_frame != 0)
+ {
+ st->first_frame = 0;
+ Copy(ispnew_q, st->ispold_q, M);
+ }
+ /* Find the interpolated ISPs and convert to a[] for all subframes */
+
+ Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq);
+
+ /* update ispold[] for the next frame */
+ Copy(ispnew_q, st->ispold_q, M);
+
+ p_Aq = Aq;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+#ifdef ASM_OPT /* asm optimization branch */
+ Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
+#else
+ Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
+#endif
+ p_Aq += (M + 1);
+ }
+
+ /* Buffer isf's and energy for dtx on non-speech frame */
+ if (vad_flag == 0)
+ {
+ for (i = 0; i < L_FRAME; i++)
+ {
+ exc2[i] = exc[i] >> Q_new;
+ }
+ L_tmp = 0;
+ for (i = 0; i < L_FRAME; i++)
+ L_tmp += (exc2[i] * exc2[i])<<1;
+ L_tmp >>= 1;
+
+ dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode);
+ }
+ /* range for closed loop pitch search in 1st subframe */
+
+ T0_min = T_op - 8;
+ if (T0_min < PIT_MIN)
+ {
+ T0_min = PIT_MIN;
+ }
+ T0_max = (T0_min + 15);
+
+ if(T0_max > PIT_MAX)
+ {
+ T0_max = PIT_MAX;
+ T0_min = T0_max - 15;
+ }
+ /*------------------------------------------------------------------------*
+ * Loop for every subframe in the analysis frame *
+ *------------------------------------------------------------------------*
+ * To find the pitch and innovation parameters. The subframe size is *
+ * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. *
+ * - compute the target signal for pitch search *
+ * - compute impulse response of weighted synthesis filter (h1[]) *
+ * - find the closed-loop pitch parameters *
+ * - encode the pitch dealy *
+ * - find 2 lt prediction (with / without LP filter for lt pred) *
+ * - find 2 pitch gains and choose the best lt prediction. *
+ * - find target vector for codebook search *
+ * - update the impulse response h1[] for codebook search *
+ * - correlation between target vector and impulse response *
+ * - codebook search and encoding *
+ * - VQ of pitch and codebook gains *
+ * - find voicing factor and tilt of code for next subframe. *
+ * - update states of weighting filter *
+ * - find excitation and synthesis speech *
+ *------------------------------------------------------------------------*/
+ p_A = A;
+ p_Aq = Aq;
+ for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR)
+ {
+ pit_flag = i_subfr;
+ if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k))
+ {
+ pit_flag = 0;
+ /* range for closed loop pitch search in 3rd subframe */
+ T0_min = (T_op2 - 8);
+
+ if (T0_min < PIT_MIN)
+ {
+ T0_min = PIT_MIN;
+ }
+ T0_max = (T0_min + 15);
+ if (T0_max > PIT_MAX)
+ {
+ T0_max = PIT_MAX;
+ T0_min = (T0_max - 15);
+ }
+ }
+ /*-----------------------------------------------------------------------*
+ * *
+ * Find the target vector for pitch search: *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
+ * *
+ * |------| res[n] *
+ * speech[n]---| A(z) |-------- *
+ * |------| | |--------| error[n] |------| *
+ * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target *
+ * exc |--------| |------| *
+ * *
+ * Instead of subtracting the zero-input response of filters from *
+ * the weighted input speech, the above configuration is used to *
+ * compute the target vector. *
+ * *
+ *-----------------------------------------------------------------------*/
+
+ for (i = 0; i < M; i++)
+ {
+ error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]);
+ }
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
+#else
+ Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR);
+#endif
+ Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0);
+ Weight_a(p_A, Ap, GAMMA1, M);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Residu_opt(Ap, error + M, xn, L_SUBFR);
+#else
+ Residu(Ap, error + M, xn, L_SUBFR);
+#endif
+ Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0));
+
+ /*----------------------------------------------------------------------*
+ * Find approx. target in residual domain "cn[]" for inovation search. *
+ *----------------------------------------------------------------------*/
+ /* first half: xn[] --> cn[] */
+ Set_zero(code, M);
+ Copy(xn, code + M, L_SUBFR / 2);
+ tmp = 0;
+ Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp);
+ Weight_a(p_A, Ap, GAMMA1, M);
+ Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2);
+#else
+ Residu(p_Aq,code + M, cn, L_SUBFR / 2);
+#endif
+
+ /* second half: res[] --> cn[] (approximated and faster) */
+ Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2);
+
+ /*---------------------------------------------------------------*
+ * Compute impulse response, h1[], of weighted synthesis filter *
+ *---------------------------------------------------------------*/
+
+ Set_zero(error, M + L_SUBFR);
+ Weight_a(p_A, error + M, GAMMA1, M);
+
+ vo_p0 = error+M;
+ vo_p3 = h1;
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = *vo_p0 << 14; /* x4 (Q12 to Q14) */
+ vo_p1 = p_Aq + 1;
+ vo_p2 = vo_p0-1;
+ for (j = 1; j <= M/4; j++)
+ {
+ L_tmp -= *vo_p1++ * *vo_p2--;
+ L_tmp -= *vo_p1++ * *vo_p2--;
+ L_tmp -= *vo_p1++ * *vo_p2--;
+ L_tmp -= *vo_p1++ * *vo_p2--;
+ }
+ *vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4));
+ }
+ /* deemph without division by 2 -> Q14 to Q15 */
+ tmp = 0;
+ Deemph2(h1, TILT_FAC, L_SUBFR, &tmp); /* h1 in Q14 */
+
+ /* h2 in Q12 for codebook search */
+ Copy(h1, h2, L_SUBFR);
+
+ /*---------------------------------------------------------------*
+ * scale xn[] and h1[] to avoid overflow in dot_product12() *
+ *---------------------------------------------------------------*/
+#ifdef ASM_OPT /* asm optimization branch */
+ Scale_sig_opt(h2, L_SUBFR, -2);
+ Scale_sig_opt(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig_opt(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */
+#else
+ Scale_sig(h2, L_SUBFR, -2);
+ Scale_sig(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */
+ Scale_sig(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */
+#endif
+ /*----------------------------------------------------------------------*
+ * Closed-loop fractional pitch search *
+ *----------------------------------------------------------------------*/
+ /* find closed loop fractional pitch lag */
+ if(*ser_size <= NBBITS_9k)
+ {
+ T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
+ pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR);
+
+ /* encode pitch lag */
+ if (pit_flag == 0) /* if 1st/3rd subframe */
+ {
+ /*--------------------------------------------------------------*
+ * The pitch range for the 1st/3rd subframe is encoded with *
+ * 8 bits and is divided as follows: *
+ * PIT_MIN to PIT_FR1-1 resolution 1/2 (frac = 0 or 2) *
+ * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) *
+ *--------------------------------------------------------------*/
+ if (T0 < PIT_FR1_8b)
+ {
+ index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1));
+ } else
+ {
+ index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2));
+ }
+
+ Parm_serial(index, 8, &prms);
+
+ /* find T0_min and T0_max for subframe 2 and 4 */
+ T0_min = (T0 - 8);
+ if (T0_min < PIT_MIN)
+ {
+ T0_min = PIT_MIN;
+ }
+ T0_max = T0_min + 15;
+ if (T0_max > PIT_MAX)
+ {
+ T0_max = PIT_MAX;
+ T0_min = (T0_max - 15);
+ }
+ } else
+ { /* if subframe 2 or 4 */
+ /*--------------------------------------------------------------*
+ * The pitch range for subframe 2 or 4 is encoded with 5 bits: *
+ * T0_min to T0_max resolution 1/2 (frac = 0 or 2) *
+ *--------------------------------------------------------------*/
+ i = (T0 - T0_min);
+ index = (i << 1) + (T0_frac >> 1);
+
+ Parm_serial(index, 5, &prms);
+ }
+ } else
+ {
+ T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac,
+ pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR);
+
+ /* encode pitch lag */
+ if (pit_flag == 0) /* if 1st/3rd subframe */
+ {
+ /*--------------------------------------------------------------*
+ * The pitch range for the 1st/3rd subframe is encoded with *
+ * 9 bits and is divided as follows: *
+ * PIT_MIN to PIT_FR2-1 resolution 1/4 (frac = 0,1,2 or 3) *
+ * PIT_FR2 to PIT_FR1-1 resolution 1/2 (frac = 0 or 1) *
+ * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) *
+ *--------------------------------------------------------------*/
+
+ if (T0 < PIT_FR2)
+ {
+ index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2);
+ } else if(T0 < PIT_FR1_9b)
+ {
+ index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2));
+ } else
+ {
+ index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1));
+ }
+
+ Parm_serial(index, 9, &prms);
+
+ /* find T0_min and T0_max for subframe 2 and 4 */
+
+ T0_min = (T0 - 8);
+ if (T0_min < PIT_MIN)
+ {
+ T0_min = PIT_MIN;
+ }
+ T0_max = T0_min + 15;
+
+ if (T0_max > PIT_MAX)
+ {
+ T0_max = PIT_MAX;
+ T0_min = (T0_max - 15);
+ }
+ } else
+ { /* if subframe 2 or 4 */
+ /*--------------------------------------------------------------*
+ * The pitch range for subframe 2 or 4 is encoded with 6 bits: *
+ * T0_min to T0_max resolution 1/4 (frac = 0,1,2 or 3) *
+ *--------------------------------------------------------------*/
+ i = (T0 - T0_min);
+ index = (i << 2) + T0_frac;
+ Parm_serial(index, 6, &prms);
+ }
+ }
+
+ /*-----------------------------------------------------------------*
+ * Gain clipping test to avoid unstable synthesis on frame erasure *
+ *-----------------------------------------------------------------*/
+
+ clip_gain = 0;
+ if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746))
+ clip_gain = 1;
+
+ /*-----------------------------------------------------------------*
+ * - find unity gain pitch excitation (adaptive codebook entry) *
+ * with fractional interpolation. *
+ * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) *
+ * - compute pitch gain1 *
+ *-----------------------------------------------------------------*/
+ /* find pitch exitation */
+#ifdef ASM_OPT /* asm optimization branch */
+ pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
+#else
+ Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1);
+#endif
+ if (*ser_size > NBBITS_9k)
+ {
+#ifdef ASM_OPT /* asm optimization branch */
+ Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR);
+#else
+ Convolve(&exc[i_subfr], h1, y1, L_SUBFR);
+#endif
+ gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR);
+ /* clip gain if necessary to avoid problem at decoder */
+ if ((clip_gain != 0) && (gain1 > GP_CLIP))
+ {
+ gain1 = GP_CLIP;
+ }
+ /* find energy of new target xn2[] */
+ Updt_tar(xn, dn, y1, gain1, L_SUBFR); /* dn used temporary */
+ } else
+ {
+ gain1 = 0;
+ }
+ /*-----------------------------------------------------------------*
+ * - find pitch excitation filtered by 1st order LP filter. *
+ * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) *
+ * - compute pitch gain2 *
+ *-----------------------------------------------------------------*/
+ /* find pitch excitation with lp filter */
+ vo_p0 = exc + i_subfr-1;
+ vo_p1 = code;
+ /* find pitch excitation with lp filter */
+ for (i = 0; i < L_SUBFR/2; i++)
+ {
+ L_tmp = 5898 * *vo_p0++;
+ L_tmp1 = 5898 * *vo_p0;
+ L_tmp += 20972 * *vo_p0++;
+ L_tmp1 += 20972 * *vo_p0++;
+ L_tmp1 += 5898 * *vo_p0--;
+ L_tmp += 5898 * *vo_p0;
+ *vo_p1++ = (L_tmp + 0x4000)>>15;
+ *vo_p1++ = (L_tmp1 + 0x4000)>>15;
+ }
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Convolve_asm(code, h1, y2, L_SUBFR);
+#else
+ Convolve(code, h1, y2, L_SUBFR);
+#endif
+
+ gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR);
+
+ /* clip gain if necessary to avoid problem at decoder */
+ if ((clip_gain != 0) && (gain2 > GP_CLIP))
+ {
+ gain2 = GP_CLIP;
+ }
+ /* find energy of new target xn2[] */
+ Updt_tar(xn, xn2, y2, gain2, L_SUBFR);
+ /*-----------------------------------------------------------------*
+ * use the best prediction (minimise quadratic error). *
+ *-----------------------------------------------------------------*/
+ select = 0;
+ if(*ser_size > NBBITS_9k)
+ {
+ L_tmp = 0L;
+ vo_p0 = dn;
+ vo_p1 = xn2;
+ for (i = 0; i < L_SUBFR/2; i++)
+ {
+ L_tmp += *vo_p0 * *vo_p0;
+ vo_p0++;
+ L_tmp -= *vo_p1 * *vo_p1;
+ vo_p1++;
+ L_tmp += *vo_p0 * *vo_p0;
+ vo_p0++;
+ L_tmp -= *vo_p1 * *vo_p1;
+ vo_p1++;
+ }
+
+ if (L_tmp <= 0)
+ {
+ select = 1;
+ }
+ Parm_serial(select, 1, &prms);
+ }
+ if (select == 0)
+ {
+ /* use the lp filter for pitch excitation prediction */
+ gain_pit = gain2;
+ Copy(code, &exc[i_subfr], L_SUBFR);
+ Copy(y2, y1, L_SUBFR);
+ Copy(g_coeff2, g_coeff, 4);
+ } else
+ {
+ /* no filter used for pitch excitation prediction */
+ gain_pit = gain1;
+ Copy(dn, xn2, L_SUBFR); /* target vector for codebook search */
+ }
+ /*-----------------------------------------------------------------*
+ * - update cn[] for codebook search *
+ *-----------------------------------------------------------------*/
+ Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Scale_sig_opt(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */
+#else
+ Scale_sig(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */
+#endif
+ /*-----------------------------------------------------------------*
+ * - include fixed-gain pitch contribution into impulse resp. h1[] *
+ *-----------------------------------------------------------------*/
+ tmp = 0;
+ Preemph(h2, st->tilt_code, L_SUBFR, &tmp);
+
+ if (T0_frac > 2)
+ T0 = (T0 + 1);
+ Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR);
+ /*-----------------------------------------------------------------*
+ * - Correlation between target xn2[] and impulse response h1[] *
+ * - Innovative codebook search *
+ *-----------------------------------------------------------------*/
+ cor_h_x(h2, xn2, dn);
+ if (*ser_size <= NBBITS_7k)
+ {
+ ACELP_2t64_fx(dn, cn, h2, code, y2, indice);
+
+ Parm_serial(indice[0], 12, &prms);
+ } else if(*ser_size <= NBBITS_9k)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice);
+
+ Parm_serial(indice[0], 5, &prms);
+ Parm_serial(indice[1], 5, &prms);
+ Parm_serial(indice[2], 5, &prms);
+ Parm_serial(indice[3], 5, &prms);
+ } else if(*ser_size <= NBBITS_12k)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice);
+
+ Parm_serial(indice[0], 9, &prms);
+ Parm_serial(indice[1], 9, &prms);
+ Parm_serial(indice[2], 9, &prms);
+ Parm_serial(indice[3], 9, &prms);
+ } else if(*ser_size <= NBBITS_14k)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice);
+
+ Parm_serial(indice[0], 13, &prms);
+ Parm_serial(indice[1], 13, &prms);
+ Parm_serial(indice[2], 9, &prms);
+ Parm_serial(indice[3], 9, &prms);
+ } else if(*ser_size <= NBBITS_16k)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice);
+
+ Parm_serial(indice[0], 13, &prms);
+ Parm_serial(indice[1], 13, &prms);
+ Parm_serial(indice[2], 13, &prms);
+ Parm_serial(indice[3], 13, &prms);
+ } else if(*ser_size <= NBBITS_18k)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice);
+
+ Parm_serial(indice[0], 2, &prms);
+ Parm_serial(indice[1], 2, &prms);
+ Parm_serial(indice[2], 2, &prms);
+ Parm_serial(indice[3], 2, &prms);
+ Parm_serial(indice[4], 14, &prms);
+ Parm_serial(indice[5], 14, &prms);
+ Parm_serial(indice[6], 14, &prms);
+ Parm_serial(indice[7], 14, &prms);
+ } else if(*ser_size <= NBBITS_20k)
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice);
+
+ Parm_serial(indice[0], 10, &prms);
+ Parm_serial(indice[1], 10, &prms);
+ Parm_serial(indice[2], 2, &prms);
+ Parm_serial(indice[3], 2, &prms);
+ Parm_serial(indice[4], 10, &prms);
+ Parm_serial(indice[5], 10, &prms);
+ Parm_serial(indice[6], 14, &prms);
+ Parm_serial(indice[7], 14, &prms);
+ } else
+ {
+ ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice);
+
+ Parm_serial(indice[0], 11, &prms);
+ Parm_serial(indice[1], 11, &prms);
+ Parm_serial(indice[2], 11, &prms);
+ Parm_serial(indice[3], 11, &prms);
+ Parm_serial(indice[4], 11, &prms);
+ Parm_serial(indice[5], 11, &prms);
+ Parm_serial(indice[6], 11, &prms);
+ Parm_serial(indice[7], 11, &prms);
+ }
+ /*-------------------------------------------------------*
+ * - Add the fixed-gain pitch contribution to code[]. *
+ *-------------------------------------------------------*/
+ tmp = 0;
+ Preemph(code, st->tilt_code, L_SUBFR, &tmp);
+ Pit_shrp(code, T0, PIT_SHARP, L_SUBFR);
+ /*----------------------------------------------------------*
+ * - Compute the fixed codebook gain *
+ * - quantize fixed codebook gain *
+ *----------------------------------------------------------*/
+ if(*ser_size <= NBBITS_9k)
+ {
+ index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6,
+ &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
+ Parm_serial(index, 6, &prms);
+ } else
+ {
+ index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7,
+ &gain_pit, &L_gain_code, clip_gain, st->qua_gain);
+ Parm_serial(index, 7, &prms);
+ }
+ /* test quantized gain of pitch for pitch clipping algorithm */
+ Gp_clip_test_gain_pit(gain_pit, st->gp_clip);
+
+ L_tmp = L_shl(L_gain_code, Q_new);
+ gain_code = extract_h(L_add(L_tmp, 0x8000));
+
+ /*----------------------------------------------------------*
+ * Update parameters for the next subframe. *
+ * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) *
+ *----------------------------------------------------------*/
+ /* find voice factor in Q15 (1=voiced, -1=unvoiced) */
+ Copy(&exc[i_subfr], exc2, L_SUBFR);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Scale_sig_opt(exc2, L_SUBFR, shift);
+#else
+ Scale_sig(exc2, L_SUBFR, shift);
+#endif
+ voice_fac = voice_factor(exc2, shift, gain_pit, code, gain_code, L_SUBFR);
+ /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */
+ st->tilt_code = ((voice_fac >> 2) + 8192);
+ /*------------------------------------------------------*
+ * - Update filter's memory "mem_w0" for finding the *
+ * target vector in the next subframe. *
+ * - Find the total excitation *
+ * - Find synthesis speech to update mem_syn[]. *
+ *------------------------------------------------------*/
+
+ /* y2 in Q9, gain_pit in Q14 */
+ L_tmp = (gain_code * y2[L_SUBFR - 1])<<1;
+ L_tmp = L_shl(L_tmp, (5 + shift));
+ L_tmp = L_negate(L_tmp);
+ L_tmp += (xn[L_SUBFR - 1] * 16384)<<1;
+ L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1;
+ L_tmp = L_shl(L_tmp, (1 - shift));
+ st->mem_w0 = extract_h(L_add(L_tmp, 0x8000));
+
+ if (*ser_size >= NBBITS_24k)
+ Copy(&exc[i_subfr], exc2, L_SUBFR);
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ /* code in Q9, gain_pit in Q14 */
+ L_tmp = (gain_code * code[i])<<1;
+ L_tmp = (L_tmp << 5);
+ L_tmp += (exc[i + i_subfr] * gain_pit)<<1;
+ L_tmp = L_shl2(L_tmp, 1);
+ exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000));
+ }
+
+ Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1);
+
+ if(*ser_size >= NBBITS_24k)
+ {
+ /*------------------------------------------------------------*
+ * phase dispersion to enhance noise in low bit rate *
+ *------------------------------------------------------------*/
+ /* L_gain_code in Q16 */
+ VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo);
+
+ /*------------------------------------------------------------*
+ * noise enhancer *
+ * ~~~~~~~~~~~~~~ *
+ * - Enhance excitation on noise. (modify gain of code) *
+ * If signal is noisy and LPC filter is stable, move gain *
+ * of code 1.5 dB toward gain of code threshold. *
+ * This decrease by 3 dB noise energy variation. *
+ *------------------------------------------------------------*/
+ tmp = (16384 - (voice_fac >> 1)); /* 1=unvoiced, 0=voiced */
+ fac = vo_mult(stab_fac, tmp);
+ L_tmp = L_gain_code;
+ if(L_tmp < st->L_gc_thres)
+ {
+ L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226));
+ if(L_tmp > st->L_gc_thres)
+ {
+ L_tmp = st->L_gc_thres;
+ }
+ } else
+ {
+ L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536);
+ if(L_tmp < st->L_gc_thres)
+ {
+ L_tmp = st->L_gc_thres;
+ }
+ }
+ st->L_gc_thres = L_tmp;
+
+ L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac));
+ VO_L_Extract(L_tmp, &gain_code, &gain_code_lo);
+ L_gain_code = vo_L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac));
+
+ /*------------------------------------------------------------*
+ * pitch enhancer *
+ * ~~~~~~~~~~~~~~ *
+ * - Enhance excitation on voice. (HP filtering of code) *
+ * On voiced signal, filtering of code by a smooth fir HP *
+ * filter to decrease energy of code in low frequency. *
+ *------------------------------------------------------------*/
+
+ tmp = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */
+
+ L_tmp = L_deposit_h(code[0]);
+ L_tmp -= (code[1] * tmp)<<1;
+ code2[0] = vo_round(L_tmp);
+
+ for (i = 1; i < L_SUBFR - 1; i++)
+ {
+ L_tmp = L_deposit_h(code[i]);
+ L_tmp -= (code[i + 1] * tmp)<<1;
+ L_tmp -= (code[i - 1] * tmp)<<1;
+ code2[i] = vo_round(L_tmp);
+ }
+
+ L_tmp = L_deposit_h(code[L_SUBFR - 1]);
+ L_tmp -= (code[L_SUBFR - 2] * tmp)<<1;
+ code2[L_SUBFR - 1] = vo_round(L_tmp);
+
+ /* build excitation */
+ gain_code = vo_round(L_shl(L_gain_code, Q_new));
+
+ for (i = 0; i < L_SUBFR; i++)
+ {
+ L_tmp = (code2[i] * gain_code)<<1;
+ L_tmp = (L_tmp << 5);
+ L_tmp += (exc2[i] * gain_pit)<<1;
+ L_tmp = (L_tmp << 1);
+ exc2[i] = vo_round(L_tmp);
+ }
+
+ corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st);
+ Parm_serial(corr_gain, 4, &prms);
+ }
+ p_A += (M + 1);
+ p_Aq += (M + 1);
+ } /* end of subframe loop */
+
+ /*--------------------------------------------------*
+ * Update signal for next frame. *
+ * -> save past of speech[], wsp[] and exc[]. *
+ *--------------------------------------------------*/
+ Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME);
+ Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM);
+ Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL);
+ return;
+}
+
+/*-----------------------------------------------------*
+* Function synthesis() *
+* *
+* Synthesis of signal at 16kHz with HF extension. *
+* *
+*-----------------------------------------------------*/
+
+static Word16 synthesis(
+ Word16 Aq[], /* A(z) : quantized Az */
+ Word16 exc[], /* (i) : excitation at 12kHz */
+ Word16 Q_new, /* (i) : scaling performed on exc */
+ Word16 synth16k[], /* (o) : 16kHz synthesis signal */
+ Coder_State * st /* (i/o) : State structure */
+ )
+{
+ Word16 fac, tmp, exp;
+ Word16 ener, exp_ener;
+ Word32 L_tmp, i;
+
+ Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR];
+ Word16 synth[L_SUBFR];
+ Word16 HF[L_SUBFR16k]; /* High Frequency vector */
+ Word16 Ap[M + 1];
+
+ Word16 HF_SP[L_SUBFR16k]; /* High Frequency vector (from original signal) */
+
+ Word16 HP_est_gain, HP_calc_gain, HP_corr_gain;
+ Word16 dist_min, dist;
+ Word16 HP_gain_ind = 0;
+ Word16 gain1, gain2;
+ Word16 weight1, weight2;
+
+ /*------------------------------------------------------------*
+ * speech synthesis *
+ * ~~~~~~~~~~~~~~~~ *
+ * - Find synthesis speech corresponding to exc2[]. *
+ * - Perform fixed deemphasis and hp 50hz filtering. *
+ * - Oversampling from 12.8kHz to 16kHz. *
+ *------------------------------------------------------------*/
+ Copy(st->mem_syn_hi, synth_hi, M);
+ Copy(st->mem_syn_lo, synth_lo, M);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
+#else
+ Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR);
+#endif
+
+ Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M);
+ Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M);
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph));
+#else
+ Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph));
+#endif
+
+ HP50_12k8(synth, L_SUBFR, st->mem_sig_out);
+
+ /* Original speech signal as reference for high band gain quantisation */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF_SP[i] = synth16k[i];
+ }
+
+ /*------------------------------------------------------*
+ * HF noise synthesis *
+ * ~~~~~~~~~~~~~~~~~~ *
+ * - Generate HF noise between 5.5 and 7.5 kHz. *
+ * - Set energy of noise according to synthesis tilt. *
+ * tilt > 0.8 ==> - 14 dB (voiced) *
+ * tilt 0.5 ==> - 6 dB (voiced or noise) *
+ * tilt < 0.0 ==> 0 dB (noise) *
+ *------------------------------------------------------*/
+ /* generate white noise vector */
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = Random(&(st->seed2))>>3;
+ }
+ /* energy of excitation */
+#ifdef ASM_OPT /* asm optimization branch */
+ Scale_sig_opt(exc, L_SUBFR, -3);
+ Q_new = Q_new - 3;
+ ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener));
+#else
+ Scale_sig(exc, L_SUBFR, -3);
+ Q_new = Q_new - 3;
+ ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener));
+#endif
+
+ exp_ener = exp_ener - (Q_new + Q_new);
+ /* set energy of white noise to energy of excitation */
+#ifdef ASM_OPT /* asm optimization branch */
+ tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));
+#else
+ tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
+#endif
+
+ if(tmp > ener)
+ {
+ tmp = (tmp >> 1); /* Be sure tmp < ener */
+ exp = (exp + 1);
+ }
+ L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
+ exp = (exp - exp_ener);
+ Isqrt_n(&L_tmp, &exp);
+ L_tmp = L_shl(L_tmp, (exp + 1)); /* L_tmp x 2, L_tmp in Q31 */
+ tmp = extract_h(L_tmp); /* tmp = 2 x sqrt(ener_exc/ener_hf) */
+
+ for (i = 0; i < L_SUBFR16k; i++)
+ {
+ HF[i] = vo_mult(HF[i], tmp);
+ }
+
+ /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */
+ HP400_12k8(synth, L_SUBFR, st->mem_hp400);
+
+ L_tmp = 1L;
+ for (i = 0; i < L_SUBFR; i++)
+ L_tmp += (synth[i] * synth[i])<<1;
+
+ exp = norm_l(L_tmp);
+ ener = extract_h(L_tmp << exp); /* ener = r[0] */
+
+ L_tmp = 1L;
+ for (i = 1; i < L_SUBFR; i++)
+ L_tmp +=(synth[i] * synth[i - 1])<<1;
+
+ tmp = extract_h(L_tmp << exp); /* tmp = r[1] */
+
+ if (tmp > 0)
+ {
+ fac = div_s(tmp, ener);
+ } else
+ {
+ fac = 0;
+ }
+
+ /* modify energy of white noise according to synthesis tilt */
+ gain1 = 32767 - fac;
+ gain2 = vo_mult(gain1, 20480);
+ gain2 = shl(gain2, 1);
+
+ if (st->vad_hist > 0)
+ {
+ weight1 = 0;
+ weight2 = 32767;
+ } else
+ {
+ weight1 = 32767;
+ weight2 = 0;
+ }
+ tmp = vo_mult(weight1, gain1);
+ tmp = add1(tmp, vo_mult(weight2, gain2));
+
+ if (tmp != 0)
+ {
+ tmp = (tmp + 1);
+ }
+ HP_est_gain = tmp;
+
+ if(HP_est_gain < 3277)
+ {
+ HP_est_gain = 3277; /* 0.1 in Q15 */
+ }
+ /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */
+ Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */
+
+#ifdef ASM_OPT /* asm optimization branch */
+ Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf);
+ /* noise High Pass filtering (1ms of delay) */
+ Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf);
+ /* filtering of the original signal */
+ Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2);
+
+ /* check the gain difference */
+ Scale_sig_opt(HF_SP, L_SUBFR16k, -1);
+ ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
+ /* set energy of white noise to energy of excitation */
+ tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp));
+#else
+ Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1);
+ /* noise High Pass filtering (1ms of delay) */
+ Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf);
+ /* filtering of the original signal */
+ Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2);
+ /* check the gain difference */
+ Scale_sig(HF_SP, L_SUBFR16k, -1);
+ ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener));
+ /* set energy of white noise to energy of excitation */
+ tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp));
+#endif
+
+ if (tmp > ener)
+ {
+ tmp = (tmp >> 1); /* Be sure tmp < ener */
+ exp = (exp + 1);
+ }
+ L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */
+ exp = vo_sub(exp, exp_ener);
+ Isqrt_n(&L_tmp, &exp);
+ L_tmp = L_shl(L_tmp, exp); /* L_tmp, L_tmp in Q31 */
+ HP_calc_gain = extract_h(L_tmp); /* tmp = sqrt(ener_input/ener_hf) */
+
+ /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */
+ L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15);
+ st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp));
+
+ if(st->dtx_encSt->dtxHangoverCount > 6)
+ st->gain_alpha = 32767;
+ HP_est_gain = HP_est_gain >> 1; /* From Q15 to Q14 */
+ HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain));
+
+ /* Quantise the correction gain */
+ dist_min = 32767;
+ for (i = 0; i < 16; i++)
+ {
+ dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i]));
+ if (dist_min > dist)
+ {
+ dist_min = dist;
+ HP_gain_ind = i;
+ }
+ }
+ HP_corr_gain = HP_gain[HP_gain_ind];
+ /* return the quantised gain index when using the highest mode, otherwise zero */
+ return (HP_gain_ind);
+}
+
+/*************************************************
+*
+* Breif: Codec main function
+*
+**************************************************/
+
+int AMR_Enc_Encode(HAMRENC hCodec)
+{
+ Word32 i;
+ Coder_State *gData = (Coder_State*)hCodec;
+ Word16 *signal;
+ Word16 packed_size = 0;
+ Word16 prms[NB_BITS_MAX];
+ Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag;
+ mode = gData->mode;
+ coding_mode = gData->mode;
+ nb_bits = nb_of_bits[mode];
+ signal = (Word16 *)gData->inputStream;
+ allow_dtx = gData->allow_dtx;
+
+ /* check for homing frame */
+ reset_flag = encoder_homing_frame_test(signal);
+
+ for (i = 0; i < L_FRAME16k; i++) /* Delete the 2 LSBs (14-bit input) */
+ {
+ *(signal + i) = (Word16) (*(signal + i) & 0xfffC);
+ }
+
+ coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx);
+ packed_size = PackBits(prms, coding_mode, mode, gData);
+ if (reset_flag != 0)
+ {
+ Reset_encoder(gData, 1);
+ }
+ return packed_size;
+}
+
+/***************************************************************************
+*
+*Brief: Codec API function --- Initialize the codec and return a codec handle
+*
+***************************************************************************/
+
+VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec, /* o: the audio codec handle */
+ VO_AUDIO_CODINGTYPE vType, /* i: Codec Type ID */
+ VO_CODEC_INIT_USERDATA * pUserData /* i: init Parameters */
+ )
+{
+ Coder_State *st;
+ FrameStream *stream;
+#ifdef USE_DEAULT_MEM
+ VO_MEM_OPERATOR voMemoprator;
+#endif
+ VO_MEM_OPERATOR *pMemOP;
+ int interMem = 0;
+
+ if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL )
+ {
+#ifdef USE_DEAULT_MEM
+ voMemoprator.Alloc = cmnMemAlloc;
+ voMemoprator.Copy = cmnMemCopy;
+ voMemoprator.Free = cmnMemFree;
+ voMemoprator.Set = cmnMemSet;
+ voMemoprator.Check = cmnMemCheck;
+ interMem = 1;
+ pMemOP = &voMemoprator;
+#else
+ *phCodec = NULL;
+ return VO_ERR_INVALID_ARG;
+#endif
+ }
+ else
+ {
+ pMemOP = (VO_MEM_OPERATOR *)pUserData->memData;
+ }
+ /*-------------------------------------------------------------------------*
+ * Memory allocation for coder state. *
+ *-------------------------------------------------------------------------*/
+ if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL)
+ {
+ return VO_ERR_OUTOF_MEMORY;
+ }
+
+ st->vadSt = NULL;
+ st->dtx_encSt = NULL;
+ st->sid_update_counter = 3;
+ st->sid_handover_debt = 0;
+ st->prev_ft = TX_SPEECH;
+ st->inputStream = NULL;
+ st->inputSize = 0;
+
+ /* Default setting */
+ st->mode = VOAMRWB_MD2385; /* bit rate 23.85kbps */
+ st->frameType = VOAMRWB_RFC3267; /* frame type: RFC3267 */
+ st->allow_dtx = 0; /* disable DTX mode */
+
+ st->outputStream = NULL;
+ st->outputSize = 0;
+
+ st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB);
+ if(st->stream == NULL)
+ return VO_ERR_OUTOF_MEMORY;
+
+ st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB);
+ if(st->stream->frame_ptr == NULL)
+ return VO_ERR_OUTOF_MEMORY;
+
+ stream = st->stream;
+ voAWB_InitFrameBuffer(stream);
+
+ wb_vad_init(&(st->vadSt), pMemOP);
+ dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP);
+
+ Reset_encoder((void *) st, 1);
+
+ if(interMem)
+ {
+ st->voMemoprator.Alloc = cmnMemAlloc;
+ st->voMemoprator.Copy = cmnMemCopy;
+ st->voMemoprator.Free = cmnMemFree;
+ st->voMemoprator.Set = cmnMemSet;
+ st->voMemoprator.Check = cmnMemCheck;
+ pMemOP = &st->voMemoprator;
+ }
+
+ st->pvoMemop = pMemOP;
+
+ *phCodec = (void *) st;
+
+ return VO_ERR_NONE;
+}
+
+/**********************************************************************************
+*
+* Brief: Codec API function: Input PCM data
+*
+***********************************************************************************/
+
+VO_U32 VO_API voAMRWB_SetInputData(
+ VO_HANDLE hCodec, /* i/o: The codec handle which was created by Init function */
+ VO_CODECBUFFER * pInput /* i: The input buffer parameter */
+ )
+{
+ Coder_State *gData;
+ FrameStream *stream;
+
+ if(NULL == hCodec)
+ {
+ return VO_ERR_INVALID_ARG;
+ }
+
+ gData = (Coder_State *)hCodec;
+ stream = gData->stream;
+
+ if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length)
+ {
+ return VO_ERR_INVALID_ARG;
+ }
+
+ stream->set_ptr = pInput->Buffer;
+ stream->set_len = pInput->Length;
+ stream->frame_ptr = stream->frame_ptr_bk;
+ stream->used_len = 0;
+
+ return VO_ERR_NONE;
+}
+
+/**************************************************************************************
+*
+* Brief: Codec API function: Get the compression audio data frame by frame
+*
+***************************************************************************************/
+
+VO_U32 VO_API voAMRWB_GetOutputData(
+ VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function*/
+ VO_CODECBUFFER * pOutput, /* o: The output audio data */
+ VO_AUDIO_OUTPUTINFO * pAudioFormat /* o: The encoder module filled audio format and used the input size*/
+ )
+{
+ Coder_State* gData = (Coder_State*)hCodec;
+ VO_MEM_OPERATOR *pMemOP;
+ FrameStream *stream = (FrameStream *)gData->stream;
+ pMemOP = (VO_MEM_OPERATOR *)gData->pvoMemop;
+
+ if(stream->framebuffer_len < Frame_MaxByte) /* check the work buffer len */
+ {
+ stream->frame_storelen = stream->framebuffer_len;
+ if(stream->frame_storelen)
+ {
+ pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen);
+ }
+ if(stream->set_len > 0)
+ {
+ voAWB_UpdateFrameBuffer(stream, pMemOP);
+ }
+ if(stream->framebuffer_len < Frame_MaxByte)
+ {
+ if(pAudioFormat)
+ pAudioFormat->InputUsed = stream->used_len;
+ return VO_ERR_INPUT_BUFFER_SMALL;
+ }
+ }
+
+ gData->inputStream = stream->frame_ptr;
+ gData->outputStream = (unsigned short*)pOutput->Buffer;
+
+ gData->outputSize = AMR_Enc_Encode(gData); /* encoder main function */
+
+ pOutput->Length = gData->outputSize; /* get the output buffer length */
+ stream->frame_ptr += 640; /* update the work buffer ptr */
+ stream->framebuffer_len -= 640;
+
+ if(pAudioFormat) /* return output audio information */
+ {
+ pAudioFormat->Format.Channels = 1;
+ pAudioFormat->Format.SampleRate = 8000;
+ pAudioFormat->Format.SampleBits = 16;
+ pAudioFormat->InputUsed = stream->used_len;
+ }
+ return VO_ERR_NONE;
+}
+
+/*************************************************************************
+*
+* Brief: Codec API function---set the data by specified parameter ID
+*
+*************************************************************************/
+
+
+VO_U32 VO_API voAMRWB_SetParam(
+ VO_HANDLE hCodec, /* i/o: The Codec Handle which was created by Init function */
+ VO_S32 uParamID, /* i: The param ID */
+ VO_PTR pData /* i: The param value depend on the ID */
+ )
+{
+ Coder_State* gData = (Coder_State*)hCodec;
+ FrameStream *stream = (FrameStream *)(gData->stream);
+ int *lValue = (int*)pData;
+
+ switch(uParamID)
+ {
+ /* setting AMR-WB frame type*/
+ case VO_PID_AMRWB_FRAMETYPE:
+ if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267)
+ return VO_ERR_WRONG_PARAM_ID;
+ gData->frameType = *lValue;
+ break;
+ /* setting AMR-WB bit rate */
+ case VO_PID_AMRWB_MODE:
+ {
+ if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385)
+ return VO_ERR_WRONG_PARAM_ID;
+ gData->mode = *lValue;
+ }
+ break;
+ /* enable or disable DTX mode */
+ case VO_PID_AMRWB_DTX:
+ gData->allow_dtx = (Word16)(*lValue);
+ break;
+
+ case VO_PID_COMMON_HEADDATA:
+ break;
+ /* flush the work buffer */
+ case VO_PID_COMMON_FLUSH:
+ stream->set_ptr = NULL;
+ stream->frame_storelen = 0;
+ stream->framebuffer_len = 0;
+ stream->set_len = 0;
+ break;
+
+ default:
+ return VO_ERR_WRONG_PARAM_ID;
+ }
+ return VO_ERR_NONE;
+}
+
+/**************************************************************************
+*
+*Brief: Codec API function---Get the data by specified parameter ID
+*
+***************************************************************************/
+
+VO_U32 VO_API voAMRWB_GetParam(
+ VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function */
+ VO_S32 uParamID, /* i: The param ID */
+ VO_PTR pData /* o: The param value depend on the ID */
+ )
+{
+ int temp;
+ Coder_State* gData = (Coder_State*)hCodec;
+
+ if (gData==NULL)
+ return VO_ERR_INVALID_ARG;
+ switch(uParamID)
+ {
+ /* output audio format */
+ case VO_PID_AMRWB_FORMAT:
+ {
+ VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData;
+ fmt->Channels = 1;
+ fmt->SampleRate = 16000;
+ fmt->SampleBits = 16;
+ break;
+ }
+ /* output audio channel number */
+ case VO_PID_AMRWB_CHANNELS:
+ temp = 1;
+ pData = (void *)(&temp);
+ break;
+ /* output audio sample rate */
+ case VO_PID_AMRWB_SAMPLERATE:
+ temp = 16000;
+ pData = (void *)(&temp);
+ break;
+ /* output audio frame type */
+ case VO_PID_AMRWB_FRAMETYPE:
+ temp = gData->frameType;
+ pData = (void *)(&temp);
+ break;
+ /* output audio bit rate */
+ case VO_PID_AMRWB_MODE:
+ temp = gData->mode;
+ pData = (void *)(&temp);
+ break;
+ default:
+ return VO_ERR_WRONG_PARAM_ID;
+ }
+
+ return VO_ERR_NONE;
+}
+
+/***********************************************************************************
+*
+* Brief: Codec API function---Release the codec after all encoder operations are done
+*
+*************************************************************************************/
+
+VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec /* i/o: Codec handle pointer */
+ )
+{
+ Coder_State* gData = (Coder_State*)hCodec;
+ VO_MEM_OPERATOR *pMemOP;
+ pMemOP = gData->pvoMemop;
+
+ if(hCodec)
+ {
+ if(gData->stream)
+ {
+ if(gData->stream->frame_ptr_bk)
+ {
+ mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB);
+ gData->stream->frame_ptr_bk = NULL;
+ }
+ mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB);
+ gData->stream = NULL;
+ }
+ wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP);
+ dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP);
+
+ mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB);
+ hCodec = NULL;
+ }
+
+ return VO_ERR_NONE;
+}
+
+/********************************************************************************
+*
+* Brief: voGetAMRWBEncAPI gets the API handle of the codec
+*
+********************************************************************************/
+
+VO_S32 VO_API voGetAMRWBEncAPI(
+ VO_AUDIO_CODECAPI * pEncHandle /* i/o: Codec handle pointer */
+ )
+{
+ if(NULL == pEncHandle)
+ return VO_ERR_INVALID_ARG;
+ pEncHandle->Init = voAMRWB_Init;
+ pEncHandle->SetInputData = voAMRWB_SetInputData;
+ pEncHandle->GetOutputData = voAMRWB_GetOutputData;
+ pEncHandle->SetParam = voAMRWB_SetParam;
+ pEncHandle->GetParam = voAMRWB_GetParam;
+ pEncHandle->Uninit = voAMRWB_Uninit;
+
+ return VO_ERR_NONE;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/media/libstagefright/codecs/amrwbenc/src/voicefac.c b/media/libstagefright/codecs/amrwbenc/src/voicefac.c
new file mode 100644
index 0000000..187d774
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/voicefac.c
@@ -0,0 +1,92 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voicefac.c *
+* *
+* Description: Find the voicing factors (1 = voice to -1 = unvoiced) *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+
+Word16 voice_factor( /* (o) Q15 : factor (-1=unvoiced to 1=voiced) */
+ Word16 exc[], /* (i) Q_exc : pitch excitation */
+ Word16 Q_exc, /* (i) : exc format */
+ Word16 gain_pit, /* (i) Q14 : gain of pitch */
+ Word16 code[], /* (i) Q9 : Fixed codebook excitation */
+ Word16 gain_code, /* (i) Q0 : gain of code */
+ Word16 L_subfr /* (i) : subframe length */
+ )
+{
+ Word16 tmp, exp, ener1, exp1, ener2, exp2;
+ Word32 i, L_tmp;
+
+#ifdef ASM_OPT /* asm optimization branch */
+ ener1 = extract_h(Dot_product12_asm(exc, exc, L_subfr, &exp1));
+#else
+ ener1 = extract_h(Dot_product12(exc, exc, L_subfr, &exp1));
+#endif
+ exp1 = exp1 - (Q_exc + Q_exc);
+ L_tmp = vo_L_mult(gain_pit, gain_pit);
+ exp = norm_l(L_tmp);
+ tmp = extract_h(L_tmp << exp);
+ ener1 = vo_mult(ener1, tmp);
+ exp1 = exp1 - exp - 10; /* 10 -> gain_pit Q14 to Q9 */
+
+#ifdef ASM_OPT /* asm optimization branch */
+ ener2 = extract_h(Dot_product12_asm(code, code, L_subfr, &exp2));
+#else
+ ener2 = extract_h(Dot_product12(code, code, L_subfr, &exp2));
+#endif
+
+ exp = norm_s(gain_code);
+ tmp = gain_code << exp;
+ tmp = vo_mult(tmp, tmp);
+ ener2 = vo_mult(ener2, tmp);
+ exp2 = exp2 - (exp + exp);
+
+ i = exp1 - exp2;
+
+ if (i >= 0)
+ {
+ ener1 = ener1 >> 1;
+ ener2 = ener2 >> (i + 1);
+ } else
+ {
+ ener1 = ener1 >> (1 - i);
+ ener2 = ener2 >> 1;
+ }
+
+ tmp = vo_sub(ener1, ener2);
+ ener1 = add1(add1(ener1, ener2), 1);
+
+ if (tmp >= 0)
+ {
+ tmp = div_s(tmp, ener1);
+ } else
+ {
+ tmp = vo_negate(div_s(vo_negate(tmp), ener1));
+ }
+
+ return (tmp);
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/wb_vad.c b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
new file mode 100644
index 0000000..0126853
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/wb_vad.c
@@ -0,0 +1,808 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: wb_vad.c *
+* *
+* Description: Voice Activity Detection *
+* *
+************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "cnst.h"
+#include "wb_vad.h"
+#include "typedef.h"
+#include "basic_op.h"
+#include "math_op.h"
+#include "wb_vad_c.h"
+#include "mem_align.h"
+
+/******************************************************************************
+* Calculate Log2 and scale the signal:
+*
+* ilog2(Word32 in) = -1024*log10(in * 2^-31)/log10(2), where in = [1, 2^31-1]
+*
+* input output
+* 32768 16384
+* 1 31744
+*
+* When input is in the range of [1,2^16], max error is 0.0380%.
+*********************************************************************************/
+
+static Word16 ilog2( /* return: output value of the log2 */
+ Word16 mant /* i: value to be converted */
+ )
+{
+ Word16 ex, ex2, res;
+ Word32 i, l_temp;
+
+ if (mant <= 0)
+ {
+ mant = 1;
+ }
+ ex = norm_s(mant);
+ mant = mant << ex;
+
+ for (i = 0; i < 3; i++)
+ mant = vo_mult(mant, mant);
+ l_temp = vo_L_mult(mant, mant);
+
+ ex2 = norm_l(l_temp);
+ mant = extract_h(l_temp << ex2);
+
+ res = (ex + 16) << 10;
+ res = add1(res, (ex2 << 6));
+ res = vo_sub(add1(res, 127), (mant >> 8));
+ return (res);
+}
+
+/******************************************************************************
+*
+* Function : filter5
+* Purpose : Fifth-order half-band lowpass/highpass filter pair with
+* decimation.
+*
+*******************************************************************************/
+
+static void filter5(
+ Word16 * in0, /* i/o : input values; output low-pass part */
+ Word16 * in1, /* i/o : input values; output high-pass part */
+ Word16 data[] /* i/o : filter memory */
+ )
+{
+ Word16 temp0, temp1, temp2;
+
+ temp0 = vo_sub(*in0, vo_mult(COEFF5_1, data[0]));
+ temp1 = add1(data[0], vo_mult(COEFF5_1, temp0));
+ data[0] = temp0;
+
+ temp0 = vo_sub(*in1, vo_mult(COEFF5_2, data[1]));
+ temp2 = add1(data[1], vo_mult(COEFF5_2, temp0));
+ data[1] = temp0;
+
+ *in0 = extract_h((vo_L_add(temp1, temp2) << 15));
+ *in1 = extract_h((vo_L_sub(temp1, temp2) << 15));
+}
+
+/******************************************************************************
+*
+* Function : filter3
+* Purpose : Third-order half-band lowpass/highpass filter pair with
+* decimation.
+*
+*******************************************************************************/
+
+static void filter3(
+ Word16 * in0, /* i/o : input values; output low-pass part */
+ Word16 * in1, /* i/o : input values; output high-pass part */
+ Word16 * data /* i/o : filter memory */
+ )
+{
+ Word16 temp1, temp2;
+
+ temp1 = vo_sub(*in1, vo_mult(COEFF3, *data));
+ temp2 = add1(*data, vo_mult(COEFF3, temp1));
+ *data = temp1;
+
+ *in1 = extract_h((vo_L_sub(*in0, temp2) << 15));
+ *in0 = extract_h((vo_L_add(*in0, temp2) << 15));
+}
+
+/******************************************************************************
+*
+* Function : level_calculation
+* Purpose : Calculate signal level in a sub-band. Level is calculated
+* by summing absolute values of the input data.
+*
+* Signal level calculated from of the end of the frame
+* (data[count1 - count2]) is stored to (*sub_level)
+* and added to the level of the next frame.
+*
+******************************************************************************/
+
+static Word16 level_calculation( /* return: signal level */
+ Word16 data[], /* i : signal buffer */
+ Word16 * sub_level, /* i : level calculated at the end of the previous frame*/
+ /* o : level of signal calculated from the last */
+ /* (count2 - count1) samples */
+ Word16 count1, /* i : number of samples to be counted */
+ Word16 count2, /* i : number of samples to be counted */
+ Word16 ind_m, /* i : step size for the index of the data buffer */
+ Word16 ind_a, /* i : starting index of the data buffer */
+ Word16 scale /* i : scaling for the level calculation */
+ )
+{
+ Word32 i, l_temp1, l_temp2;
+ Word16 level;
+
+ l_temp1 = 0L;
+ for (i = count1; i < count2; i++)
+ {
+ l_temp1 += (abs_s(data[ind_m * i + ind_a])<<1);
+ }
+
+ l_temp2 = vo_L_add(l_temp1, L_shl(*sub_level, 16 - scale));
+ *sub_level = extract_h(L_shl(l_temp1, scale));
+
+ for (i = 0; i < count1; i++)
+ {
+ l_temp2 += (abs_s(data[ind_m * i + ind_a])<<1);
+ }
+ level = extract_h(L_shl2(l_temp2, scale));
+
+ return level;
+}
+
+/******************************************************************************
+*
+* Function : filter_bank
+* Purpose : Divide input signal into bands and calculate level of
+* the signal in each band
+*
+*******************************************************************************/
+
+static void filter_bank(
+ VadVars * st, /* i/o : State struct */
+ Word16 in[], /* i : input frame */
+ Word16 level[] /* o : signal levels at each band */
+ )
+{
+ Word32 i;
+ Word16 tmp_buf[FRAME_LEN];
+
+ /* shift input 1 bit down for safe scaling */
+ for (i = 0; i < FRAME_LEN; i++)
+ {
+ tmp_buf[i] = in[i] >> 1;
+ }
+
+ /* run the filter bank */
+ for (i = 0; i < 128; i++)
+ {
+ filter5(&tmp_buf[2 * i], &tmp_buf[2 * i + 1], st->a_data5[0]);
+ }
+ for (i = 0; i < 64; i++)
+ {
+ filter5(&tmp_buf[4 * i], &tmp_buf[4 * i + 2], st->a_data5[1]);
+ filter5(&tmp_buf[4 * i + 1], &tmp_buf[4 * i + 3], st->a_data5[2]);
+ }
+ for (i = 0; i < 32; i++)
+ {
+ filter5(&tmp_buf[8 * i], &tmp_buf[8 * i + 4], st->a_data5[3]);
+ filter5(&tmp_buf[8 * i + 2], &tmp_buf[8 * i + 6], st->a_data5[4]);
+ filter3(&tmp_buf[8 * i + 3], &tmp_buf[8 * i + 7], &st->a_data3[0]);
+ }
+ for (i = 0; i < 16; i++)
+ {
+ filter3(&tmp_buf[16 * i + 0], &tmp_buf[16 * i + 8], &st->a_data3[1]);
+ filter3(&tmp_buf[16 * i + 4], &tmp_buf[16 * i + 12], &st->a_data3[2]);
+ filter3(&tmp_buf[16 * i + 6], &tmp_buf[16 * i + 14], &st->a_data3[3]);
+ }
+
+ for (i = 0; i < 8; i++)
+ {
+ filter3(&tmp_buf[32 * i + 0], &tmp_buf[32 * i + 16], &st->a_data3[4]);
+ filter3(&tmp_buf[32 * i + 8], &tmp_buf[32 * i + 24], &st->a_data3[5]);
+ }
+
+ /* calculate levels in each frequency band */
+
+ /* 4800 - 6400 Hz */
+ level[11] = level_calculation(tmp_buf, &st->sub_level[11], 16, 64, 4, 1, 14);
+ /* 4000 - 4800 Hz */
+ level[10] = level_calculation(tmp_buf, &st->sub_level[10], 8, 32, 8, 7, 15);
+ /* 3200 - 4000 Hz */
+ level[9] = level_calculation(tmp_buf, &st->sub_level[9],8, 32, 8, 3, 15);
+ /* 2400 - 3200 Hz */
+ level[8] = level_calculation(tmp_buf, &st->sub_level[8],8, 32, 8, 2, 15);
+ /* 2000 - 2400 Hz */
+ level[7] = level_calculation(tmp_buf, &st->sub_level[7],4, 16, 16, 14, 16);
+ /* 1600 - 2000 Hz */
+ level[6] = level_calculation(tmp_buf, &st->sub_level[6],4, 16, 16, 6, 16);
+ /* 1200 - 1600 Hz */
+ level[5] = level_calculation(tmp_buf, &st->sub_level[5],4, 16, 16, 4, 16);
+ /* 800 - 1200 Hz */
+ level[4] = level_calculation(tmp_buf, &st->sub_level[4],4, 16, 16, 12, 16);
+ /* 600 - 800 Hz */
+ level[3] = level_calculation(tmp_buf, &st->sub_level[3],2, 8, 32, 8, 17);
+ /* 400 - 600 Hz */
+ level[2] = level_calculation(tmp_buf, &st->sub_level[2],2, 8, 32, 24, 17);
+ /* 200 - 400 Hz */
+ level[1] = level_calculation(tmp_buf, &st->sub_level[1],2, 8, 32, 16, 17);
+ /* 0 - 200 Hz */
+ level[0] = level_calculation(tmp_buf, &st->sub_level[0],2, 8, 32, 0, 17);
+}
+
+/******************************************************************************
+*
+* Function : update_cntrl
+* Purpose : Control update of the background noise estimate.
+*
+*******************************************************************************/
+
+static void update_cntrl(
+ VadVars * st, /* i/o : State structure */
+ Word16 level[] /* i : sub-band levels of the input frame */
+ )
+{
+ Word32 i;
+ Word16 num, temp, stat_rat, exp, denom;
+ Word16 alpha;
+
+ /* if a tone has been detected for a while, initialize stat_count */
+ if (sub((Word16) (st->tone_flag & 0x7c00), 0x7c00) == 0)
+ {
+ st->stat_count = STAT_COUNT;
+ } else
+ {
+ /* if 8 last vad-decisions have been "0", reinitialize stat_count */
+ if ((st->vadreg & 0x7f80) == 0)
+ {
+ st->stat_count = STAT_COUNT;
+ } else
+ {
+ stat_rat = 0;
+ for (i = 0; i < COMPLEN; i++)
+ {
+ if(level[i] > st->ave_level[i])
+ {
+ num = level[i];
+ denom = st->ave_level[i];
+ } else
+ {
+ num = st->ave_level[i];
+ denom = level[i];
+ }
+ /* Limit nimimum value of num and denom to STAT_THR_LEVEL */
+ if(num < STAT_THR_LEVEL)
+ {
+ num = STAT_THR_LEVEL;
+ }
+ if(denom < STAT_THR_LEVEL)
+ {
+ denom = STAT_THR_LEVEL;
+ }
+ exp = norm_s(denom);
+ denom = denom << exp;
+
+ /* stat_rat = num/denom * 64 */
+ temp = div_s(num >> 1, denom);
+ stat_rat = add1(stat_rat, shr(temp, (8 - exp)));
+ }
+
+ /* compare stat_rat with a threshold and update stat_count */
+ if(stat_rat > STAT_THR)
+ {
+ st->stat_count = STAT_COUNT;
+ } else
+ {
+ if ((st->vadreg & 0x4000) != 0)
+ {
+
+ if (st->stat_count != 0)
+ {
+ st->stat_count = st->stat_count - 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* Update average amplitude estimate for stationarity estimation */
+ alpha = ALPHA4;
+ if(st->stat_count == STAT_COUNT)
+ {
+ alpha = 32767;
+ } else if ((st->vadreg & 0x4000) == 0)
+ {
+ alpha = ALPHA5;
+ }
+ for (i = 0; i < COMPLEN; i++)
+ {
+ st->ave_level[i] = add1(st->ave_level[i], vo_mult_r(alpha, vo_sub(level[i], st->ave_level[i])));
+ }
+}
+
+/******************************************************************************
+*
+* Function : hangover_addition
+* Purpose : Add hangover after speech bursts
+*
+*******************************************************************************/
+
+static Word16 hangover_addition( /* return: VAD_flag indicating final VAD decision */
+ VadVars * st, /* i/o : State structure */
+ Word16 low_power, /* i : flag power of the input frame */
+ Word16 hang_len, /* i : hangover length */
+ Word16 burst_len /* i : minimum burst length for hangover addition */
+ )
+{
+ /* if the input power (pow_sum) is lower than a threshold, clear counters and set VAD_flag to "0" */
+ if (low_power != 0)
+ {
+ st->burst_count = 0;
+ st->hang_count = 0;
+ return 0;
+ }
+ /* update the counters (hang_count, burst_count) */
+ if ((st->vadreg & 0x4000) != 0)
+ {
+ st->burst_count = st->burst_count + 1;
+ if(st->burst_count >= burst_len)
+ {
+ st->hang_count = hang_len;
+ }
+ return 1;
+ } else
+ {
+ st->burst_count = 0;
+ if (st->hang_count > 0)
+ {
+ st->hang_count = st->hang_count - 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/******************************************************************************
+*
+* Function : noise_estimate_update
+* Purpose : Update of background noise estimate
+*
+*******************************************************************************/
+
+static void noise_estimate_update(
+ VadVars * st, /* i/o : State structure */
+ Word16 level[] /* i : sub-band levels of the input frame */
+ )
+{
+ Word32 i;
+ Word16 alpha_up, alpha_down, bckr_add = 2;
+
+ /* Control update of bckr_est[] */
+ update_cntrl(st, level);
+
+ /* Choose update speed */
+ if ((0x7800 & st->vadreg) == 0)
+ {
+ alpha_up = ALPHA_UP1;
+ alpha_down = ALPHA_DOWN1;
+ } else
+ {
+ if ((st->stat_count == 0))
+ {
+ alpha_up = ALPHA_UP2;
+ alpha_down = ALPHA_DOWN2;
+ } else
+ {
+ alpha_up = 0;
+ alpha_down = ALPHA3;
+ bckr_add = 0;
+ }
+ }
+
+ /* Update noise estimate (bckr_est) */
+ for (i = 0; i < COMPLEN; i++)
+ {
+ Word16 temp;
+ temp = (st->old_level[i] - st->bckr_est[i]);
+
+ if (temp < 0)
+ { /* update downwards */
+ st->bckr_est[i] = add1(-2, add(st->bckr_est[i],vo_mult_r(alpha_down, temp)));
+ /* limit minimum value of the noise estimate to NOISE_MIN */
+ if(st->bckr_est[i] < NOISE_MIN)
+ {
+ st->bckr_est[i] = NOISE_MIN;
+ }
+ } else
+ { /* update upwards */
+ st->bckr_est[i] = add1(bckr_add, add1(st->bckr_est[i],vo_mult_r(alpha_up, temp)));
+
+ /* limit maximum value of the noise estimate to NOISE_MAX */
+ if(st->bckr_est[i] > NOISE_MAX)
+ {
+ st->bckr_est[i] = NOISE_MAX;
+ }
+ }
+ }
+
+ /* Update signal levels of the previous frame (old_level) */
+ for (i = 0; i < COMPLEN; i++)
+ {
+ st->old_level[i] = level[i];
+ }
+}
+
+/******************************************************************************
+*
+* Function : vad_decision
+* Purpose : Calculates VAD_flag
+*
+*******************************************************************************/
+
+static Word16 vad_decision( /* return value : VAD_flag */
+ VadVars * st, /* i/o : State structure */
+ Word16 level[COMPLEN], /* i : sub-band levels of the input frame */
+ Word32 pow_sum /* i : power of the input frame */
+ )
+{
+ Word32 i;
+ Word32 L_snr_sum;
+ Word32 L_temp;
+ Word16 vad_thr, temp, noise_level;
+ Word16 low_power_flag;
+ Word16 hang_len, burst_len;
+ Word16 ilog2_speech_level, ilog2_noise_level;
+ Word16 temp2;
+
+ /* Calculate squared sum of the input levels (level) divided by the background noise components
+ * (bckr_est). */
+ L_snr_sum = 0;
+ for (i = 0; i < COMPLEN; i++)
+ {
+ Word16 exp;
+
+ exp = norm_s(st->bckr_est[i]);
+ temp = (st->bckr_est[i] << exp);
+ temp = div_s((level[i] >> 1), temp);
+ temp = shl(temp, (exp - (UNIRSHFT - 1)));
+ L_snr_sum = L_mac(L_snr_sum, temp, temp);
+ }
+
+ /* Calculate average level of estimated background noise */
+ L_temp = 0;
+ for (i = 1; i < COMPLEN; i++) /* ignore lowest band */
+ {
+ L_temp = vo_L_add(L_temp, st->bckr_est[i]);
+ }
+
+ noise_level = extract_h((L_temp << 12));
+ /* if SNR is lower than a threshold (MIN_SPEECH_SNR), and increase speech_level */
+ temp = vo_mult(noise_level, MIN_SPEECH_SNR) << 3;
+
+ if(st->speech_level < temp)
+ {
+ st->speech_level = temp;
+ }
+ ilog2_noise_level = ilog2(noise_level);
+
+ /* If SNR is very poor, speech_level is probably corrupted by noise level. This is correctred by
+ * subtracting MIN_SPEECH_SNR*noise_level from speech level */
+ ilog2_speech_level = ilog2(st->speech_level - temp);
+
+ temp = add1(vo_mult(NO_SLOPE, (ilog2_noise_level - NO_P1)), THR_HIGH);
+
+ temp2 = add1(SP_CH_MIN, vo_mult(SP_SLOPE, (ilog2_speech_level - SP_P1)));
+ if (temp2 < SP_CH_MIN)
+ {
+ temp2 = SP_CH_MIN;
+ }
+ if (temp2 > SP_CH_MAX)
+ {
+ temp2 = SP_CH_MAX;
+ }
+ vad_thr = temp + temp2;
+
+ if(vad_thr < THR_MIN)
+ {
+ vad_thr = THR_MIN;
+ }
+ /* Shift VAD decision register */
+ st->vadreg = (st->vadreg >> 1);
+
+ /* Make intermediate VAD decision */
+ if(L_snr_sum > vo_L_mult(vad_thr, (512 * COMPLEN)))
+ {
+ st->vadreg = (Word16) (st->vadreg | 0x4000);
+ }
+ /* check if the input power (pow_sum) is lower than a threshold" */
+ if(pow_sum < VAD_POW_LOW)
+ {
+ low_power_flag = 1;
+ } else
+ {
+ low_power_flag = 0;
+ }
+ /* Update background noise estimates */
+ noise_estimate_update(st, level);
+
+ /* Calculate values for hang_len and burst_len based on vad_thr */
+ hang_len = add1(vo_mult(HANG_SLOPE, (vad_thr - HANG_P1)), HANG_HIGH);
+ if(hang_len < HANG_LOW)
+ {
+ hang_len = HANG_LOW;
+ }
+ burst_len = add1(vo_mult(BURST_SLOPE, (vad_thr - BURST_P1)), BURST_HIGH);
+
+ return (hangover_addition(st, low_power_flag, hang_len, burst_len));
+}
+
+/******************************************************************************
+*
+* Function : Estimate_Speech()
+* Purpose : Estimate speech level
+*
+* Maximum signal level is searched and stored to the variable sp_max.
+* The speech frames must locate within SP_EST_COUNT number of frames.
+* Thus, noisy frames having occasional VAD = "1" decisions will not
+* affect to the estimated speech_level.
+*
+*******************************************************************************/
+
+static void Estimate_Speech(
+ VadVars * st, /* i/o : State structure */
+ Word16 in_level /* level of the input frame */
+ )
+{
+ Word16 alpha;
+
+ /* if the required activity count cannot be achieved, reset counters */
+ if((st->sp_est_cnt - st->sp_max_cnt) > (SP_EST_COUNT - SP_ACTIVITY_COUNT))
+ {
+ st->sp_est_cnt = 0;
+ st->sp_max = 0;
+ st->sp_max_cnt = 0;
+ }
+ st->sp_est_cnt += 1;
+
+ if (((st->vadreg & 0x4000)||(in_level > st->speech_level)) && (in_level > MIN_SPEECH_LEVEL1))
+ {
+ /* update sp_max */
+ if(in_level > st->sp_max)
+ {
+ st->sp_max = in_level;
+ }
+ st->sp_max_cnt += 1;
+
+ if(st->sp_max_cnt >= SP_ACTIVITY_COUNT)
+ {
+ Word16 tmp;
+ /* update speech estimate */
+ tmp = (st->sp_max >> 1); /* scale to get "average" speech level */
+
+ /* select update speed */
+ if(tmp > st->speech_level)
+ {
+ alpha = ALPHA_SP_UP;
+ } else
+ {
+ alpha = ALPHA_SP_DOWN;
+ }
+ if(tmp > MIN_SPEECH_LEVEL2)
+ {
+ st->speech_level = add1(st->speech_level, vo_mult_r(alpha, vo_sub(tmp, st->speech_level)));
+ }
+ /* clear all counters used for speech estimation */
+ st->sp_max = 0;
+ st->sp_max_cnt = 0;
+ st->sp_est_cnt = 0;
+ }
+ }
+}
+
+/******************************************************************************
+*
+* Function: wb_vad_init
+* Purpose: Allocates state memory and initializes state memory
+*
+*******************************************************************************/
+
+Word16 wb_vad_init( /* return: non-zero with error, zero for ok. */
+ VadVars ** state, /* i/o : State structure */
+ VO_MEM_OPERATOR *pMemOP
+ )
+{
+ VadVars *s;
+
+ if (state == (VadVars **) NULL)
+ {
+ fprintf(stderr, "vad_init: invalid parameter\n");
+ return -1;
+ }
+ *state = NULL;
+
+ /* allocate memory */
+ if ((s = (VadVars *) mem_malloc(pMemOP, sizeof(VadVars), 32, VO_INDEX_ENC_AMRWB)) == NULL)
+ {
+ fprintf(stderr, "vad_init: can not malloc state structure\n");
+ return -1;
+ }
+ wb_vad_reset(s);
+
+ *state = s;
+
+ return 0;
+}
+
+/******************************************************************************
+*
+* Function: wb_vad_reset
+* Purpose: Initializes state memory
+*
+*******************************************************************************/
+
+Word16 wb_vad_reset( /* return: non-zero with error, zero for ok. */
+ VadVars * state /* i/o : State structure */
+ )
+{
+ Word32 i, j;
+
+ if (state == (VadVars *) NULL)
+ {
+ fprintf(stderr, "vad_reset: invalid parameter\n");
+ return -1;
+ }
+ state->tone_flag = 0;
+ state->vadreg = 0;
+ state->hang_count = 0;
+ state->burst_count = 0;
+ state->hang_count = 0;
+
+ /* initialize memory used by the filter bank */
+ for (i = 0; i < F_5TH_CNT; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ state->a_data5[i][j] = 0;
+ }
+ }
+
+ for (i = 0; i < F_3TH_CNT; i++)
+ {
+ state->a_data3[i] = 0;
+ }
+
+ /* initialize the rest of the memory */
+ for (i = 0; i < COMPLEN; i++)
+ {
+ state->bckr_est[i] = NOISE_INIT;
+ state->old_level[i] = NOISE_INIT;
+ state->ave_level[i] = NOISE_INIT;
+ state->sub_level[i] = 0;
+ }
+
+ state->sp_est_cnt = 0;
+ state->sp_max = 0;
+ state->sp_max_cnt = 0;
+ state->speech_level = SPEECH_LEVEL_INIT;
+ state->prev_pow_sum = 0;
+ return 0;
+}
+
+/******************************************************************************
+*
+* Function: wb_vad_exit
+* Purpose: The memory used for state memory is freed
+*
+*******************************************************************************/
+
+void wb_vad_exit(
+ VadVars ** state, /* i/o : State structure */
+ VO_MEM_OPERATOR *pMemOP
+ )
+{
+ if (state == NULL || *state == NULL)
+ return;
+ /* deallocate memory */
+ mem_free(pMemOP, *state, VO_INDEX_ENC_AMRWB);
+ *state = NULL;
+ return;
+}
+
+/******************************************************************************
+*
+* Function : wb_vad_tone_detection
+* Purpose : Search maximum pitch gain from a frame. Set tone flag if
+* pitch gain is high. This is used to detect
+* signaling tones and other signals with high pitch gain.
+*
+*******************************************************************************/
+
+void wb_vad_tone_detection(
+ VadVars * st, /* i/o : State struct */
+ Word16 p_gain /* pitch gain */
+ )
+{
+ /* update tone flag */
+ st->tone_flag = (st->tone_flag >> 1);
+
+ /* if (pitch_gain > TONE_THR) set tone flag */
+ if (p_gain > TONE_THR)
+ {
+ st->tone_flag = (Word16) (st->tone_flag | 0x4000);
+ }
+}
+
+/******************************************************************************
+*
+* Function : wb_vad
+* Purpose : Main program for Voice Activity Detection (VAD) for AMR
+*
+*******************************************************************************/
+
+Word16 wb_vad( /* Return value : VAD Decision, 1 = speech, 0 = noise */
+ VadVars * st, /* i/o : State structure */
+ Word16 in_buf[] /* i : samples of the input frame */
+ )
+{
+ Word16 level[COMPLEN];
+ Word32 i;
+ Word16 VAD_flag, temp;
+ Word32 L_temp, pow_sum;
+
+ /* Calculate power of the input frame. */
+ L_temp = 0L;
+ for (i = 0; i < FRAME_LEN; i++)
+ {
+ L_temp = L_mac(L_temp, in_buf[i], in_buf[i]);
+ }
+
+ /* pow_sum = power of current frame and previous frame */
+ pow_sum = L_add(L_temp, st->prev_pow_sum);
+
+ /* save power of current frame for next call */
+ st->prev_pow_sum = L_temp;
+
+ /* If input power is very low, clear tone flag */
+ if (pow_sum < POW_TONE_THR)
+ {
+ st->tone_flag = (Word16) (st->tone_flag & 0x1fff);
+ }
+ /* Run the filter bank and calculate signal levels at each band */
+ filter_bank(st, in_buf, level);
+
+ /* compute VAD decision */
+ VAD_flag = vad_decision(st, level, pow_sum);
+
+ /* Calculate input level */
+ L_temp = 0;
+ for (i = 1; i < COMPLEN; i++) /* ignore lowest band */
+ {
+ L_temp = vo_L_add(L_temp, level[i]);
+ }
+
+ temp = extract_h(L_temp << 12);
+
+ Estimate_Speech(st, temp); /* Estimate speech level */
+ return (VAD_flag);
+}
+
+
+
+
diff --git a/media/libstagefright/codecs/amrwbenc/src/weight_a.c b/media/libstagefright/codecs/amrwbenc/src/weight_a.c
new file mode 100644
index 0000000..d47be97
--- /dev/null
+++ b/media/libstagefright/codecs/amrwbenc/src/weight_a.c
@@ -0,0 +1,48 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: weight_a.c *
+* *
+* Description:Weighting of LPC coefficients *
+* ap[i] = a[i] * (gamma ** i) *
+* *
+************************************************************************/
+
+#include "typedef.h"
+#include "basic_op.h"
+
+void Weight_a(
+ Word16 a[], /* (i) Q12 : a[m+1] LPC coefficients */
+ Word16 ap[], /* (o) Q12 : Spectral expanded LPC coefficients */
+ Word16 gamma, /* (i) Q15 : Spectral expansion factor. */
+ Word16 m /* (i) : LPC order. */
+ )
+{
+ Word32 num = m - 1, fac;
+ *ap++ = *a++;
+ fac = gamma;
+ do{
+ *ap++ =(Word16)(((vo_L_mult((*a++), fac)) + 0x8000) >> 16);
+ fac = (vo_L_mult(fac, gamma) + 0x8000) >> 16;
+ }while(--num != 0);
+
+ *ap++ = (Word16)(((vo_L_mult((*a++), fac)) + 0x8000) >> 16);
+ return;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
index aa2a3d1..050e3da 100644
--- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
+++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp
@@ -34,6 +34,8 @@
namespace android {
+static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };
+
static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
return reinterpret_cast<int32_t>(malloc(size));
}
@@ -49,7 +51,9 @@ AVCDecoder::AVCDecoder(const sp<MediaSource> &source)
mInputBuffer(NULL),
mAnchorTimeUs(0),
mNumSamplesOutput(0),
- mPendingSeekTimeUs(-1) {
+ mPendingSeekTimeUs(-1),
+ mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC),
+ mTargetTimeUs(-1) {
memset(mHandle, 0, sizeof(tagAVCHandle));
mHandle->AVCObject = NULL;
mHandle->userData = this;
@@ -154,22 +158,23 @@ status_t AVCDecoder::start(MetaData *) {
}
}
- sp<MetaData> params = new MetaData;
- params->setInt32(kKeyWantsNALFragments, true);
- mSource->start(params.get());
+ mSource->start();
mAnchorTimeUs = 0;
mNumSamplesOutput = 0;
mPendingSeekTimeUs = -1;
+ mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
+ mTargetTimeUs = -1;
mStarted = true;
return OK;
}
void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
- MediaBuffer *buffer = new MediaBuffer(size);
- memcpy(buffer->data(), data, size);
- buffer->set_range(0, size);
+ MediaBuffer *buffer = new MediaBuffer(size + 4);
+ memcpy(buffer->data(), kStartCode, 4);
+ memcpy((uint8_t *)buffer->data() + 4, data, size);
+ buffer->set_range(0, size + 4);
mCodecSpecificData.push(buffer);
}
@@ -200,16 +205,41 @@ sp<MetaData> AVCDecoder::getFormat() {
return mFormat;
}
+static void findNALFragment(
+ const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) {
+ const uint8_t *data =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+
+ size_t size = buffer->range_length();
+
+ CHECK(size >= 4);
+ CHECK(!memcmp(kStartCode, data, 4));
+
+ size_t offset = 4;
+ while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
+ ++offset;
+ }
+
+ *fragPtr = &data[4];
+ if (offset + 3 >= size) {
+ *fragSize = size - 4;
+ } else {
+ *fragSize = offset - 4;
+ }
+}
+
status_t AVCDecoder::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
LOGV("seek requested to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
CHECK(seekTimeUs >= 0);
mPendingSeekTimeUs = seekTimeUs;
+ mPendingSeekMode = mode;
if (mInputBuffer) {
mInputBuffer->release();
@@ -222,6 +252,8 @@ status_t AVCDecoder::read(
if (mInputBuffer == NULL) {
LOGV("fetching new input buffer.");
+ bool seeking = false;
+
if (!mCodecSpecificData.isEmpty()) {
mInputBuffer = mCodecSpecificData.editItemAt(0);
mCodecSpecificData.removeAt(0);
@@ -234,7 +266,9 @@ status_t AVCDecoder::read(
ReadOptions seekOptions;
if (mPendingSeekTimeUs >= 0) {
- seekOptions.setSeekTo(mPendingSeekTimeUs);
+ seeking = true;
+
+ seekOptions.setSeekTo(mPendingSeekTimeUs, mPendingSeekMode);
mPendingSeekTimeUs = -1;
}
status_t err = mSource->read(&mInputBuffer, &seekOptions);
@@ -252,39 +286,43 @@ status_t AVCDecoder::read(
mInputBuffer = NULL;
}
}
+
+ if (seeking) {
+ int64_t targetTimeUs;
+ if (mInputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
+ && targetTimeUs >= 0) {
+ mTargetTimeUs = targetTimeUs;
+ } else {
+ mTargetTimeUs = -1;
+ }
+ }
}
- const uint8_t *inPtr =
- (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
+ const uint8_t *fragPtr;
+ size_t fragSize;
+ findNALFragment(mInputBuffer, &fragPtr, &fragSize);
+
+ bool releaseFragment = true;
+ status_t err = UNKNOWN_ERROR;
int nalType;
int nalRefIdc;
AVCDec_Status res =
PVAVCDecGetNALType(
- const_cast<uint8_t *>(inPtr), mInputBuffer->range_length(),
+ const_cast<uint8_t *>(fragPtr), fragSize,
&nalType, &nalRefIdc);
if (res != AVCDEC_SUCCESS) {
LOGE("cannot determine nal type");
-
- mInputBuffer->release();
- mInputBuffer = NULL;
-
- return UNKNOWN_ERROR;
- }
-
- switch (nalType) {
+ } else switch (nalType) {
case AVC_NALTYPE_SPS:
{
res = PVAVCDecSeqParamSet(
- mHandle, const_cast<uint8_t *>(inPtr),
- mInputBuffer->range_length());
+ mHandle, const_cast<uint8_t *>(fragPtr),
+ fragSize);
if (res != AVCDEC_SUCCESS) {
- mInputBuffer->release();
- mInputBuffer = NULL;
-
- return UNKNOWN_ERROR;
+ break;
}
AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
@@ -324,100 +362,128 @@ status_t AVCDecoder::read(
int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15;
int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15;
- mFormat->setInt32(kKeyWidth, aligned_width);
- mFormat->setInt32(kKeyHeight, aligned_height);
- mInputBuffer->release();
- mInputBuffer = NULL;
+ int32_t oldWidth, oldHeight;
+ CHECK(mFormat->findInt32(kKeyWidth, &oldWidth));
+ CHECK(mFormat->findInt32(kKeyHeight, &oldHeight));
+
+ if (oldWidth != aligned_width || oldHeight != aligned_height) {
+ mFormat->setInt32(kKeyWidth, aligned_width);
+ mFormat->setInt32(kKeyHeight, aligned_height);
- return INFO_FORMAT_CHANGED;
+ err = INFO_FORMAT_CHANGED;
+ } else {
+ *out = new MediaBuffer(0);
+ err = OK;
+ }
+ break;
}
case AVC_NALTYPE_PPS:
{
res = PVAVCDecPicParamSet(
- mHandle, const_cast<uint8_t *>(inPtr),
- mInputBuffer->range_length());
-
- mInputBuffer->release();
- mInputBuffer = NULL;
+ mHandle, const_cast<uint8_t *>(fragPtr),
+ fragSize);
if (res != AVCDEC_SUCCESS) {
- return UNKNOWN_ERROR;
+ break;
}
*out = new MediaBuffer(0);
- return OK;
+ err = OK;
+ break;
}
case AVC_NALTYPE_SLICE:
case AVC_NALTYPE_IDR:
{
res = PVAVCDecodeSlice(
- mHandle, const_cast<uint8_t *>(inPtr),
- mInputBuffer->range_length());
+ mHandle, const_cast<uint8_t *>(fragPtr),
+ fragSize);
if (res == AVCDEC_PICTURE_OUTPUT_READY) {
int32_t index;
int32_t Release;
AVCFrameIO Output;
Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
- CHECK_EQ(PVAVCDecGetOutput(
- mHandle, &index, &Release, &Output),
+
+ CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output),
AVCDEC_SUCCESS);
CHECK(index >= 0);
CHECK(index < (int32_t)mFrames.size());
- *out = mFrames.editItemAt(index);
- (*out)->set_range(0, (*out)->size());
- (*out)->add_ref();
+ MediaBuffer *mbuf = mFrames.editItemAt(index);
+
+ bool skipFrame = false;
+
+ if (mTargetTimeUs >= 0) {
+ int64_t timeUs;
+ CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
+ CHECK(timeUs <= mTargetTimeUs);
+
+ if (timeUs < mTargetTimeUs) {
+ // We're still waiting for the frame with the matching
+ // timestamp and we won't return the current one.
+ skipFrame = true;
+
+ LOGV("skipping frame at %lld us", timeUs);
+ } else {
+ LOGV("found target frame at %lld us", timeUs);
+
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (!skipFrame) {
+ *out = mbuf;
+ (*out)->set_range(0, (*out)->size());
+ (*out)->add_ref();
+ } else {
+ *out = new MediaBuffer(0);
+ }
// Do _not_ release input buffer yet.
- return OK;
+ releaseFragment = false;
+ err = OK;
+ break;
}
- mInputBuffer->release();
- mInputBuffer = NULL;
-
if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
*out = new MediaBuffer(0);
- return OK;
+ err = OK;
} else {
LOGV("failed to decode frame (res = %d)", res);
- return UNKNOWN_ERROR;
}
+ break;
}
case AVC_NALTYPE_SEI:
{
res = PVAVCDecSEI(
- mHandle, const_cast<uint8_t *>(inPtr),
- mInputBuffer->range_length());
-
- mInputBuffer->release();
- mInputBuffer = NULL;
+ mHandle, const_cast<uint8_t *>(fragPtr),
+ fragSize);
if (res != AVCDEC_SUCCESS) {
- return UNKNOWN_ERROR;
+ break;
}
*out = new MediaBuffer(0);
- return OK;
+ err = OK;
+ break;
}
case AVC_NALTYPE_AUD:
+ case AVC_NALTYPE_FILL:
{
- mInputBuffer->release();
- mInputBuffer = NULL;
-
*out = new MediaBuffer(0);
- return OK;
+ err = OK;
+ break;
}
default:
@@ -428,10 +494,19 @@ status_t AVCDecoder::read(
}
}
- mInputBuffer->release();
- mInputBuffer = NULL;
+ if (releaseFragment) {
+ size_t offset = mInputBuffer->range_offset();
+ if (fragSize + 4 == mInputBuffer->range_length()) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ } else {
+ mInputBuffer->set_range(
+ offset + fragSize + 4,
+ mInputBuffer->range_length() - fragSize - 4);
+ }
+ }
- return UNKNOWN_ERROR;
+ return err;
}
// static
diff --git a/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
new file mode 100644
index 0000000..d5eb156
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/AVCEncoder.cpp
@@ -0,0 +1,492 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AVCEncoder"
+#include <utils/Log.h>
+
+#include "AVCEncoder.h"
+
+#include "avcenc_api.h"
+#include "avcenc_int.h"
+#include "OMX_Video.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+inline static void ConvertYUV420SemiPlanarToYUV420Planar(
+ uint8_t *inyuv, uint8_t* outyuv,
+ int32_t width, int32_t height) {
+
+ int32_t outYsize = width * height;
+ uint32_t *outy = (uint32_t *) outyuv;
+ uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
+ uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
+
+ /* Y copying */
+ memcpy(outy, inyuv, outYsize);
+
+ /* U & V copying */
+ uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
+ for (int32_t i = height >> 1; i > 0; --i) {
+ for (int32_t j = width >> 2; j > 0; --j) {
+ uint32_t temp = *inyuv_4++;
+ uint32_t tempU = temp & 0xFF;
+ tempU = tempU | ((temp >> 8) & 0xFF00);
+
+ uint32_t tempV = (temp >> 8) & 0xFF;
+ tempV = tempV | ((temp >> 16) & 0xFF00);
+
+ // Flip U and V
+ *outcb++ = tempV;
+ *outcr++ = tempU;
+ }
+ }
+}
+
+static int32_t MallocWrapper(
+ void *userData, int32_t size, int32_t attrs) {
+ return reinterpret_cast<int32_t>(malloc(size));
+}
+
+static void FreeWrapper(void *userData, int32_t ptr) {
+ free(reinterpret_cast<void *>(ptr));
+}
+
+static int32_t DpbAllocWrapper(void *userData,
+ unsigned int sizeInMbs, unsigned int numBuffers) {
+ AVCEncoder *encoder = static_cast<AVCEncoder *>(userData);
+ CHECK(encoder != NULL);
+ return encoder->allocOutputBuffers(sizeInMbs, numBuffers);
+}
+
+static int32_t BindFrameWrapper(
+ void *userData, int32_t index, uint8_t **yuv) {
+ AVCEncoder *encoder = static_cast<AVCEncoder *>(userData);
+ CHECK(encoder != NULL);
+ return encoder->bindOutputBuffer(index, yuv);
+}
+
+static void UnbindFrameWrapper(void *userData, int32_t index) {
+ AVCEncoder *encoder = static_cast<AVCEncoder *>(userData);
+ CHECK(encoder != NULL);
+ return encoder->unbindOutputBuffer(index);
+}
+
+AVCEncoder::AVCEncoder(
+ const sp<MediaSource>& source,
+ const sp<MetaData>& meta)
+ : mSource(source),
+ mMeta(meta),
+ mNumInputFrames(-1),
+ mStarted(false),
+ mInputBuffer(NULL),
+ mInputFrameData(NULL),
+ mGroup(NULL) {
+
+ LOGV("Construct software AVCEncoder");
+
+ mHandle = new tagAVCHandle;
+ memset(mHandle, 0, sizeof(tagAVCHandle));
+ mHandle->AVCObject = NULL;
+ mHandle->userData = this;
+ mHandle->CBAVC_DPBAlloc = DpbAllocWrapper;
+ mHandle->CBAVC_FrameBind = BindFrameWrapper;
+ mHandle->CBAVC_FrameUnbind = UnbindFrameWrapper;
+ mHandle->CBAVC_Malloc = MallocWrapper;
+ mHandle->CBAVC_Free = FreeWrapper;
+
+ mInitCheck = initCheck(meta);
+}
+
+AVCEncoder::~AVCEncoder() {
+ LOGV("Destruct software AVCEncoder");
+ if (mStarted) {
+ stop();
+ }
+
+ delete mEncParams;
+ delete mHandle;
+}
+
+status_t AVCEncoder::initCheck(const sp<MetaData>& meta) {
+ LOGV("initCheck");
+ CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
+ CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
+ CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
+ CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
+
+ // XXX: Add more color format support
+ CHECK(meta->findInt32(kKeyColorFormat, &mVideoColorFormat));
+ if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
+ LOGE("Color format %d is not supported", mVideoColorFormat);
+ return BAD_VALUE;
+ }
+ // Allocate spare buffer only when color conversion is needed.
+ // Assume the color format is OMX_COLOR_FormatYUV420SemiPlanar.
+ mInputFrameData =
+ (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+ CHECK(mInputFrameData);
+ }
+
+ // XXX: Remove this restriction
+ if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+ LOGE("Video frame size %dx%d must be a multiple of 16",
+ mVideoWidth, mVideoHeight);
+ return BAD_VALUE;
+ }
+
+ mEncParams = new tagAVCEncParam;
+ memset(mEncParams, 0, sizeof(mEncParams));
+ mEncParams->width = mVideoWidth;
+ mEncParams->height = mVideoHeight;
+ mEncParams->frame_rate = 1000 * mVideoFrameRate; // In frames/ms!
+ mEncParams->rate_control = AVC_ON;
+ mEncParams->bitrate = mVideoBitRate;
+ mEncParams->initQP = 0;
+ mEncParams->init_CBP_removal_delay = 1600;
+ mEncParams->CPB_size = (uint32_t) (mVideoBitRate >> 1);
+
+ mEncParams->intramb_refresh = 0;
+ mEncParams->auto_scd = AVC_ON;
+ mEncParams->out_of_band_param_set = AVC_ON;
+ mEncParams->poc_type = 2;
+ mEncParams->log2_max_poc_lsb_minus_4 = 12;
+ mEncParams->delta_poc_zero_flag = 0;
+ mEncParams->offset_poc_non_ref = 0;
+ mEncParams->offset_top_bottom = 0;
+ mEncParams->num_ref_in_cycle = 0;
+ mEncParams->offset_poc_ref = NULL;
+
+ mEncParams->num_ref_frame = 1;
+ mEncParams->num_slice_group = 1;
+ mEncParams->fmo_type = 0;
+
+ mEncParams->db_filter = AVC_ON;
+ mEncParams->disable_db_idc = 0;
+
+ mEncParams->alpha_offset = 0;
+ mEncParams->beta_offset = 0;
+ mEncParams->constrained_intra_pred = AVC_OFF;
+
+ mEncParams->data_par = AVC_OFF;
+ mEncParams->fullsearch = AVC_OFF;
+ mEncParams->search_range = 16;
+ mEncParams->sub_pel = AVC_OFF;
+ mEncParams->submb_pred = AVC_OFF;
+ mEncParams->rdopt_mode = AVC_OFF;
+ mEncParams->bidir_pred = AVC_OFF;
+ int32_t nMacroBlocks = ((((mVideoWidth + 15) >> 4) << 4) *
+ (((mVideoHeight + 15) >> 4) << 4)) >> 8;
+ uint32_t *sliceGroup = (uint32_t *) malloc(sizeof(uint32_t) * nMacroBlocks);
+ for (int ii = 0, idx = 0; ii < nMacroBlocks; ++ii) {
+ sliceGroup[ii] = idx++;
+ if (idx >= mEncParams->num_slice_group) {
+ idx = 0;
+ }
+ }
+ mEncParams->slice_group = sliceGroup;
+
+ mEncParams->use_overrun_buffer = AVC_OFF;
+
+ // Set IDR frame refresh interval
+ int32_t iFramesIntervalSec;
+ CHECK(meta->findInt32(kKeyIFramesInterval, &iFramesIntervalSec));
+ if (iFramesIntervalSec < 0) {
+ mEncParams->idr_period = -1;
+ } else if (iFramesIntervalSec == 0) {
+ mEncParams->idr_period = 1; // All I frames
+ } else {
+ mEncParams->idr_period =
+ (iFramesIntervalSec * mVideoFrameRate);
+ }
+ LOGV("idr_period: %d, I-frames interval: %d seconds, and frame rate: %d",
+ mEncParams->idr_period, iFramesIntervalSec, mVideoFrameRate);
+
+ // Set profile and level
+ // If profile and level setting is not correct, failure
+ // is reported when the encoder is initialized.
+ mEncParams->profile = AVC_BASELINE;
+ mEncParams->level = AVC_LEVEL3_2;
+ int32_t profile, level;
+ if (meta->findInt32(kKeyVideoProfile, &profile)) {
+ mEncParams->profile = (AVCProfile) profile;
+ }
+ if (meta->findInt32(kKeyVideoLevel, &level)) {
+ mEncParams->level = (AVCLevel) level;
+ }
+
+
+ mFormat = new MetaData;
+ mFormat->setInt32(kKeyWidth, mVideoWidth);
+ mFormat->setInt32(kKeyHeight, mVideoHeight);
+ mFormat->setInt32(kKeyBitRate, mVideoBitRate);
+ mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
+ mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ mFormat->setCString(kKeyDecoderComponent, "AVCEncoder");
+ return OK;
+}
+
+status_t AVCEncoder::start(MetaData *params) {
+ LOGV("start");
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mStarted) {
+ LOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ AVCEnc_Status err;
+ err = PVAVCEncInitialize(mHandle, mEncParams, NULL, NULL);
+ if (err != AVCENC_SUCCESS) {
+ LOGE("Failed to initialize the encoder: %d", err);
+ return UNKNOWN_ERROR;
+ }
+
+ mGroup = new MediaBufferGroup();
+ int32_t maxSize;
+ if (AVCENC_SUCCESS !=
+ PVAVCEncGetMaxOutputBufferSize(mHandle, &maxSize)) {
+ maxSize = 31584; // Magic #
+ }
+ mGroup->add_buffer(new MediaBuffer(maxSize));
+
+ mSource->start(params);
+ mNumInputFrames = -2; // 1st two buffers contain SPS and PPS
+ mStarted = true;
+ mSpsPpsHeaderReceived = false;
+ mReadyForNextFrame = true;
+ mIsIDRFrame = 0;
+
+ return OK;
+}
+
+status_t AVCEncoder::stop() {
+ LOGV("stop");
+ if (!mStarted) {
+ LOGW("Call stop() when encoder has not started");
+ return OK;
+ }
+
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ if (mGroup) {
+ delete mGroup;
+ mGroup = NULL;
+ }
+
+ if (mInputFrameData) {
+ delete mInputFrameData;
+ mInputFrameData = NULL;
+ }
+
+ PVAVCCleanUpEncoder(mHandle);
+ mSource->stop();
+ releaseOutputBuffers();
+ mStarted = false;
+
+ return OK;
+}
+
+void AVCEncoder::releaseOutputBuffers() {
+ LOGV("releaseOutputBuffers");
+ for (size_t i = 0; i < mOutputBuffers.size(); ++i) {
+ MediaBuffer *buffer = mOutputBuffers.editItemAt(i);
+ buffer->setObserver(NULL);
+ buffer->release();
+ }
+ mOutputBuffers.clear();
+}
+
+sp<MetaData> AVCEncoder::getFormat() {
+ LOGV("getFormat");
+ return mFormat;
+}
+
+status_t AVCEncoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+
+ CHECK(!options);
+ *out = NULL;
+
+ MediaBuffer *outputBuffer;
+ CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
+ uint8_t *outPtr = (uint8_t *) outputBuffer->data();
+ uint32_t dataLength = outputBuffer->size();
+
+ int32_t type;
+ AVCEnc_Status encoderStatus = AVCENC_SUCCESS;
+
+ // Return SPS and PPS for the first two buffers
+ if (!mSpsPpsHeaderReceived) {
+ encoderStatus = PVAVCEncodeNAL(mHandle, outPtr, &dataLength, &type);
+ if (encoderStatus == AVCENC_WRONG_STATE) {
+ mSpsPpsHeaderReceived = true;
+ CHECK_EQ(0, mNumInputFrames); // 1st video frame is 0
+ } else {
+ switch (type) {
+ case AVC_NALTYPE_SPS:
+ case AVC_NALTYPE_PPS:
+ LOGV("%s received",
+ (type == AVC_NALTYPE_SPS)? "SPS": "PPS");
+ ++mNumInputFrames;
+ outputBuffer->set_range(0, dataLength);
+ *out = outputBuffer;
+ return OK;
+ default:
+ LOGE("Nal type (%d) other than SPS/PPS is unexpected", type);
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+
+ // Get next input video frame
+ if (mReadyForNextFrame) {
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+ status_t err = mSource->read(&mInputBuffer, options);
+ if (err != OK) {
+ LOGE("Failed to read input video frame: %d", err);
+ outputBuffer->release();
+ return err;
+ }
+ int64_t timeUs;
+ CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+ AVCFrameIO videoInput;
+ memset(&videoInput, 0, sizeof(videoInput));
+ videoInput.height = ((mVideoHeight + 15) >> 4) << 4;
+ videoInput.pitch = ((mVideoWidth + 15) >> 4) << 4;
+ videoInput.coding_timestamp = (timeUs + 500) / 1000; // in ms
+ uint8_t *inputData = (uint8_t *) mInputBuffer->data();
+
+ if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ CHECK(mInputFrameData);
+ CHECK(mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar);
+ ConvertYUV420SemiPlanarToYUV420Planar(
+ inputData, mInputFrameData, mVideoWidth, mVideoHeight);
+ inputData = mInputFrameData;
+ }
+ CHECK(inputData != NULL);
+ videoInput.YCbCr[0] = inputData;
+ videoInput.YCbCr[1] = videoInput.YCbCr[0] + videoInput.height * videoInput.pitch;
+ videoInput.YCbCr[2] = videoInput.YCbCr[1] +
+ ((videoInput.height * videoInput.pitch) >> 2);
+ videoInput.disp_order = mNumInputFrames;
+
+ encoderStatus = PVAVCEncSetInput(mHandle, &videoInput);
+ if (encoderStatus == AVCENC_SUCCESS ||
+ encoderStatus == AVCENC_NEW_IDR) {
+ mReadyForNextFrame = false;
+ ++mNumInputFrames;
+ if (encoderStatus == AVCENC_NEW_IDR) {
+ mIsIDRFrame = 1;
+ }
+ } else {
+ if (encoderStatus < AVCENC_SUCCESS) {
+ outputBuffer->release();
+ return UNKNOWN_ERROR;
+ } else {
+ outputBuffer->set_range(0, 0);
+ *out = outputBuffer;
+ return OK;
+ }
+ }
+ }
+
+ // Encode an input video frame
+ CHECK(encoderStatus == AVCENC_SUCCESS ||
+ encoderStatus == AVCENC_NEW_IDR);
+ dataLength = outputBuffer->size(); // Reset the output buffer length
+ encoderStatus = PVAVCEncodeNAL(mHandle, outPtr, &dataLength, &type);
+ if (encoderStatus == AVCENC_SUCCESS) {
+ outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, mIsIDRFrame);
+ CHECK_EQ(NULL, PVAVCEncGetOverrunBuffer(mHandle));
+ } else if (encoderStatus == AVCENC_PICTURE_READY) {
+ CHECK_EQ(NULL, PVAVCEncGetOverrunBuffer(mHandle));
+ if (mIsIDRFrame) {
+ outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, mIsIDRFrame);
+ mIsIDRFrame = 0;
+ LOGV("Output an IDR frame");
+ }
+ mReadyForNextFrame = true;
+ AVCFrameIO recon;
+ if (PVAVCEncGetRecon(mHandle, &recon) == AVCENC_SUCCESS) {
+ PVAVCEncReleaseRecon(mHandle, &recon);
+ }
+ } else {
+ dataLength = 0;
+ mReadyForNextFrame = true;
+ }
+ if (encoderStatus < AVCENC_SUCCESS) {
+ outputBuffer->release();
+ return UNKNOWN_ERROR;
+ }
+
+ outputBuffer->set_range(0, dataLength);
+ *out = outputBuffer;
+ return OK;
+}
+
+int32_t AVCEncoder::allocOutputBuffers(
+ unsigned int sizeInMbs, unsigned int numBuffers) {
+ CHECK(mOutputBuffers.isEmpty());
+ size_t frameSize = (sizeInMbs << 7) * 3;
+ for (unsigned int i = 0; i < numBuffers; ++i) {
+ MediaBuffer *buffer = new MediaBuffer(frameSize);
+ buffer->setObserver(this);
+ mOutputBuffers.push(buffer);
+ }
+
+ return 1;
+}
+
+void AVCEncoder::unbindOutputBuffer(int32_t index) {
+ CHECK(index >= 0);
+}
+
+int32_t AVCEncoder::bindOutputBuffer(int32_t index, uint8_t **yuv) {
+ CHECK(index >= 0);
+ CHECK(index < (int32_t) mOutputBuffers.size());
+ int64_t timeUs;
+ CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ mOutputBuffers[index]->meta_data()->setInt64(kKeyTime, timeUs);
+
+ *yuv = (uint8_t *) mOutputBuffers[index]->data();
+
+ return 1;
+}
+
+void AVCEncoder::signalBufferReturned(MediaBuffer *buffer) {
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/avc/enc/Android.mk b/media/libstagefright/codecs/avc/enc/Android.mk
new file mode 100644
index 0000000..100f239
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/Android.mk
@@ -0,0 +1,35 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ AVCEncoder.cpp \
+ src/avcenc_api.cpp \
+ src/bitstream_io.cpp \
+ src/block.cpp \
+ src/findhalfpel.cpp \
+ src/header.cpp \
+ src/init.cpp \
+ src/intra_est.cpp \
+ src/motion_comp.cpp \
+ src/motion_est.cpp \
+ src/rate_control.cpp \
+ src/residual.cpp \
+ src/sad.cpp \
+ src/sad_halfpel.cpp \
+ src/slice.cpp \
+ src/vlc_encode.cpp
+
+
+LOCAL_MODULE := libstagefright_avcenc
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/../common/include \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/frameworks/base/media/libstagefright/include
+
+LOCAL_CFLAGS := \
+ -D__arm__ \
+ -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp b/media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp
new file mode 100644
index 0000000..d39885d
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_api.cpp
@@ -0,0 +1,744 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_api.h"
+#include "avcenc_lib.h"
+
+/* ======================================================================== */
+/* Function : PVAVCGetNALType() */
+/* Date : 11/4/2003 */
+/* Purpose : Sniff NAL type from the bitstream */
+/* In/out : */
+/* Return : AVCENC_SUCCESS if succeed, AVCENC_FAIL if fail. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncGetNALType(unsigned char *bitstream, int size,
+ int *nal_type, int *nal_ref_idc)
+{
+ int forbidden_zero_bit;
+ if (size > 0)
+ {
+ forbidden_zero_bit = bitstream[0] >> 7;
+ if (forbidden_zero_bit != 0)
+ return AVCENC_FAIL;
+ *nal_ref_idc = (bitstream[0] & 0x60) >> 5;
+ *nal_type = bitstream[0] & 0x1F;
+ return AVCENC_SUCCESS;
+ }
+
+ return AVCENC_FAIL;
+}
+
+
+/* ======================================================================== */
+/* Function : PVAVCEncInitialize() */
+/* Date : 3/18/2004 */
+/* Purpose : Initialize the encoder library, allocate memory and verify */
+/* the profile/level support/settings. */
+/* In/out : Encoding parameters. */
+/* Return : AVCENC_SUCCESS for success. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncInitialize(AVCHandle *avcHandle, AVCEncParams *encParam,
+ void* extSPS, void* extPPS)
+{
+ AVCEnc_Status status;
+ AVCEncObject *encvid;
+ AVCCommonObj *video;
+ uint32 *userData = (uint32*) avcHandle->userData;
+ int framesize;
+
+ if (avcHandle->AVCObject != NULL)
+ {
+ return AVCENC_ALREADY_INITIALIZED; /* It's already initialized, need to cleanup first */
+ }
+
+ /* not initialized */
+
+ /* allocate videoObject */
+ avcHandle->AVCObject = (void*)avcHandle->CBAVC_Malloc(userData, sizeof(AVCEncObject), DEFAULT_ATTR);
+ if (avcHandle->AVCObject == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ encvid = (AVCEncObject*) avcHandle->AVCObject;
+ memset(encvid, 0, sizeof(AVCEncObject)); /* reset everything */
+
+ encvid->enc_state = AVCEnc_Initializing;
+
+ encvid->avcHandle = avcHandle;
+
+ encvid->common = (AVCCommonObj*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCCommonObj), DEFAULT_ATTR);
+ if (encvid->common == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ video = encvid->common;
+ memset(video, 0, sizeof(AVCCommonObj));
+
+ /* allocate bitstream structure */
+ encvid->bitstream = (AVCEncBitstream*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCEncBitstream), DEFAULT_ATTR);
+ if (encvid->bitstream == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ encvid->bitstream->encvid = encvid; /* to point back for reallocation */
+
+ /* allocate sequence parameter set structure */
+ video->currSeqParams = (AVCSeqParamSet*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSeqParamSet), DEFAULT_ATTR);
+ if (video->currSeqParams == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ memset(video->currSeqParams, 0, sizeof(AVCSeqParamSet));
+
+ /* allocate picture parameter set structure */
+ video->currPicParams = (AVCPicParamSet*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCPicParamSet), DEFAULT_ATTR);
+ if (video->currPicParams == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ memset(video->currPicParams, 0, sizeof(AVCPicParamSet));
+
+ /* allocate slice header structure */
+ video->sliceHdr = (AVCSliceHeader*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCSliceHeader), DEFAULT_ATTR);
+ if (video->sliceHdr == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ memset(video->sliceHdr, 0, sizeof(AVCSliceHeader));
+
+ /* allocate encoded picture buffer structure*/
+ video->decPicBuf = (AVCDecPicBuffer*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCDecPicBuffer), DEFAULT_ATTR);
+ if (video->decPicBuf == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ memset(video->decPicBuf, 0, sizeof(AVCDecPicBuffer));
+
+ /* allocate rate control structure */
+ encvid->rateCtrl = (AVCRateControl*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCRateControl), DEFAULT_ATTR);
+ if (encvid->rateCtrl == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ memset(encvid->rateCtrl, 0, sizeof(AVCRateControl));
+
+ /* reset frame list, not really needed */
+ video->currPic = NULL;
+ video->currFS = NULL;
+ encvid->currInput = NULL;
+ video->prevRefPic = NULL;
+
+ /* now read encParams, and allocate dimension-dependent variables */
+ /* such as mblock */
+ status = SetEncodeParam(avcHandle, encParam, extSPS, extPPS); /* initialized variables to be used in SPS*/
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ if (encParam->use_overrun_buffer == AVC_ON)
+ {
+ /* allocate overrun buffer */
+ encvid->oBSize = encvid->rateCtrl->cpbSize;
+ if (encvid->oBSize > DEFAULT_OVERRUN_BUFFER_SIZE)
+ {
+ encvid->oBSize = DEFAULT_OVERRUN_BUFFER_SIZE;
+ }
+ encvid->overrunBuffer = (uint8*) avcHandle->CBAVC_Malloc(userData, encvid->oBSize, DEFAULT_ATTR);
+ if (encvid->overrunBuffer == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ }
+ else
+ {
+ encvid->oBSize = 0;
+ encvid->overrunBuffer = NULL;
+ }
+
+ /* allocate frame size dependent structures */
+ framesize = video->FrameHeightInMbs * video->PicWidthInMbs;
+
+ video->mblock = (AVCMacroblock*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMacroblock) * framesize, DEFAULT_ATTR);
+ if (video->mblock == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ video->MbToSliceGroupMap = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits * 2, DEFAULT_ATTR);
+ if (video->MbToSliceGroupMap == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ encvid->mot16x16 = (AVCMV*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCMV) * framesize, DEFAULT_ATTR);
+ if (encvid->mot16x16 == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ memset(encvid->mot16x16, 0, sizeof(AVCMV)*framesize);
+
+ encvid->intraSearch = (uint8*) avcHandle->CBAVC_Malloc(userData, sizeof(uint8) * framesize, DEFAULT_ATTR);
+ if (encvid->intraSearch == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ encvid->min_cost = (int*) avcHandle->CBAVC_Malloc(userData, sizeof(int) * framesize, DEFAULT_ATTR);
+ if (encvid->min_cost == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ /* initialize motion search related memory */
+ if (AVCENC_SUCCESS != InitMotionSearchModule(avcHandle))
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ if (AVCENC_SUCCESS != InitRateControlModule(avcHandle))
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ /* intialize function pointers */
+ encvid->functionPointer = (AVCEncFuncPtr*) avcHandle->CBAVC_Malloc(userData, sizeof(AVCEncFuncPtr), DEFAULT_ATTR);
+ if (encvid->functionPointer == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+ encvid->functionPointer->SAD_Macroblock = &AVCSAD_Macroblock_C;
+ encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
+ encvid->functionPointer->SAD_MB_HalfPel[1] = &AVCSAD_MB_HalfPel_Cxh;
+ encvid->functionPointer->SAD_MB_HalfPel[2] = &AVCSAD_MB_HalfPel_Cyh;
+ encvid->functionPointer->SAD_MB_HalfPel[3] = &AVCSAD_MB_HalfPel_Cxhyh;
+
+ /* initialize timing control */
+ encvid->modTimeRef = 0; /* ALWAYS ASSUME THAT TIMESTAMP START FROM 0 !!!*/
+ video->prevFrameNum = 0;
+ encvid->prevCodedFrameNum = 0;
+ encvid->dispOrdPOCRef = 0;
+
+ if (encvid->outOfBandParamSet == TRUE)
+ {
+ encvid->enc_state = AVCEnc_Encoding_SPS;
+ }
+ else
+ {
+ encvid->enc_state = AVCEnc_Analyzing_Frame;
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCEncGetMaxOutputSize() */
+/* Date : 11/29/2008 */
+/* Purpose : Return max output buffer size that apps should allocate for */
+/* output buffer. */
+/* In/out : */
+/* Return : AVCENC_SUCCESS for success. */
+/* Modified : size */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncGetMaxOutputBufferSize(AVCHandle *avcHandle, int* size)
+{
+ AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+
+ if (encvid == NULL)
+ {
+ return AVCENC_UNINITIALIZED;
+ }
+
+ *size = encvid->rateCtrl->cpbSize;
+
+ return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCEncSetInput() */
+/* Date : 4/18/2004 */
+/* Purpose : To feed an unencoded original frame to the encoder library. */
+/* In/out : */
+/* Return : AVCENC_SUCCESS for success. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncSetInput(AVCHandle *avcHandle, AVCFrameIO *input)
+{
+ AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+ AVCCommonObj *video = encvid->common;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+
+ AVCEnc_Status status;
+ uint frameNum;
+
+ if (encvid == NULL)
+ {
+ return AVCENC_UNINITIALIZED;
+ }
+
+ if (encvid->enc_state == AVCEnc_WaitingForBuffer)
+ {
+ goto RECALL_INITFRAME;
+ }
+ else if (encvid->enc_state != AVCEnc_Analyzing_Frame)
+ {
+ return AVCENC_FAIL;
+ }
+
+ if (input->pitch > 0xFFFF)
+ {
+ return AVCENC_NOT_SUPPORTED; // we use 2-bytes for pitch
+ }
+
+ /***********************************/
+
+ /* Let's rate control decide whether to encode this frame or not */
+ /* Also set video->nal_unit_type, sliceHdr->slice_type, video->slice_type */
+ if (AVCENC_SUCCESS != RCDetermineFrameNum(encvid, rateCtrl, input->coding_timestamp, &frameNum))
+ {
+ return AVCENC_SKIPPED_PICTURE; /* not time to encode, thus skipping */
+ }
+
+ /* we may not need this line */
+ //nextFrmModTime = (uint32)((((frameNum+1)*1000)/rateCtrl->frame_rate) + modTimeRef); /* rec. time */
+ //encvid->nextModTime = nextFrmModTime - (encvid->frameInterval>>1) - 1; /* between current and next frame */
+
+ encvid->currInput = input;
+ encvid->currInput->coding_order = frameNum;
+
+RECALL_INITFRAME:
+ /* initialize and analyze the frame */
+ status = InitFrame(encvid);
+
+ if (status == AVCENC_SUCCESS)
+ {
+ encvid->enc_state = AVCEnc_Encoding_Frame;
+ }
+ else if (status == AVCENC_NEW_IDR)
+ {
+ if (encvid->outOfBandParamSet == TRUE)
+ {
+ encvid->enc_state = AVCEnc_Encoding_Frame;
+ }
+ else // assuming that in-band paramset keeps sending new SPS and PPS.
+ {
+ encvid->enc_state = AVCEnc_Encoding_SPS;
+ //video->currSeqParams->seq_parameter_set_id++;
+ //if(video->currSeqParams->seq_parameter_set_id > 31) // range check
+ {
+ video->currSeqParams->seq_parameter_set_id = 0; // reset
+ }
+ }
+
+ video->sliceHdr->idr_pic_id++;
+ if (video->sliceHdr->idr_pic_id > 65535) // range check
+ {
+ video->sliceHdr->idr_pic_id = 0; // reset
+ }
+ }
+ /* the following logics need to be revisited */
+ else if (status == AVCENC_PICTURE_READY) // no buffers returned back to the encoder
+ {
+ encvid->enc_state = AVCEnc_WaitingForBuffer; // Input accepted but can't continue
+ // need to free up some memory before proceeding with Encode
+ }
+
+ return status; // return status, including the AVCENC_FAIL case and all 3 above.
+}
+
+/* ======================================================================== */
+/* Function : PVAVCEncodeNAL() */
+/* Date : 4/29/2004 */
+/* Purpose : To encode one NAL/slice. */
+/* In/out : */
+/* Return : AVCENC_SUCCESS for success. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncodeNAL(AVCHandle *avcHandle, unsigned char *buffer, unsigned int *buf_nal_size, int *nal_type)
+{
+ AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+ AVCCommonObj *video = encvid->common;
+ AVCEncBitstream *bitstream = encvid->bitstream;
+ AVCEnc_Status status;
+
+ if (encvid == NULL)
+ {
+ return AVCENC_UNINITIALIZED;
+ }
+
+ switch (encvid->enc_state)
+ {
+ case AVCEnc_Initializing:
+ return AVCENC_UNINITIALIZED;
+ case AVCEnc_Encoding_SPS:
+ /* initialized the structure */
+ BitstreamEncInit(bitstream, buffer, *buf_nal_size, NULL, 0);
+ BitstreamWriteBits(bitstream, 8, (1 << 5) | AVC_NALTYPE_SPS);
+
+ /* encode SPS */
+ status = EncodeSPS(encvid, bitstream);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ /* closing the NAL with trailing bits */
+ status = BitstreamTrailingBits(bitstream, buf_nal_size);
+ if (status == AVCENC_SUCCESS)
+ {
+ encvid->enc_state = AVCEnc_Encoding_PPS;
+ video->currPicParams->seq_parameter_set_id = video->currSeqParams->seq_parameter_set_id;
+ video->currPicParams->pic_parameter_set_id++;
+ *nal_type = AVC_NALTYPE_SPS;
+ *buf_nal_size = bitstream->write_pos;
+ }
+ break;
+ case AVCEnc_Encoding_PPS:
+ /* initialized the structure */
+ BitstreamEncInit(bitstream, buffer, *buf_nal_size, NULL, 0);
+ BitstreamWriteBits(bitstream, 8, (1 << 5) | AVC_NALTYPE_PPS);
+
+ /* encode PPS */
+ status = EncodePPS(encvid, bitstream);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ /* closing the NAL with trailing bits */
+ status = BitstreamTrailingBits(bitstream, buf_nal_size);
+ if (status == AVCENC_SUCCESS)
+ {
+ if (encvid->outOfBandParamSet == TRUE) // already extract PPS, SPS
+ {
+ encvid->enc_state = AVCEnc_Analyzing_Frame;
+ }
+ else // SetInput has been called before SPS and PPS.
+ {
+ encvid->enc_state = AVCEnc_Encoding_Frame;
+ }
+
+ *nal_type = AVC_NALTYPE_PPS;
+ *buf_nal_size = bitstream->write_pos;
+ }
+ break;
+
+ case AVCEnc_Encoding_Frame:
+ /* initialized the structure */
+ BitstreamEncInit(bitstream, buffer, *buf_nal_size, encvid->overrunBuffer, encvid->oBSize);
+ BitstreamWriteBits(bitstream, 8, (video->nal_ref_idc << 5) | (video->nal_unit_type));
+
+ /* Re-order the reference list according to the ref_pic_list_reordering() */
+ /* We don't have to reorder the list for the encoder here. This can only be done
+ after we encode this slice. We can run thru a second-pass to see if new ordering
+ would save more bits. Too much delay !! */
+ /* status = ReOrderList(video);*/
+ status = InitSlice(encvid);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ /* when we have everything, we encode the slice header */
+ status = EncodeSliceHeader(encvid, bitstream);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = AVCEncodeSlice(encvid);
+
+ video->slice_id++;
+
+ /* closing the NAL with trailing bits */
+ BitstreamTrailingBits(bitstream, buf_nal_size);
+
+ *buf_nal_size = bitstream->write_pos;
+
+ encvid->rateCtrl->numFrameBits += ((*buf_nal_size) << 3);
+
+ *nal_type = video->nal_unit_type;
+
+ if (status == AVCENC_PICTURE_READY)
+ {
+ status = RCUpdateFrame(encvid);
+ if (status == AVCENC_SKIPPED_PICTURE) /* skip current frame */
+ {
+ DPBReleaseCurrentFrame(avcHandle, video);
+ encvid->enc_state = AVCEnc_Analyzing_Frame;
+
+ return status;
+ }
+
+ /* perform loop-filtering on the entire frame */
+ DeblockPicture(video);
+
+ /* update the original frame array */
+ encvid->prevCodedFrameNum = encvid->currInput->coding_order;
+
+ /* store the encoded picture in the DPB buffer */
+ StorePictureInDPB(avcHandle, video);
+
+ if (video->currPic->isReference)
+ {
+ video->PrevRefFrameNum = video->sliceHdr->frame_num;
+ }
+
+ /* update POC related variables */
+ PostPOC(video);
+
+ encvid->enc_state = AVCEnc_Analyzing_Frame;
+ status = AVCENC_PICTURE_READY;
+
+ }
+ break;
+ default:
+ status = AVCENC_WRONG_STATE;
+ }
+
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : PVAVCEncGetOverrunBuffer() */
+/* Purpose : To retrieve the overrun buffer. Check whether overrun buffer */
+/* is used or not before returning */
+/* In/out : */
+/* Return : Pointer to the internal overrun buffer. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF uint8* PVAVCEncGetOverrunBuffer(AVCHandle* avcHandle)
+{
+ AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+ AVCEncBitstream *bitstream = encvid->bitstream;
+
+ if (bitstream->overrunBuffer == bitstream->bitstreamBuffer) /* OB is used */
+ {
+ return encvid->overrunBuffer;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+/* ======================================================================== */
+/* Function : PVAVCEncGetRecon() */
+/* Date : 4/29/2004 */
+/* Purpose : To retrieve the most recently encoded frame. */
+/* assume that user will make a copy if they want to hold on */
+/* to it. Otherwise, it is not guaranteed to be reserved. */
+/* Most applications prefer to see original frame rather than */
+/* reconstructed frame. So, we are staying aware from complex */
+/* buffering mechanism. If needed, can be added later. */
+/* In/out : */
+/* Return : AVCENC_SUCCESS for success. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncGetRecon(AVCHandle *avcHandle, AVCFrameIO *recon)
+{
+ AVCEncObject *encvid = (AVCEncObject*)avcHandle->AVCObject;
+ AVCCommonObj *video = encvid->common;
+ AVCFrameStore *currFS = video->currFS;
+
+ if (encvid == NULL)
+ {
+ return AVCENC_UNINITIALIZED;
+ }
+
+ recon->YCbCr[0] = currFS->frame.Sl;
+ recon->YCbCr[1] = currFS->frame.Scb;
+ recon->YCbCr[2] = currFS->frame.Scr;
+ recon->height = currFS->frame.height;
+ recon->pitch = currFS->frame.pitch;
+ recon->disp_order = currFS->PicOrderCnt;
+ recon->coding_order = currFS->FrameNum;
+ recon->id = (uint32) currFS->base_dpb; /* use the pointer as the id */
+
+ currFS->IsOutputted |= 1;
+
+ return AVCENC_SUCCESS;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncReleaseRecon(AVCHandle *avcHandle, AVCFrameIO *recon)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(recon);
+
+ return AVCENC_SUCCESS; //for now
+}
+
+/* ======================================================================== */
+/* Function : PVAVCCleanUpEncoder() */
+/* Date : 4/18/2004 */
+/* Purpose : To clean up memories allocated by PVAVCEncInitialize() */
+/* In/out : */
+/* Return : AVCENC_SUCCESS for success. */
+/* Modified : */
+/* ======================================================================== */
+OSCL_EXPORT_REF void PVAVCCleanUpEncoder(AVCHandle *avcHandle)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+ AVCCommonObj *video;
+ uint32 *userData = (uint32*) avcHandle->userData;
+
+ if (encvid != NULL)
+ {
+ CleanMotionSearchModule(avcHandle);
+
+ CleanupRateControlModule(avcHandle);
+
+ if (encvid->functionPointer != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->functionPointer);
+ }
+
+ if (encvid->min_cost)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->min_cost);
+ }
+
+ if (encvid->intraSearch)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->intraSearch);
+ }
+
+ if (encvid->mot16x16)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->mot16x16);
+ }
+
+ if (encvid->rateCtrl)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->rateCtrl);
+ }
+
+ if (encvid->overrunBuffer)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->overrunBuffer);
+ }
+
+ video = encvid->common;
+ if (video != NULL)
+ {
+ if (video->MbToSliceGroupMap)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->MbToSliceGroupMap);
+ }
+ if (video->mblock != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->mblock);
+ }
+ if (video->decPicBuf != NULL)
+ {
+ CleanUpDPB(avcHandle, video);
+ avcHandle->CBAVC_Free(userData, (int)video->decPicBuf);
+ }
+ if (video->sliceHdr != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->sliceHdr);
+ }
+ if (video->currPicParams != NULL)
+ {
+ if (video->currPicParams->slice_group_id)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->currPicParams->slice_group_id);
+ }
+
+ avcHandle->CBAVC_Free(userData, (int)video->currPicParams);
+ }
+ if (video->currSeqParams != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video->currSeqParams);
+ }
+ if (encvid->bitstream != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)encvid->bitstream);
+ }
+ if (video != NULL)
+ {
+ avcHandle->CBAVC_Free(userData, (int)video);
+ }
+ }
+
+ avcHandle->CBAVC_Free(userData, (int)encvid);
+
+ avcHandle->AVCObject = NULL;
+ }
+
+ return ;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateBitRate(AVCHandle *avcHandle, uint32 bitrate)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(bitrate);
+
+ return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateFrameRate(AVCHandle *avcHandle, uint32 num, uint32 denom)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(num);
+ OSCL_UNUSED_ARG(denom);
+
+ return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateIDRInterval(AVCHandle *avcHandle, int IDRInterval)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(IDRInterval);
+
+ return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncIDRRequest(AVCHandle *avcHandle)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+
+ return AVCENC_FAIL;
+}
+
+OSCL_EXPORT_REF AVCEnc_Status PVAVCEncUpdateIMBRefresh(AVCHandle *avcHandle, int numMB)
+{
+ OSCL_UNUSED_ARG(avcHandle);
+ OSCL_UNUSED_ARG(numMB);
+
+ return AVCENC_FAIL;
+}
+
+void PVAVCEncGetFrameStats(AVCHandle *avcHandle, AVCEncFrameStats *avcStats)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+
+ avcStats->avgFrameQP = GetAvgFrameQP(rateCtrl);
+ avcStats->numIntraMBs = encvid->numIntraMB;
+
+ return ;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_api.h b/media/libstagefright/codecs/avc/enc/src/avcenc_api.h
new file mode 100644
index 0000000..6841ec3
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_api.h
@@ -0,0 +1,323 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC encoder library
+and necessary type defitionitions and enumerations.
+@publishedAll
+*/
+
+#ifndef AVCENC_API_H_INCLUDED
+#define AVCENC_API_H_INCLUDED
+
+#ifndef AVCAPI_COMMON_H_INCLUDED
+#include "avcapi_common.h"
+#endif
+
+// For memset, etc
+#include <string.h>
+
+/**
+ This enumeration is used for the status returned from the library interface.
+*/
+typedef enum
+{
+ /**
+ Fail information, need to add more error code for more specific info
+ */
+ AVCENC_TRAILINGONES_FAIL = -35,
+ AVCENC_SLICE_EMPTY = -34,
+ AVCENC_POC_FAIL = -33,
+ AVCENC_CONSECUTIVE_NONREF = -32,
+ AVCENC_CABAC_FAIL = -31,
+ AVCENC_PRED_WEIGHT_TAB_FAIL = -30,
+ AVCENC_DEC_REF_PIC_MARK_FAIL = -29,
+ AVCENC_SPS_FAIL = -28,
+ AVCENC_BITSTREAM_BUFFER_FULL = -27,
+ AVCENC_BITSTREAM_INIT_FAIL = -26,
+ AVCENC_CHROMA_QP_FAIL = -25,
+ AVCENC_INIT_QS_FAIL = -24,
+ AVCENC_INIT_QP_FAIL = -23,
+ AVCENC_WEIGHTED_BIPRED_FAIL = -22,
+ AVCENC_INVALID_INTRA_PERIOD = -21,
+ AVCENC_INVALID_CHANGE_RATE = -20,
+ AVCENC_INVALID_BETA_OFFSET = -19,
+ AVCENC_INVALID_ALPHA_OFFSET = -18,
+ AVCENC_INVALID_DEBLOCK_IDC = -17,
+ AVCENC_INVALID_REDUNDANT_PIC = -16,
+ AVCENC_INVALID_FRAMERATE = -15,
+ AVCENC_INVALID_NUM_SLICEGROUP = -14,
+ AVCENC_INVALID_POC_LSB = -13,
+ AVCENC_INVALID_NUM_REF = -12,
+ AVCENC_INVALID_FMO_TYPE = -11,
+ AVCENC_ENCPARAM_MEM_FAIL = -10,
+ AVCENC_LEVEL_NOT_SUPPORTED = -9,
+ AVCENC_LEVEL_FAIL = -8,
+ AVCENC_PROFILE_NOT_SUPPORTED = -7,
+ AVCENC_TOOLS_NOT_SUPPORTED = -6,
+ AVCENC_WRONG_STATE = -5,
+ AVCENC_UNINITIALIZED = -4,
+ AVCENC_ALREADY_INITIALIZED = -3,
+ AVCENC_NOT_SUPPORTED = -2,
+ AVCENC_MEMORY_FAIL = AVC_MEMORY_FAIL,
+ AVCENC_FAIL = AVC_FAIL,
+ /**
+ Generic success value
+ */
+ AVCENC_SUCCESS = AVC_SUCCESS,
+ AVCENC_PICTURE_READY = 2,
+ AVCENC_NEW_IDR = 3, /* upon getting this, users have to call PVAVCEncodeSPS and PVAVCEncodePPS to get a new SPS and PPS*/
+ AVCENC_SKIPPED_PICTURE = 4 /* continuable error message */
+
+} AVCEnc_Status;
+
+#define MAX_NUM_SLICE_GROUP 8 /* maximum for all the profiles */
+
+/**
+This structure contains the encoding parameters.
+*/
+typedef struct tagAVCEncParam
+{
+ /* if profile/level is set to zero, encoder will choose the closest one for you */
+ AVCProfile profile; /* profile of the bitstream to be compliant with*/
+ AVCLevel level; /* level of the bitstream to be compliant with*/
+
+ int width; /* width of an input frame in pixel */
+ int height; /* height of an input frame in pixel */
+
+ int poc_type; /* picture order count mode, 0,1 or 2 */
+ /* for poc_type == 0 */
+ uint log2_max_poc_lsb_minus_4; /* specify maximum value of POC Lsb, range 0..12*/
+ /* for poc_type == 1 */
+ uint delta_poc_zero_flag; /* delta POC always zero */
+ int offset_poc_non_ref; /* offset for non-reference pic */
+ int offset_top_bottom; /* offset between top and bottom field */
+ uint num_ref_in_cycle; /* number of reference frame in one cycle */
+ int *offset_poc_ref; /* array of offset for ref pic, dimension [num_ref_in_cycle] */
+
+ int num_ref_frame; /* number of reference frame used */
+ int num_slice_group; /* number of slice group */
+ int fmo_type; /* 0: interleave, 1: dispersed, 2: foreground with left-over
+ 3: box-out, 4:raster scan, 5:wipe, 6:explicit */
+ /* for fmo_type == 0 */
+ uint run_length_minus1[MAX_NUM_SLICE_GROUP]; /* array of size num_slice_group, in round robin fasion */
+ /* fmo_type == 2*/
+ uint top_left[MAX_NUM_SLICE_GROUP-1]; /* array of co-ordinates of each slice_group */
+ uint bottom_right[MAX_NUM_SLICE_GROUP-1]; /* except the last one which is the background. */
+ /* fmo_type == 3,4,5 */
+ AVCFlag change_dir_flag; /* slice group change direction flag */
+ uint change_rate_minus1;
+ /* fmo_type == 6 */
+ uint *slice_group; /* array of size MBWidth*MBHeight */
+
+ AVCFlag db_filter; /* enable deblocking loop filter */
+ int disable_db_idc; /* 0: filter everywhere, 1: no filter, 2: no filter across slice boundary */
+ int alpha_offset; /* alpha offset range -6,...,6 */
+ int beta_offset; /* beta offset range -6,...,6 */
+
+ AVCFlag constrained_intra_pred; /* constrained intra prediction flag */
+
+ AVCFlag auto_scd; /* scene change detection on or off */
+ int idr_period; /* idr frame refresh rate in number of target encoded frame (no concept of actual time).*/
+ int intramb_refresh; /* minimum number of intra MB per frame */
+ AVCFlag data_par; /* enable data partitioning */
+
+ AVCFlag fullsearch; /* enable full-pel full-search mode */
+ int search_range; /* search range for motion vector in (-search_range,+search_range) pixels */
+ AVCFlag sub_pel; /* enable sub pel prediction */
+ AVCFlag submb_pred; /* enable sub MB partition mode */
+ AVCFlag rdopt_mode; /* RD optimal mode selection */
+ AVCFlag bidir_pred; /* enable bi-directional for B-slice, this flag forces the encoder to encode
+ any frame with POC less than the previously encoded frame as a B-frame.
+ If it's off, then such frames will remain P-frame. */
+
+ AVCFlag rate_control; /* rate control enable, on: RC on, off: constant QP */
+ int initQP; /* initial QP */
+ uint32 bitrate; /* target encoding bit rate in bits/second */
+ uint32 CPB_size; /* coded picture buffer in number of bits */
+ uint32 init_CBP_removal_delay; /* initial CBP removal delay in msec */
+
+ uint32 frame_rate; /* frame rate in the unit of frames per 1000 second */
+ /* note, frame rate is only needed by the rate control, AVC is timestamp agnostic. */
+
+ AVCFlag out_of_band_param_set; /* flag to set whether param sets are to be retrieved up front or not */
+
+ AVCFlag use_overrun_buffer; /* do not throw away the frame if output buffer is not big enough.
+ copy excess bits to the overrun buffer */
+} AVCEncParams;
+
+
+/**
+This structure contains current frame encoding statistics for debugging purpose.
+*/
+typedef struct tagAVCEncFrameStats
+{
+ int avgFrameQP; /* average frame QP */
+ int numIntraMBs; /* number of intra MBs */
+ int numFalseAlarm;
+ int numMisDetected;
+ int numDetected;
+
+} AVCEncFrameStats;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /** THE FOLLOWINGS ARE APIS */
+ /**
+ This function initializes the encoder library. It verifies the validity of the
+ encoding parameters against the specified profile/level and the list of supported
+ tools by this library. It allocates necessary memories required to perform encoding.
+ For re-encoding application, if users want to setup encoder in a more precise way,
+ users can give the external SPS and PPS to the encoder to follow.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ \param "encParam" "Pointer to the encoding parameter structure."
+ \param "extSPS" "External SPS used for re-encoding purpose. NULL if not present"
+ \param "extPPS" "External PPS used for re-encoding purpose. NULL if not present"
+ \return "AVCENC_SUCCESS for success,
+ AVCENC_NOT_SUPPORTED for the use of unsupported tools,
+ AVCENC_MEMORY_FAIL for memory allocation failure,
+ AVCENC_FAIL for generic failure."
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncInitialize(AVCHandle *avcHandle, AVCEncParams *encParam, void* extSPS, void* extPPS);
+
+
+ /**
+ Since the output buffer size is not known prior to encoding a frame, users need to
+ allocate big enough buffer otherwise, that frame will be dropped. This function returns
+ the size of the output buffer to be allocated by the users that guarantees to hold one frame.
+ It follows the CPB spec for a particular level. However, when the users set use_overrun_buffer
+ flag, this API is useless as excess output bits are saved in the overrun buffer waiting to be
+ copied out in small chunks, i.e. users can allocate any size of output buffer.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ \param "size" "Pointer to the size to be modified."
+ \return "AVCENC_SUCCESS for success, AVCENC_UNINITIALIZED when level is not known.
+ */
+
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncGetMaxOutputBufferSize(AVCHandle *avcHandle, int* size);
+
+ /**
+ Users call this function to provide an input structure to the encoder library which will keep
+ a list of input structures it receives in case the users call this function many time before
+ calling PVAVCEncodeSlice. The encoder library will encode them according to the frame_num order.
+ Users should not modify the content of a particular frame until this frame is encoded and
+ returned thru CBAVCEnc_ReturnInput() callback function.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ \param "input" "Pointer to the input structure."
+ \return "AVCENC_SUCCESS for success,
+ AVCENC_FAIL if the encoder is not in the right state to take a new input frame.
+ AVCENC_NEW_IDR for the detection or determination of a new IDR, with this status,
+ the returned NAL is an SPS NAL,
+ AVCENC_NO_PICTURE if the input frame coding timestamp is too early, users must
+ get next frame or adjust the coding timestamp."
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncSetInput(AVCHandle *avcHandle, AVCFrameIO *input);
+
+ /**
+ This function is called to encode a NAL unit which can be an SPS NAL, a PPS NAL or
+ a VCL (video coding layer) NAL which contains one slice of data. It could be a
+ fixed number of macroblocks, as specified in the encoder parameters set, or the
+ maximum number of macroblocks fitted into the given input argument "buffer". The
+ input frame is taken from the oldest unencoded input frame retrieved by users by
+ PVAVCEncGetInput API.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ \param "buffer" "Pointer to the output AVC bitstream buffer, the format will be EBSP,
+ not RBSP."
+ \param "buf_nal_size" "As input, the size of the buffer in bytes.
+ This is the physical limitation of the buffer. As output, the size of the EBSP."
+ \param "nal_type" "Pointer to the NAL type of the returned buffer."
+ \return "AVCENC_SUCCESS for success of encoding one slice,
+ AVCENC_PICTURE_READY for the completion of a frame encoding,
+ AVCENC_FAIL for failure (this should not occur, though)."
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncodeNAL(AVCHandle *avcHandle, uint8 *buffer, uint *buf_nal_size, int *nal_type);
+
+ /**
+ This function sniffs the nal_unit_type such that users can call corresponding APIs.
+ This function is identical to PVAVCDecGetNALType() in the decoder.
+ \param "bitstream" "Pointer to the beginning of a NAL unit (start with forbidden_zero_bit, etc.)."
+ \param "size" "size of the bitstream (NumBytesInNALunit + 1)."
+ \param "nal_unit_type" "Pointer to the return value of nal unit type."
+ \return "AVCENC_SUCCESS if success, AVCENC_FAIL otherwise."
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncGetNALType(uint8 *bitstream, int size, int *nal_type, int *nal_ref_idc);
+
+ /**
+ This function returns the pointer to internal overrun buffer. Users can call this to query
+ whether the overrun buffer has been used to encode the current NAL.
+ \param "avcHandle" "Pointer to the handle."
+ \return "Pointer to overrun buffer if it is used, otherwise, NULL."
+ */
+ OSCL_IMPORT_REF uint8* PVAVCEncGetOverrunBuffer(AVCHandle* avcHandle);
+
+ /**
+ This function returns the reconstructed frame of the most recently encoded frame.
+ Note that this frame is not returned to the users yet. Users should only read the
+ content of this frame.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ \param "output" "Pointer to the input structure."
+ \return "AVCENC_SUCCESS for success, AVCENC_NO_PICTURE if no picture to be outputted."
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncGetRecon(AVCHandle *avcHandle, AVCFrameIO *recon);
+
+ /**
+ This function is used to return the recontructed frame back to the AVC encoder library
+ in order to be re-used for encoding operation. If users want the content of it to remain
+ unchanged for a long time, they should make a copy of it and release the memory back to
+ the encoder. The encoder relies on the id element in the AVCFrameIO structure,
+ thus users should not change the id value.
+ \param "avcHandle" "Handle to the AVC decoder library object."
+ \param "output" "Pointer to the AVCFrameIO structure."
+ \return "AVCENC_SUCCESS for success, AVCENC_FAIL for fail for id not found."
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncReleaseRecon(AVCHandle *avcHandle, AVCFrameIO *recon);
+
+ /**
+ This function performs clean up operation including memory deallocation.
+ The encoder will also clear the list of input structures it has not released.
+ This implies that users must keep track of the number of input structure they have allocated
+ and free them accordingly.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ */
+ OSCL_IMPORT_REF void PVAVCCleanUpEncoder(AVCHandle *avcHandle);
+
+ /**
+ This function extracts statistics of the current frame. If the encoder has not finished
+ with the current frame, the result is not accurate.
+ \param "avcHandle" "Handle to the AVC encoder library object."
+ \param "avcStats" "Pointer to AVCEncFrameStats structure."
+ \return "void."
+ */
+ void PVAVCEncGetFrameStats(AVCHandle *avcHandle, AVCEncFrameStats *avcStats);
+
+ /**
+ These functions are used for the modification of encoding parameters.
+ To be polished.
+ */
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateBitRate(AVCHandle *avcHandle, uint32 bitrate);
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateFrameRate(AVCHandle *avcHandle, uint32 num, uint32 denom);
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateIDRInterval(AVCHandle *avcHandle, int IDRInterval);
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncIDRRequest(AVCHandle *avcHandle);
+ OSCL_IMPORT_REF AVCEnc_Status PVAVCEncUpdateIMBRefresh(AVCHandle *avcHandle, int numMB);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _AVCENC_API_H_ */
+
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_int.h b/media/libstagefright/codecs/avc/enc/src/avcenc_int.h
new file mode 100644
index 0000000..3fe08a1
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_int.h
@@ -0,0 +1,471 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains application function interfaces to the AVC encoder library
+and necessary type defitionitions and enumerations.
+@publishedAll
+*/
+
+#ifndef AVCENC_INT_H_INCLUDED
+#define AVCENC_INT_H_INCLUDED
+
+#ifndef AVCINT_COMMON_H_INCLUDED
+#include "avcint_common.h"
+#endif
+#ifndef AVCENC_API_H_INCLUDED
+#include "avcenc_api.h"
+#endif
+
+typedef float OsclFloat;
+
+/* Definition for the structures below */
+#define DEFAULT_ATTR 0 /* default memory attribute */
+#define MAX_INPUT_FRAME 30 /* some arbitrary number, it can be much higher than this. */
+#define MAX_REF_FRAME 16 /* max size of the RefPicList0 and RefPicList1 */
+#define MAX_REF_PIC_LIST 33
+
+#define MIN_QP 0
+#define MAX_QP 51
+#define SHIFT_QP 12
+#define LAMBDA_ACCURACY_BITS 16
+#define LAMBDA_FACTOR(lambda) ((int)((double)(1<<LAMBDA_ACCURACY_BITS)*lambda+0.5))
+
+
+#define DISABLE_THRESHOLDING 0
+// for better R-D performance
+#define _LUMA_COEFF_COST_ 4 //!< threshold for luma coeffs
+#define _CHROMA_COEFF_COST_ 4 //!< threshold for chroma coeffs, used to be 7
+#define _LUMA_MB_COEFF_COST_ 5 //!< threshold for luma coeffs of inter Macroblocks
+#define _LUMA_8x8_COEFF_COST_ 5 //!< threshold for luma coeffs of 8x8 Inter Partition
+#define MAX_VALUE 999999 //!< used for start value for some variables
+
+#define WEIGHTED_COST(factor,bits) (((factor)*(bits))>>LAMBDA_ACCURACY_BITS)
+#define MV_COST(f,s,cx,cy,px,py) (WEIGHTED_COST(f,mvbits[((cx)<<(s))-px]+mvbits[((cy)<<(s))-py]))
+#define MV_COST_S(f,cx,cy,px,py) (WEIGHTED_COST(f,mvbits[cx-px]+mvbits[cy-py]))
+
+/* for sub-pel search and interpolation */
+#define SUBPEL_PRED_BLK_SIZE 576 // 24x24
+#define REF_CENTER 75
+#define V2Q_H0Q 1
+#define V0Q_H2Q 2
+#define V2Q_H2Q 3
+
+/*
+#define V3Q_H0Q 1
+#define V3Q_H1Q 2
+#define V0Q_H1Q 3
+#define V1Q_H1Q 4
+#define V1Q_H0Q 5
+#define V1Q_H3Q 6
+#define V0Q_H3Q 7
+#define V3Q_H3Q 8
+#define V2Q_H3Q 9
+#define V2Q_H0Q 10
+#define V2Q_H1Q 11
+#define V2Q_H2Q 12
+#define V3Q_H2Q 13
+#define V0Q_H2Q 14
+#define V1Q_H2Q 15
+*/
+
+
+#define DEFAULT_OVERRUN_BUFFER_SIZE 1000
+
+// associated with the above cost model
+const uint8 COEFF_COST[2][16] =
+{
+ {3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}
+};
+
+
+
+//! convert from H.263 QP to H.264 quant given by: quant=pow(2,QP/6)
+const int QP2QUANT[40] =
+{
+ 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 4, 4, 4, 5, 6,
+ 6, 7, 8, 9, 10, 11, 13, 14,
+ 16, 18, 20, 23, 25, 29, 32, 36,
+ 40, 45, 51, 57, 64, 72, 81, 91
+};
+
+
+/**
+This enumeration keeps track of the internal status of the encoder whether it is doing
+something. The encoding flow follows the order in which these states are.
+@publishedAll
+*/
+typedef enum
+{
+ AVCEnc_Initializing = 0,
+ AVCEnc_Encoding_SPS,
+ AVCEnc_Encoding_PPS,
+ AVCEnc_Analyzing_Frame,
+ AVCEnc_WaitingForBuffer, // pending state
+ AVCEnc_Encoding_Frame,
+} AVCEnc_State ;
+
+/**
+Bitstream structure contains bitstream related parameters such as the pointer
+to the buffer, the current byte position and bit position. The content of the
+bitstreamBuffer will be in EBSP format as the emulation prevention codes are
+automatically inserted as the RBSP is recorded.
+@publishedAll
+*/
+typedef struct tagEncBitstream
+{
+ uint8 *bitstreamBuffer; /* pointer to buffer memory */
+ int buf_size; /* size of the buffer memory */
+ int write_pos; /* next position to write to bitstreamBuffer */
+ int count_zeros; /* count number of consecutive zero */
+ uint current_word; /* byte-swapped (MSB left) current word to write to buffer */
+ int bit_left; /* number of bit left in current_word */
+ uint8 *overrunBuffer; /* extra output buffer to prevent current skip due to output buffer overrun*/
+ int oBSize; /* size of allocated overrun buffer */
+ void *encvid; /* pointer to the main object */
+
+} AVCEncBitstream;
+
+/**
+This structure is used for rate control purpose and other performance related control
+variables such as, RD cost, statistics, motion search stuffs, etc.
+should be in this structure.
+@publishedAll
+*/
+
+
+typedef struct tagRDInfo
+{
+ int QP;
+ int actual_bits;
+ OsclFloat mad;
+ OsclFloat R_D;
+} RDInfo;
+
+typedef struct tagMultiPass
+{
+ /* multipass rate control data */
+ int target_bits; /* target bits for current frame, = rc->T */
+ int actual_bits; /* actual bits for current frame obtained after encoding, = rc->Rc*/
+ int QP; /* quantization level for current frame, = rc->Qc*/
+ int prev_QP; /* quantization level for previous frame */
+ int prev_prev_QP; /* quantization level for previous frame before last*/
+ OsclFloat mad; /* mad for current frame, = video->avgMAD*/
+ int bitrate; /* bitrate for current frame */
+ OsclFloat framerate; /* framerate for current frame*/
+
+ int nRe_Quantized; /* control variable for multipass encoding, */
+ /* 0 : first pass */
+ /* 1 : intermediate pass(quantization and VLC loop only) */
+ /* 2 : final pass(de-quantization, idct, etc) */
+ /* 3 : macroblock level rate control */
+
+ int encoded_frames; /* counter for all encoded frames */
+ int re_encoded_frames; /* counter for all multipass encoded frames*/
+ int re_encoded_times; /* counter for all times of multipass frame encoding */
+
+ /* Multiple frame prediction*/
+ RDInfo **pRDSamples; /* pRDSamples[30][32], 30->30fps, 32 -> 5 bit quantizer, 32 candidates*/
+ int framePos; /* specific position in previous multiple frames*/
+ int frameRange; /* number of overall previous multiple frames */
+ int samplesPerFrame[30]; /* number of samples per frame, 30->30fps */
+
+ /* Bit allocation for scene change frames and high motion frames */
+ OsclFloat sum_mad;
+ int counter_BTsrc; /* BT = Bit Transfer, bit transfer from low motion frames or less complicatedly compressed frames */
+ int counter_BTdst; /* BT = Bit Transfer, bit transfer to scene change frames or high motion frames or more complicatedly compressed frames */
+ OsclFloat sum_QP;
+ int diff_counter; /* diff_counter = -diff_counter_BTdst, or diff_counter_BTsrc */
+
+ /* For target bitrate or framerate update */
+ OsclFloat target_bits_per_frame; /* = C = bitrate/framerate */
+ OsclFloat target_bits_per_frame_prev; /* previous C */
+ OsclFloat aver_mad; /* so-far average mad could replace sum_mad */
+ OsclFloat aver_mad_prev; /* previous average mad */
+ int overlapped_win_size; /* transition period of time */
+ int encoded_frames_prev; /* previous encoded_frames */
+} MultiPass;
+
+
+typedef struct tagdataPointArray
+{
+ int Qp;
+ int Rp;
+ OsclFloat Mp; /* for MB-based RC */
+ struct tagdataPointArray *next;
+ struct tagdataPointArray *prev;
+} dataPointArray;
+
+typedef struct tagAVCRateControl
+{
+
+ /* these parameters are initialized by the users AVCEncParams */
+ /* bitrate-robustness tradeoff */
+ uint scdEnable; /* enable scene change detection */
+ int idrPeriod; /* IDR period in number of frames */
+ int intraMBRate; /* intra MB refresh rate per frame */
+ uint dpEnable; /* enable data partitioning */
+
+ /* quality-complexity tradeoff */
+ uint subPelEnable; /* enable quarter pel search */
+ int mvRange; /* motion vector search range in +/- pixel */
+ uint subMBEnable; /* enable sub MB prediction mode (4x4, 4x8, 8x4) */
+ uint rdOptEnable; /* enable RD-opt mode selection */
+ uint twoPass; /* flag for 2 pass encoding ( for future )*/
+ uint bidirPred; /* bi-directional prediction for B-frame. */
+
+ uint rcEnable; /* enable rate control, '1' on, '0' const QP */
+ int initQP; /* initial QP */
+
+ /* note the following 3 params are for HRD, these triplets can be a series
+ of triplets as the generalized HRD allows. SEI message must be generated in this case. */
+ /* We no longer have to differentiate between CBR and VBR. The users to the
+ AVC encoder lib will do the mapping from CBR/VBR to these parameters. */
+ int32 bitRate; /* target bit rate for the overall clip in bits/second*/
+ int32 cpbSize; /* coded picture buffer size in bytes */
+ int32 initDelayOffset; /* initial CBP removal delay in bits */
+
+ OsclFloat frame_rate; /* frame rate */
+ int srcInterval; /* source frame rate in msec */
+ int basicUnit; /* number of macroblocks per BU */
+
+ /* Then internal parameters for the operation */
+ uint first_frame; /* a flag for the first frame */
+ int lambda_mf; /* for example */
+ int totalSAD; /* SAD of current frame */
+
+ /*******************************************/
+ /* this part comes from MPEG4 rate control */
+ int alpha; /* weight for I frame */
+ int Rs; /*bit rate for the sequence (or segment) e.g., 24000 bits/sec */
+ int Rc; /*bits used for the current frame. It is the bit count obtained after encoding. */
+ int Rp; /*bits to be removed from the buffer per picture. */
+ /*? is this the average one, or just the bits coded for the previous frame */
+ int Rps; /*bit to be removed from buffer per src frame */
+ OsclFloat Ts; /*number of seconds for the sequence (or segment). e.g., 10 sec */
+ OsclFloat Ep;
+ OsclFloat Ec; /*mean absolute difference for the current frame after motion compensation.*/
+ /*If the macroblock is intra coded, the original spatial pixel values are summed.*/
+ int Qc; /*quantization level used for the current frame. */
+ int Nr; /*number of P frames remaining for encoding.*/
+ int Rr; /*number of bits remaining for encoding this sequence (or segment).*/
+ int Rr_Old;
+ int T; /*target bit to be used for the current frame.*/
+ int S; /*number of bits used for encoding the previous frame.*/
+ int Hc; /*header and motion vector bits used in the current frame. It includes all the information except to the residual information.*/
+ int Hp; /*header and motion vector bits used in the previous frame. It includes all the information except to the residual information.*/
+ int Ql; /*quantization level used in the previous frame */
+ int Bs; /*buffer size e.g., R/2 */
+ int B; /*current buffer level e.g., R/4 - start from the middle of the buffer */
+ OsclFloat X1;
+ OsclFloat X2;
+ OsclFloat X11;
+ OsclFloat M; /*safe margin for the buffer */
+ OsclFloat smTick; /*ratio of src versus enc frame rate */
+ double remnant; /*remainder frame of src/enc frame for fine frame skipping */
+ int timeIncRes; /* vol->timeIncrementResolution */
+
+ dataPointArray *end; /*quantization levels for the past (20) frames */
+
+ int frameNumber; /* ranging from 0 to 20 nodes*/
+ int w;
+ int Nr_Original;
+ int Nr_Old, Nr_Old2;
+ int skip_next_frame;
+ int Qdep; /* smooth Q adjustment */
+ int VBR_Enabled;
+
+ int totalFrameNumber; /* total coded frames, for debugging!!*/
+
+ char oFirstTime;
+
+ int numFrameBits; /* keep track of number of bits of the current frame */
+ int NumberofHeaderBits;
+ int NumberofTextureBits;
+ int numMBHeaderBits;
+ int numMBTextureBits;
+ double *MADofMB;
+ int32 bitsPerFrame;
+
+ /* BX rate control, something like TMN8 rate control*/
+
+ MultiPass *pMP;
+
+ int TMN_W;
+ int TMN_TH;
+ int VBV_fullness;
+ int max_BitVariance_num; /* the number of the maximum bit variance within the given buffer with the unit of 10% of bitrate/framerate*/
+ int encoded_frames; /* counter for all encoded frames */
+ int low_bound; /* bound for underflow detection, usually low_bound=-Bs/2, but could be changed in H.263 mode */
+ int VBV_fullness_offset; /* offset of VBV_fullness, usually is zero, but can be changed in H.263 mode*/
+ /* End BX */
+
+} AVCRateControl;
+
+
+/**
+This structure is for the motion vector information. */
+typedef struct tagMV
+{
+ int x;
+ int y;
+ uint sad;
+} AVCMV;
+
+/**
+This structure contains function pointers for different platform dependent implementation of
+functions. */
+typedef struct tagAVCEncFuncPtr
+{
+
+ int (*SAD_MB_HalfPel[4])(uint8*, uint8*, int, void *);
+ int (*SAD_Macroblock)(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+
+} AVCEncFuncPtr;
+
+/**
+This structure contains information necessary for correct padding.
+*/
+typedef struct tagPadInfo
+{
+ int i;
+ int width;
+ int j;
+ int height;
+} AVCPadInfo;
+
+
+#ifdef HTFM
+typedef struct tagHTFM_Stat
+{
+ int abs_dif_mad_avg;
+ uint countbreak;
+ int offsetArray[16];
+ int offsetRef[16];
+} HTFM_Stat;
+#endif
+
+
+/**
+This structure is the main object for AVC encoder library providing access to all
+global variables. It is allocated at PVAVCInitEncoder and freed at PVAVCCleanUpEncoder.
+@publishedAll
+*/
+typedef struct tagEncObject
+{
+
+ AVCCommonObj *common;
+
+ AVCEncBitstream *bitstream; /* for current NAL */
+ uint8 *overrunBuffer; /* extra output buffer to prevent current skip due to output buffer overrun*/
+ int oBSize; /* size of allocated overrun buffer */
+
+ /* rate control */
+ AVCRateControl *rateCtrl; /* pointer to the rate control structure */
+
+ /* encoding operation */
+ AVCEnc_State enc_state; /* encoding state */
+
+ AVCFrameIO *currInput; /* pointer to the current input frame */
+
+ int currSliceGroup; /* currently encoded slice group id */
+
+ int level[24][16], run[24][16]; /* scratch memory */
+ int leveldc[16], rundc[16]; /* for DC component */
+ int levelcdc[16], runcdc[16]; /* for chroma DC component */
+ int numcoefcdc[2]; /* number of coefficient for chroma DC */
+ int numcoefdc; /* number of coefficients for DC component */
+
+ int qp_const;
+ int qp_const_c;
+ /********* intra prediction scratch memory **********************/
+ uint8 pred_i16[AVCNumI16PredMode][256]; /* save prediction for MB */
+ uint8 pred_i4[AVCNumI4PredMode][16]; /* save prediction for blk */
+ uint8 pred_ic[AVCNumIChromaMode][128]; /* for 2 chroma */
+
+ int mostProbableI4Mode[16]; /* in raster scan order */
+ /********* motion compensation related variables ****************/
+ AVCMV *mot16x16; /* Saved motion vectors for 16x16 block*/
+ AVCMV(*mot16x8)[2]; /* Saved motion vectors for 16x8 block*/
+ AVCMV(*mot8x16)[2]; /* Saved motion vectors for 8x16 block*/
+ AVCMV(*mot8x8)[4]; /* Saved motion vectors for 8x8 block*/
+
+ /********* subpel position **************************************/
+ uint32 subpel_pred[SUBPEL_PRED_BLK_SIZE/*<<2*/]; /* all 16 sub-pel positions */
+ uint8 *hpel_cand[9]; /* pointer to half-pel position */
+ int best_hpel_pos; /* best position */
+ uint8 qpel_cand[8][24*16]; /* pointer to quarter-pel position */
+ int best_qpel_pos;
+ uint8 *bilin_base[9][4]; /* pointer to 4 position at top left of bilinear quarter-pel */
+
+ /* need for intra refresh rate */
+ uint8 *intraSearch; /* Intra Array for MBs to be intra searched */
+ uint firstIntraRefreshMBIndx; /* keep track for intra refresh */
+
+ int i4_sad; /* temporary for i4 mode SAD */
+ int *min_cost; /* Minimum cost for the all MBs */
+ int lambda_mode; /* Lagrange parameter for mode selection */
+ int lambda_motion; /* Lagrange parameter for MV selection */
+
+ uint8 *mvbits_array; /* Table for bits spent in the cost funciton */
+ uint8 *mvbits; /* An offset to the above array. */
+
+ /* to speedup the SAD calculation */
+ void *sad_extra_info;
+ uint8 currYMB[256]; /* interleaved current macroblock in HTFM order */
+
+#ifdef HTFM
+ int nrmlz_th[48]; /* Threshold for fast SAD calculation using HTFM */
+ HTFM_Stat htfm_stat; /* For statistics collection */
+#endif
+
+ /* statistics */
+ int numIntraMB; /* keep track of number of intra MB */
+
+ /* encoding complexity control */
+ uint fullsearch_enable; /* flag to enable full-pel full-search */
+
+ /* misc.*/
+ bool outOfBandParamSet; /* flag to enable out-of-band param set */
+
+ AVCSeqParamSet extSPS; /* for external SPS */
+ AVCPicParamSet extPPS; /* for external PPS */
+
+ /* time control */
+ uint32 prevFrameNum; /* previous frame number starting from modTimeRef */
+ uint32 modTimeRef; /* Reference modTime update every I-Vop*/
+ uint32 wrapModTime; /* Offset to modTime Ref, rarely used */
+
+ uint prevProcFrameNum; /* previously processed frame number, could be skipped */
+ uint prevCodedFrameNum; /* previously encoded frame number */
+ /* POC related variables */
+ uint32 dispOrdPOCRef; /* reference POC is displayer order unit. */
+
+ /* Function pointers */
+ AVCEncFuncPtr *functionPointer; /* store pointers to platform specific functions */
+
+ /* Application control data */
+ AVCHandle *avcHandle;
+
+
+} AVCEncObject;
+
+
+#endif /*AVCENC_INT_H_INCLUDED*/
+
diff --git a/media/libstagefright/codecs/avc/enc/src/avcenc_lib.h b/media/libstagefright/codecs/avc/enc/src/avcenc_lib.h
new file mode 100644
index 0000000..17e28ef
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/avcenc_lib.h
@@ -0,0 +1,1020 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/**
+This file contains declarations of internal functions for AVC decoder library.
+@publishedAll
+*/
+#ifndef AVCENC_LIB_H_INCLUDED
+#define AVCENC_LIB_H_INCLUDED
+
+#ifndef AVCLIB_COMMON_H_INCLUDED
+#include "avclib_common.h"
+#endif
+#ifndef AVCENC_INT_H_INCLUDED
+#include "avcenc_int.h"
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /*------------- block.c -------------------------*/
+
+ /**
+ This function perform residue calculation, transform, quantize, inverse quantize,
+ inverse transform and residue compensation on a 4x4 block.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "blkidx" "raster scan block index of the current 4x4 block."
+ \param "cur" "Pointer to the reconstructed block."
+ \param "org" "Pointer to the original block."
+ \param "coef_cost" "Pointer to the coefficient cost to be filled in and returned."
+ \return "Number of non-zero coefficients."
+ */
+ int dct_luma(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org, int *coef_cost);
+
+ /**
+ This function performs IDCT on an INTER macroblock.
+ \param "video" "Pointer to AVCCommonObj."
+ \param "curL" "Pointer to the origin of the macroblock on the current frame."
+ \param "currMB" "Pointer to the AVCMacroblock structure."
+ \param "picPitch" "Pitch of the current frame."
+ \return "void".
+ */
+ void MBInterIdct(AVCCommonObj *video, uint8 *curL, AVCMacroblock *currMB, int picPitch);
+
+ /**
+ This function perform residue calculation, transform, quantize, inverse quantize,
+ inverse transform and residue compensation on a macroblock.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "curL" "Pointer to the reconstructed MB."
+ \param "orgL" "Pointer to the original MB."
+ \return "void"
+ */
+ void dct_luma_16x16(AVCEncObject *encvid, uint8 *curL, uint8 *orgL);
+
+ /**
+ This function perform residue calculation, transform, quantize, inverse quantize,
+ inverse transform and residue compensation for chroma components of an MB.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "curC" "Pointer to the reconstructed MB."
+ \param "orgC" "Pointer to the original MB."
+ \param "cr" "Flag whether it is Cr or not."
+ \return "void"
+ */
+ void dct_chroma(AVCEncObject *encvid, uint8 *curC, uint8 *orgC, int cr);
+
+ /*----------- init.c ------------------*/
+ /**
+ This function interprets the encoding parameters provided by users in encParam.
+ The results are kept in AVCEncObject, AVCSeqParamSet, AVCPicParamSet and AVCSliceHeader.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "encParam" "Pointer to AVCEncParam."
+ \param "extSPS" "External SPS template to be followed. NULL if not present."
+ \param "extPPS" "External PPS template to be followed. NULL if not present."
+ \return "see AVCEnc_Status."
+ */
+ AVCEnc_Status SetEncodeParam(AVCHandle *avcHandle, AVCEncParams *encParam,
+ void *extSPS, void *extPPS);
+
+ /**
+ This function verifies the encoding parameters whether they meet the set of supported
+ tool by a specific profile. If the profile is not set, it will just find the closest
+ profile instead of verifying it.
+ \param "video" "Pointer to AVCEncObject."
+ \param "seqParam" "Pointer to AVCSeqParamSet."
+ \param "picParam" "Pointer to AVCPicParamSet."
+ \return "AVCENC_SUCCESS if success,
+ AVCENC_PROFILE_NOT_SUPPORTED if the specified profile
+ is not supported by this version of the library,
+ AVCENC_TOOLS_NOT_SUPPORTED if any of the specified encoding tools are
+ not supported by the user-selected profile."
+ */
+ AVCEnc_Status VerifyProfile(AVCEncObject *video, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam);
+
+ /**
+ This function verifies the encoding parameters whether they meet the requirement
+ for a specific level. If the level is not set, it will just find the closest
+ level instead of verifying it.
+ \param "video" "Pointer to AVCEncObject."
+ \param "seqParam" "Pointer to AVCSeqParamSet."
+ \param "picParam" "Pointer to AVCPicParamSet."
+ \return "AVCENC_SUCCESS if success,
+ AVCENC_LEVEL_NOT_SUPPORTED if the specified level
+ is not supported by this version of the library,
+ AVCENC_LEVEL_FAIL if any of the encoding parameters exceed
+ the range of the user-selected level."
+ */
+ AVCEnc_Status VerifyLevel(AVCEncObject *video, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam);
+
+ /**
+ This funciton initializes the frame encoding by setting poc/frame_num related parameters. it
+ also performs motion estimation.
+ \param "encvid" "Pointer to the AVCEncObject."
+ \return "AVCENC_SUCCESS if success, AVCENC_NO_PICTURE if there is no input picture
+ in the queue to encode, AVCENC_POC_FAIL or AVCENC_CONSECUTIVE_NONREF for POC
+ related errors, AVCENC_NEW_IDR if new IDR is detected."
+ */
+ AVCEnc_Status InitFrame(AVCEncObject *encvid);
+
+ /**
+ This function initializes slice header related variables and other variables necessary
+ for decoding one slice.
+ \param "encvid" "Pointer to the AVCEncObject."
+ \return "AVCENC_SUCCESS if success."
+ */
+ AVCEnc_Status InitSlice(AVCEncObject *encvid);
+
+ /*----------- header.c ----------------*/
+ /**
+ This function performs bitstream encoding of the sequence parameter set NAL.
+ \param "encvid" "Pointer to the AVCEncObject."
+ \param "stream" "Pointer to AVCEncBitstream."
+ \return "AVCENC_SUCCESS if success or AVCENC_SPS_FAIL or others for unexpected failure which
+ should not occur. The SPS parameters should all be verified before this function is called."
+ */
+ AVCEnc_Status EncodeSPS(AVCEncObject *encvid, AVCEncBitstream *stream);
+
+ /**
+ This function encodes the VUI parameters into the sequence parameter set bitstream.
+ \param "stream" "Pointer to AVCEncBitstream."
+ \param "vui" "Pointer to AVCVUIParams."
+ \return "nothing."
+ */
+ void EncodeVUI(AVCEncBitstream* stream, AVCVUIParams* vui);
+
+ /**
+ This function encodes HRD parameters into the sequence parameter set bitstream
+ \param "stream" "Pointer to AVCEncBitstream."
+ \param "hrd" "Pointer to AVCHRDParams."
+ \return "nothing."
+ */
+ void EncodeHRD(AVCEncBitstream* stream, AVCHRDParams* hrd);
+
+
+ /**
+ This function performs bitstream encoding of the picture parameter set NAL.
+ \param "encvid" "Pointer to the AVCEncObject."
+ \param "stream" "Pointer to AVCEncBitstream."
+ \return "AVCENC_SUCCESS if success or AVCENC_PPS_FAIL or others for unexpected failure which
+ should not occur. The SPS parameters should all be verified before this function is called."
+ */
+ AVCEnc_Status EncodePPS(AVCEncObject *encvid, AVCEncBitstream *stream);
+
+ /**
+ This function encodes slice header information which has been initialized or fabricated
+ prior to entering this funciton.
+ \param "encvid" "Pointer to the AVCEncObject."
+ \param "stream" "Pointer to AVCEncBitstream."
+ \return "AVCENC_SUCCESS if success or bitstream fail statuses."
+ */
+ AVCEnc_Status EncodeSliceHeader(AVCEncObject *encvid, AVCEncBitstream *stream);
+
+ /**
+ This function encodes reference picture list reordering relted syntax.
+ \param "video" "Pointer to AVCCommonObj."
+ \param "stream" "Pointer to AVCEncBitstream."
+ \param "sliceHdr" "Pointer to AVCSliceHdr."
+ \param "slice_type" "Value of slice_type - 5 if greater than 5."
+ \return "AVCENC_SUCCESS for success and AVCENC_FAIL otherwise."
+ */
+ AVCEnc_Status ref_pic_list_reordering(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type);
+
+ /**
+ This function encodes dec_ref_pic_marking related syntax.
+ \param "video" "Pointer to AVCCommonObj."
+ \param "stream" "Pointer to AVCEncBitstream."
+ \param "sliceHdr" "Pointer to AVCSliceHdr."
+ \return "AVCENC_SUCCESS for success and AVCENC_FAIL otherwise."
+ */
+ AVCEnc_Status dec_ref_pic_marking(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr);
+
+ /**
+ This function initializes the POC related variables and the POC syntax to be encoded
+ to the slice header derived from the disp_order and is_reference flag of the original
+ input frame to be encoded.
+ \param "video" "Pointer to the AVCEncObject."
+ \return "AVCENC_SUCCESS if success,
+ AVCENC_POC_FAIL if the poc type is undefined or
+ AVCENC_CONSECUTIVE_NONREF if there are consecutive non-reference frame for POC type 2."
+ */
+ AVCEnc_Status InitPOC(AVCEncObject *video);
+
+ /**
+ This function performs POC related operation after a picture is decoded.
+ \param "video" "Pointer to AVCCommonObj."
+ \return "AVCENC_SUCCESS"
+ */
+ AVCEnc_Status PostPOC(AVCCommonObj *video);
+
+ /*----------- bitstream_io.c ----------------*/
+ /**
+ This function initializes the bitstream structure with the information given by
+ the users.
+ \param "bitstream" "Pointer to the AVCEncBitstream structure."
+ \param "buffer" "Pointer to the unsigned char buffer for output."
+ \param "buf_size" "The size of the buffer in bytes."
+ \param "overrunBuffer" "Pointer to extra overrun buffer."
+ \param "oBSize" "Size of overrun buffer in bytes."
+ \return "AVCENC_SUCCESS if success, AVCENC_BITSTREAM_INIT_FAIL if fail"
+ */
+ AVCEnc_Status BitstreamEncInit(AVCEncBitstream *bitstream, uint8 *buffer, int buf_size,
+ uint8 *overrunBuffer, int oBSize);
+
+ /**
+ This function writes the data from the cache into the bitstream buffer. It also adds the
+ emulation prevention code if necessary.
+ \param "stream" "Pointer to the AVCEncBitstream structure."
+ \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+ */
+ AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream);
+
+ /**
+ This function writes the codeword into the cache which will eventually be written to
+ the bitstream buffer.
+ \param "stream" "Pointer to the AVCEncBitstream structure."
+ \param "nBits" "Number of bits in the codeword."
+ \param "code" "The codeword."
+ \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+ */
+ AVCEnc_Status BitstreamWriteBits(AVCEncBitstream *stream, int nBits, uint code);
+
+ /**
+ This function writes one bit of data into the cache which will eventually be written
+ to the bitstream buffer.
+ \param "stream" "Pointer to the AVCEncBitstream structure."
+ \param "code" "The codeword."
+ \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+ */
+ AVCEnc_Status BitstreamWrite1Bit(AVCEncBitstream *stream, uint code);
+
+ /**
+ This function adds trailing bits to the bitstream and reports back the final EBSP size.
+ \param "stream" "Pointer to the AVCEncBitstream structure."
+ \param "nal_size" "Output the final NAL size."
+ \return "AVCENC_SUCCESS if success or AVCENC_BITSTREAM_BUFFER_FULL if fail."
+ */
+ AVCEnc_Status BitstreamTrailingBits(AVCEncBitstream *bitstream, uint *nal_size);
+
+ /**
+ This function checks whether the current bit position is byte-aligned or not.
+ \param "stream" "Pointer to the bitstream structure."
+ \return "true if byte-aligned, false otherwise."
+ */
+ bool byte_aligned(AVCEncBitstream *stream);
+
+
+ /**
+ This function checks the availability of overrun buffer and switches to use it when
+ normal bufffer is not big enough.
+ \param "stream" "Pointer to the bitstream structure."
+ \param "numExtraBytes" "Number of extra byte needed."
+ \return "AVCENC_SUCCESS or AVCENC_FAIL."
+ */
+ AVCEnc_Status AVCBitstreamUseOverrunBuffer(AVCEncBitstream* stream, int numExtraBytes);
+
+
+ /*-------------- intra_est.c ---------------*/
+
+ /** This function performs intra/inter decision based on ABE.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "min_cost" "Best inter cost."
+ \param "curL" "Pointer to the current MB origin in reconstructed frame."
+ \param "picPitch" "Pitch of the reconstructed frame."
+ \return "Boolean for intra mode."
+ */
+
+//bool IntraDecisionABE(AVCEncObject *encvid, int min_cost, uint8 *curL, int picPitch);
+ bool IntraDecision(int *min_cost, uint8 *cur, int pitch, bool ave);
+
+ /**
+ This function performs intra prediction mode search.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "mbnum" "Current MB number."
+ \param "curL" "Pointer to the current MB origin in reconstructed frame."
+ \param "picPitch" "Pitch of the reconstructed frame."
+ \return "void."
+ */
+ void MBIntraSearch(AVCEncObject *encvid, int mbnum, uint8 *curL, int picPitch);
+
+ /**
+ This function generates all the I16 prediction modes for an MB and keep it in
+ encvid->pred_i16.
+ \param "encvid" "Pointer to AVCEncObject."
+ \return "void"
+ */
+ void intrapred_luma_16x16(AVCEncObject *encvid);
+
+ /**
+ This function calculate the cost of all I16 modes and compare them to get the minimum.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "orgY" "Pointer to the original luma MB."
+ \param "min_cost" "Pointer to the minimal cost so-far."
+ \return "void"
+ */
+ void find_cost_16x16(AVCEncObject *encvid, uint8 *orgY, int *min_cost);
+
+ /**
+ This function calculates the cost of each I16 mode.
+ \param "org" "Pointer to the original luma MB."
+ \param "org_pitch" "Stride size of the original frame."
+ \param "pred" "Pointer to the prediction values."
+ \param "min_cost" "Minimal cost so-far."
+ \return "Cost"
+ */
+
+ int cost_i16(uint8 *org, int org_pitch, uint8 *pred, int min_cost);
+
+ /**
+ This function generates all the I4 prediction modes and select the best one
+ for all the blocks inside a macroblock.It also calls dct_luma to generate the reconstructed
+ MB, and transform coefficients to be encoded.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "min_cost" "Pointer to the minimal cost so-far."
+ \return "void"
+ */
+ void mb_intra4x4_search(AVCEncObject *encvid, int *min_cost);
+
+ /**
+ This function calculates the most probable I4 mode of a given 4x4 block
+ from neighboring informationaccording to AVC/H.264 standard.
+ \param "video" "Pointer to AVCCommonObj."
+ \param "blkidx" "The current block index."
+ \return "Most probable mode."
+ */
+ int FindMostProbableI4Mode(AVCCommonObj *video, int blkidx);
+
+ /**
+ This function is where a lot of actions take place in the 4x4 block level inside
+ mb_intra4x4_search.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "blkidx" "The current 4x4 block index."
+ \param "cur" "Pointer to the reconstructed block."
+ \param "org" "Pointer to the original block."
+ \return "Minimal cost, also set currMB->i4Mode"
+ */
+ int blk_intra4x4_search(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org);
+
+ /**
+ This function calculates the cost of a given I4 prediction mode.
+ \param "org" "Pointer to the original block."
+ \param "org_pitch" "Stride size of the original frame."
+ \param "pred" "Pointer to the prediction block. (encvid->pred_i4)"
+ \param "cost" "Pointer to the minimal cost (to be updated)."
+ \return "void"
+ */
+ void cost_i4(uint8 *org, int org_pitch, uint8 *pred, uint16 *cost);
+
+ /**
+ This function performs chroma intra search. Each mode is saved in encvid->pred_ic.
+ \param "encvid" "Pointer to AVCEncObject."
+ \return "void"
+ */
+ void chroma_intra_search(AVCEncObject *encvid);
+
+ /**
+ This function calculates the cost of a chroma prediction mode.
+ \param "orgCb" "Pointer to the original Cb block."
+ \param "orgCr" "Pointer to the original Cr block."
+ \param "org_pitch" "Stride size of the original frame."
+ \param "pred" "Pointer to the prediction block (encvid->pred_ic)"
+ \param "mincost" "Minimal cost so far."
+ \return "Cost."
+ */
+
+ int SATDChroma(uint8 *orgCb, uint8 *orgCr, int org_pitch, uint8 *pred, int mincost);
+
+ /*-------------- motion_comp.c ---------------*/
+
+ /**
+ This is a main function to peform inter prediction.
+ \param "encvid" "Pointer to AVCEncObject."
+ \param "video" "Pointer to AVCCommonObj."
+ \return "void".
+ */
+ void AVCMBMotionComp(AVCEncObject *encvid, AVCCommonObj *video);
+
+
+ /**
+ This function is called for luma motion compensation.
+ \param "ref" "Pointer to the origin of a reference luma."
+ \param "picwidth" "Width of the picture."
+ \param "picheight" "Height of the picture."
+ \param "x_pos" "X-coordinate of the predicted block in quarter pel resolution."
+ \param "y_pos" "Y-coordinate of the predicted block in quarter pel resolution."
+ \param "pred" "Pointer to the output predicted block."
+ \param "pred_pitch" "Width of pred."
+ \param "blkwidth" "Width of the current partition."
+ \param "blkheight" "Height of the current partition."
+ \return "void"
+ */
+ void eLumaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos,
+ uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight);
+
+ void eFullPelMC(uint8 *in, int inwidth, uint8 *out, int outpitch,
+ int blkwidth, int blkheight);
+
+ void eHorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx);
+
+ void eHorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx);
+
+ void eHorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight);
+
+ void eVertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy);
+
+ void eVertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight);
+
+ void eVertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy);
+
+ void eDiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
+ uint8 *out, int outpitch,
+ int blkwidth, int blkheight);
+
+ void eChromaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos, uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight);
+
+ void eChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+ void eChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+ void eChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+ void eChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+ void eChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+ void eChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+ void eChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight);
+
+
+ /*-------------- motion_est.c ---------------*/
+
+ /**
+ Allocate and initialize arrays necessary for motion search algorithm.
+ \param "envid" "Pointer to AVCEncObject."
+ \return "AVC_SUCCESS or AVC_MEMORY_FAIL."
+ */
+ AVCEnc_Status InitMotionSearchModule(AVCHandle *avcHandle);
+
+ /**
+ Clean up memory allocated in InitMotionSearchModule.
+ \param "envid" "Pointer to AVCEncObject."
+ \return "void."
+ */
+ void CleanMotionSearchModule(AVCHandle *avcHandle);
+
+
+ /**
+ This function performs motion estimation of all macroblocks in a frame during the InitFrame.
+ The goal is to find the best MB partition for inter and find out if intra search is needed for
+ any MBs. This intra MB tendency can be used for scene change detection.
+ \param "encvid" "Pointer to AVCEncObject."
+ \return "void"
+ */
+ void AVCMotionEstimation(AVCEncObject *encvid);
+
+ /**
+ This function performs repetitive edge padding to the reference picture by adding 16 pixels
+ around the luma and 8 pixels around the chromas.
+ \param "refPic" "Pointer to the reference picture."
+ \return "void"
+ */
+ void AVCPaddingEdge(AVCPictureData *refPic);
+
+ /**
+ This function keeps track of intra refresh macroblock locations.
+ \param "encvid" "Pointer to the global array structure AVCEncObject."
+ \param "mblock" "Pointer to the array of AVCMacroblock structures."
+ \param "totalMB" "Total number of MBs in a frame."
+ \param "numRefresh" "Number of MB to be intra refresh in a single frame."
+ \return "void"
+ */
+ void AVCRasterIntraUpdate(AVCEncObject *encvid, AVCMacroblock *mblock, int totalMB, int numRefresh);
+
+#ifdef HTFM
+ void InitHTFM(VideoEncData *encvid, HTFM_Stat *htfm_stat, double *newvar, int *collect);
+ void UpdateHTFM(AVCEncObject *encvid, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat);
+ void CalcThreshold(double pf, double exp_lamda[], int nrmlz_th[]);
+ void HTFMPrepareCurMB_AVC(AVCEncObject *encvid, HTFM_Stat *htfm_stat, uint8 *cur, int pitch);
+#endif
+
+ /**
+ This function reads the input MB into a smaller faster memory space to minimize the cache miss.
+ \param "encvid" "Pointer to the global AVCEncObject."
+ \param "cur" "Pointer to the original input macroblock."
+ \param "pitch" "Stride size of the input frame (luma)."
+ \return "void"
+ */
+ void AVCPrepareCurMB(AVCEncObject *encvid, uint8 *cur, int pitch);
+
+ /**
+ Performs motion vector search for a macroblock.
+ \param "encvid" "Pointer to AVCEncObject structure."
+ \param "cur" "Pointer to the current macroblock in the input frame."
+ \param "best_cand" "Array of best candidates (to be filled in and returned)."
+ \param "i0" "X-coordinate of the macroblock."
+ \param "j0" "Y-coordinate of the macroblock."
+ \param "type_pred" "Indicates the type of operations."
+ \param "FS_en" "Flag for fullsearch enable."
+ \param "hp_guess" "Guess for half-pel search."
+ \return "void"
+ */
+ void AVCMBMotionSearch(AVCEncObject *encvid, uint8 *cur, uint8 *best_cand[],
+ int i0, int j0, int type_pred, int FS_en, int *hp_guess);
+
+//AVCEnc_Status AVCMBMotionSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum,
+// int num_pass);
+
+ /**
+ Perform full-pel exhaustive search around the predicted MV.
+ \param "encvid" "Pointer to AVCEncObject structure."
+ \param "prev" "Pointer to the reference frame."
+ \param "cur" "Pointer to the input macroblock."
+ \param "imin" "Pointer to minimal mv (x)."
+ \param "jmin" "Pointer to minimal mv (y)."
+ \param "ilow, ihigh, jlow, jhigh" "Lower bound on search range."
+ \param "cmvx, cmvy" "Predicted MV value."
+
+ \return "The cost function of the best candidate."
+ */
+ int AVCFullSearch(AVCEncObject *encvid, uint8 *prev, uint8 *cur,
+ int *imin, int *jmin, int ilow, int ihigh, int jlow, int jhigh,
+ int cmvx, int cmvy);
+
+ /**
+ Select candidates from neighboring blocks according to the type of the
+ prediction selection.
+ \param "mvx" "Pointer to the candidate, x-coordinate."
+ \param "mvy" "Pointer to the candidate, y-coordinate."
+ \param "num_can" "Pointer to the number of candidates returned."
+ \param "imb" "The MB index x-coordinate."
+ \param "jmb" "The MB index y-coordinate."
+ \param "type_pred" "Type of the prediction."
+ \param "cmvx, cmvy" "Pointer to predicted MV (modified version)."
+ \return "void."
+ */
+ void AVCCandidateSelection(int *mvx, int *mvy, int *num_can, int imb, int jmb,
+ AVCEncObject *encvid, int type_pred, int *cmvx, int *cmvy);
+
+ /**
+ Utility function to move the values in the array dn according to the new
+ location to avoid redundant calculation.
+ \param "dn" "Array of integer of size 9."
+ \param "new_loc" "New location index."
+ \return "void."
+ */
+ void AVCMoveNeighborSAD(int dn[], int new_loc);
+
+ /**
+ Find minimum index of dn.
+ \param "dn" "Array of integer of size 9."
+ \return "The index of dn with the smallest dn[] value."
+ */
+ int AVCFindMin(int dn[]);
+
+
+ /*------------- findhalfpel.c -------------------*/
+
+ /**
+ Search for the best half-pel resolution MV around the full-pel MV.
+ \param "encvid" "Pointer to the global AVCEncObject structure."
+ \param "cur" "Pointer to the current macroblock."
+ \param "mot" "Pointer to the AVCMV array of the frame."
+ \param "ncand" "Pointer to the origin of the fullsearch result."
+ \param "xpos" "The current MB position in x."
+ \param "ypos" "The current MB position in y."
+ \param "hp_guess" "Input to help speedup the search."
+ \param "cmvx, cmvy" "Predicted motion vector use for mvcost."
+ \return "Minimal cost (SATD) without MV cost. (for rate control purpose)"
+ */
+ int AVCFindHalfPelMB(AVCEncObject *encvid, uint8 *cur, AVCMV *mot, uint8 *ncand,
+ int xpos, int ypos, int hp_guess, int cmvx, int cmvy);
+
+ /**
+ This function generates sub-pel pixels required to do subpel MV search.
+ \param "subpel_pred" "Pointer to 2-D array, each array for each position."
+ \param "ncand" "Pointer to the full-pel center position in ref frame."
+ \param "lx" "Pitch of the ref frame."
+ \return "void"
+ */
+ void GenerateHalfPelPred(uint8 *subpel_pred, uint8 *ncand, int lx);
+
+ /**
+ This function calculate vertical interpolation at half-point of size 4x17.
+ \param "dst" "Pointer to destination."
+ \param "ref" "Pointer to the starting reference pixel."
+ \return "void."
+ */
+ void VertInterpWClip(uint8 *dst, uint8 *ref);
+
+ /**
+ This function generates quarter-pel pixels around the best half-pel result
+ during the sub-pel MV search.
+ \param "bilin_base" "Array of pointers to be used as basis for q-pel interp."
+ \param "qpel_pred" "Array of pointers pointing to quarter-pel candidates."
+ \param "hpel_pos" "Best half-pel position at the center."
+ \return "void"
+ */
+ void GenerateQuartPelPred(uint8 **bilin_base, uint8 *qpel_pred, int hpel_pos);
+
+ /**
+ This function calculates the SATD of a subpel candidate.
+ \param "cand" "Pointer to a candidate."
+ \param "cur" "Pointer to the current block."
+ \param "dmin" "Min-so-far SATD."
+ \return "Sum of Absolute Transformed Difference."
+ */
+ int SATD_MB(uint8 *cand, uint8 *cur, int dmin);
+
+ /*------------- rate_control.c -------------------*/
+
+ /** This function is a utility function. It returns average QP of the previously encoded frame.
+ \param "rateCtrl" "Pointer to AVCRateControl structure."
+ \return "Average QP."
+ */
+ int GetAvgFrameQP(AVCRateControl *rateCtrl);
+
+ /**
+ This function takes the timestamp of the input and determine whether it should be encoded
+ or skipped.
+ \param "encvid" "Pointer to the AVCEncObject structure."
+ \param "rateCtrl" "Pointer to the AVCRateControl structure."
+ \param "modTime" "The 32 bit timestamp of the input frame."
+ \param "frameNum" "Pointer to the frame number if to be encoded."
+ \return "AVC_SUCCESS or else."
+ */
+ AVCEnc_Status RCDetermineFrameNum(AVCEncObject *encvid, AVCRateControl *rateCtrl, uint32 modTime, uint *frameNum);
+
+ /**
+ This function updates the buffer fullness when frames are dropped either by the
+ rate control algorithm or by the users to make sure that target bit rate is still met.
+ \param "video" "Pointer to the common object structure."
+ \param "rateCtrl" "Pointer to rate control structure."
+ \param "frameInc" "Difference of the current frame number and previous frame number."
+ \return "void."
+ */
+ void RCUpdateBuffer(AVCCommonObj *video, AVCRateControl *rateCtrl, int frameInc);
+
+ /**
+ This function initializes rate control module and allocates necessary bufferes to do the job.
+ \param "avcHandle" "Pointer to the encoder handle."
+ \return "AVCENC_SUCCESS or AVCENC_MEMORY_FAIL."
+ */
+ AVCEnc_Status InitRateControlModule(AVCHandle *avcHandle);
+
+ /**
+ This function frees buffers allocated in InitRateControlModule.
+ \param "avcHandle" "Pointer to the encoder handle."
+ \return "void."
+ */
+ void CleanupRateControlModule(AVCHandle *avcHandle);
+
+ /**
+ This function is called at the beginning of each GOP or the first IDR frame. It calculates
+ target bits for a GOP.
+ \param "encvid" "Pointer to the encoder object."
+ \return "void."
+ */
+ void RCInitGOP(AVCEncObject *encvid);
+
+ /**
+ This function calculates target bits for a particular frame.
+ \param "video" "Pointer to the AVCEncObject structure."
+ \return "void"
+ */
+ void RCInitFrameQP(AVCEncObject *video);
+
+ /**
+ This function calculates QP for the upcoming frame or basic unit.
+ \param "encvid" "Pointer to the encoder object."
+ \param "rateCtrl" "Pointer to the rate control object."
+ \return "QP value ranging from 0-51."
+ */
+ int RCCalculateQP(AVCEncObject *encvid, AVCRateControl *rateCtrl);
+
+ /**
+ This function translates the luma QP to chroma QP and calculates lambda based on QP.
+ \param "video" "Pointer to the AVCEncObject structure."
+ \return "void"
+ */
+ void RCInitChromaQP(AVCEncObject *encvid);
+
+ /**
+ This function is called before encoding each macroblock.
+ \param "encvid" "Pointer to the encoder object."
+ \return "void."
+ */
+ void RCInitMBQP(AVCEncObject *encvid);
+
+ /**
+ This function updates bits usage stats after encoding an macroblock.
+ \param "video" "Pointer to AVCCommonObj."
+ \param "rateCtrl" "Pointer to AVCRateControl."
+ \param "num_header_bits" "Number of bits used for MB header."
+ \param "num_texture_bits" "Number of bits used for MB texture."
+ \return "void"
+ */
+ void RCPostMB(AVCCommonObj *video, AVCRateControl *rateCtrl, int num_header_bits, int num_texture_bits);
+
+ /**
+ This function calculates the difference between prediction and original MB.
+ \param "encvid" "Pointer to the encoder object."
+ \param "currMB" "Pointer to the current macroblock structure."
+ \param "orgL" "Pointer to the original MB."
+ \param "orgPitch" "Pointer to the original picture pitch."
+ \return "void."
+ */
+ void RCCalculateMAD(AVCEncObject *encvid, AVCMacroblock *currMB, uint8 *orgL, int orgPitch);
+
+ /**
+ Restore QP related parameters of previous MB when current MB is skipped.
+ \param "currMB" "Pointer to the current macroblock."
+ \param "video" "Pointer to the common video structure."
+ \param "encvid" "Pointer to the global encoding structure."
+ \return "void"
+ */
+ void RCRestoreQP(AVCMacroblock *currMB, AVCCommonObj *video, AVCEncObject *encvid);
+
+ /**
+ This function is called after done with a frame.
+ \param "encvid" "Pointer to the encoder object."
+ \return "AVCENC_SUCCESS or AVCENC_SKIPPED_PICTURE when bufer overflow (need to discard current frame)."
+ */
+ AVCEnc_Status RCUpdateFrame(AVCEncObject *encvid);
+
+ /*--------- residual.c -------------------*/
+
+ /**
+ This function encodes the intra pcm data and fill it in the corresponding location
+ on the current picture.
+ \param "video" "Pointer to AVCEncObject."
+ \return "AVCENC_SUCCESS if success, or else for bitstream errors."
+ */
+ AVCEnc_Status EncodeIntraPCM(AVCEncObject *video);
+
+ /**
+ This function performs CAVLC syntax encoding on the run and level information of the coefficients.
+ The level and run arrays are elements in AVCEncObject structure, populated by TransQuantZZ,
+ TransQuantIntraDC and TransQuantChromaDC functions.
+ \param "video" "Pointer to AVCEncObject."
+ \param "type" "One of AVCResidualType for a particular 4x4 block."
+ \param "bindx" "Block index or number of nonzero coefficients for AVC_Intra16DC and AVC_ChromaDC mode."
+ \param "currMB" "Pointer to the current macroblock structure."
+ \return "AVCENC_SUCCESS for success."
+ \Note "This function has 32-bit machine specific instruction!!!!"
+ */
+ AVCEnc_Status enc_residual_block(AVCEncObject *encvid, AVCResidualType type, int bindx, AVCMacroblock *currMB);
+
+
+ /*------------- sad.c ---------------------------*/
+
+
+ int AVCSAD_MB_HalfPel_Cxhyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_MB_HalfPel_Cyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_MB_HalfPel_Cxh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_Macroblock_C(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+
+#ifdef HTFM /* 3/2/1, Hypothesis Testing Fast Matching */
+ int AVCSAD_MB_HP_HTFM_Collectxhyh(uint8 *ref, uint8 *blk, int dmin_x, void *extra_info);
+ int AVCSAD_MB_HP_HTFM_Collectyh(uint8 *ref, uint8 *blk, int dmin_x, void *extra_info);
+ int AVCSAD_MB_HP_HTFM_Collectxh(uint8 *ref, uint8 *blk, int dmin_x, void *extra_info);
+ int AVCSAD_MB_HP_HTFMxhyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_MB_HP_HTFMyh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_MB_HP_HTFMxh(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_MB_HTFM_Collect(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+ int AVCSAD_MB_HTFM(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info);
+#endif
+
+
+ /*------------- slice.c -------------------------*/
+
+ /**
+ This function performs the main encoding loop for a slice.
+ \param "encvid" "Pointer to AVCEncObject."
+ \return "AVCENC_SUCCESS for success, AVCENC_PICTURE_READY for end-of-picture and
+ AVCENC_FAIL or AVCENC_SLICE_EMPTY otherwise."
+ */
+ AVCEnc_Status AVCEncodeSlice(AVCEncObject *encvid);
+
+ /**
+ This function performs the main encoding operation for one macroblock.
+ \param "video" "pointer to AVCEncObject."
+ \return "AVCENC_SUCCESS for success, or other bitstream related failure status."
+ */
+ AVCEnc_Status EncodeMB(AVCEncObject *video);
+
+ /**
+ This function calls prediction INTRA/INTER functions, transform,
+ quantization and zigzag scanning to get the run-level symbols.
+ \param "encvid" "pointer to AVCEncObject."
+ \param "curL" "pointer to Luma component of the current frame.
+ \param "curCb" "pointer to Cb component of the current frame.
+ \param "curCr" "pointer to Cr component of the current frame.
+ \return "void for now."
+ */
+ void MBPredTransQuantZZ(AVCEncObject *encvid, uint8 *curL, uint8 *curCb, uint8 *curCr);
+
+ /**
+ This function copies the content of the prediction MB into the reconstructed YUV
+ frame directly.
+ \param "curL" "Pointer to the destination Y component."
+ \param "curCb" "Pointer to the destination Cb component."
+ \param "curCr" "Pointer to the destination Cr component."
+ \param "predBlock" "Pointer to the prediction MB."
+ \param "picWidth" "The width of the frame."
+ \return "None."
+ */
+ void Copy_MB(uint8 *curL, uint8 *curCb, uint8 *curCr, uint8 *predBlock, int picWidth);
+
+ /**
+ This function encodes the mb_type, CBP, prediction mode, ref idx and MV.
+ \param "currMB" "Pointer to the current macroblock structure."
+ \param "video" "Pointer to the AVCEncObject structure."
+ \return "AVCENC_SUCCESS for success or else for fail."
+ */
+ AVCEnc_Status EncodeMBHeader(AVCMacroblock *currMB, AVCEncObject *video);
+
+ /**
+ This function finds the right mb_type for a macroblock given the mbMode, CBP,
+ NumPart, PredPartMode.
+ \param "currMB" "Pointer to the current macroblock structure."
+ \param "slice_type" "Value of the slice_type."
+ \return "mb_type."
+ */
+ uint InterpretMBType(AVCMacroblock *currMB, int slice_type);
+
+ /**
+ This function encodes the mb_pred part of the macroblock data.
+ \param "video" "Pointer to the AVCCommonObj structure."
+ \param "currMB" "Pointer to the current macroblock structure."
+ \param "stream" "Pointer to the AVCEncBitstream structure."
+ \return "AVCENC_SUCCESS for success or bitstream fail status."
+ */
+ AVCEnc_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+ /**
+ This function encodes the sub_mb_pred part of the macroblock data.
+ \param "video" "Pointer to the AVCCommonObj structure."
+ \param "currMB" "Pointer to the current macroblock structure."
+ \param "stream" "Pointer to the AVCEncBitstream structure."
+ \return "AVCENC_SUCCESS for success or bitstream fail status."
+ */
+ AVCEnc_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+ /**
+ This function interprets the sub_mb_type and sets necessary information
+ when the slice type is AVC_P_SLICE.
+ in the macroblock structure.
+ \param "mblock" "Pointer to current AVCMacroblock."
+ \param "sub_mb_type" "From the syntax bitstream."
+ \return "void"
+ */
+ void InterpretSubMBTypeP(AVCMacroblock *mblock, uint *sub_mb_type);
+
+ /**
+ This function interprets the sub_mb_type and sets necessary information
+ when the slice type is AVC_B_SLICE.
+ in the macroblock structure.
+ \param "mblock" "Pointer to current AVCMacroblock."
+ \param "sub_mb_type" "From the syntax bitstream."
+ \return "void"
+ */
+ void InterpretSubMBTypeB(AVCMacroblock *mblock, uint *sub_mb_type);
+
+ /**
+ This function encodes intra 4x4 mode. It calculates the predicted I4x4 mode and the
+ remnant to be encoded.
+ \param "video" "Pointer to AVCEncObject structure."
+ \param "currMB" "Pointer to the AVCMacroblock structure."
+ \param "stream" "Pointer to AVCEncBitstream sructure."
+ \return "AVCENC_SUCCESS for success."
+ */
+ AVCEnc_Status EncodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+ /*------------- vlc_encode.c -----------------------*/
+ /**
+ This function encodes and writes a value into an Exp-Golomb codeword.
+ \param "bitstream" "Pointer to AVCEncBitstream."
+ \param "codeNum" "Pointer to the value of the codeNum."
+ \return "AVCENC_SUCCESS for success or bitstream error messages for fail."
+ */
+ AVCEnc_Status ue_v(AVCEncBitstream *bitstream, uint codeNum);
+
+ /**
+ This function maps and encodes signed Exp-Golomb codes.
+ \param "bitstream" "Pointer to AVCEncBitstream."
+ \param "value" "Pointer to syntax element value."
+ \return "AVCENC_SUCCESS or AVCENC_FAIL."
+ */
+ AVCEnc_Status se_v(AVCEncBitstream *bitstream, int value);
+
+ /**
+ This function maps and encodes truncated Exp-Golomb codes.
+ \param "bitstream" "Pointer to AVCEncBitstream."
+ \param "value" "Pointer to syntax element value."
+ \param "range" "Range of the value as input to determine the algorithm."
+ \return "AVCENC_SUCCESS or AVCENC_FAIL."
+ */
+ AVCEnc_Status te_v(AVCEncBitstream *bitstream, uint value, uint range);
+
+ /**
+ This function creates Exp-Golomb codeword from codeNum.
+ \param "bitstream" "Pointer to AVCEncBitstream."
+ \param "codeNum" "Pointer to the codeNum value."
+ \return "AVCENC_SUCCESS for success or bitstream error messages for fail."
+ */
+ AVCEnc_Status SetEGBitstring(AVCEncBitstream *bitstream, uint codeNum);
+
+ /**
+ This function performs CAVLC encoding of the CBP (coded block pattern) of a macroblock
+ by calling ue_v() and then mapping the CBP to the corresponding VLC codeNum.
+ \param "currMB" "Pointer to the current AVCMacroblock structure."
+ \param "stream" "Pointer to the AVCEncBitstream."
+ \return "void"
+ */
+ AVCEnc_Status EncodeCBP(AVCMacroblock *currMB, AVCEncBitstream *stream);
+
+ /**
+ This function encodes trailing ones and total coefficient.
+ \param "stream" "Pointer to the AVCEncBitstream."
+ \param "TrailingOnes" "The trailing one variable output."
+ \param "TotalCoeff" "The total coefficient variable output."
+ \param "nC" "Context for number of nonzero coefficient (prediction context)."
+ \return "AVCENC_SUCCESS for success or else for bitstream failure."
+ */
+ AVCEnc_Status ce_TotalCoeffTrailingOnes(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff, int nC);
+
+ /**
+ This function encodes trailing ones and total coefficient for chroma DC block.
+ \param "stream" "Pointer to the AVCEncBitstream."
+ \param "TrailingOnes" "The trailing one variable output."
+ \param "TotalCoeff" "The total coefficient variable output."
+ \return "AVCENC_SUCCESS for success or else for bitstream failure."
+ */
+ AVCEnc_Status ce_TotalCoeffTrailingOnesChromaDC(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff);
+
+ /**
+ This function encodes total_zeros value as in Table 9-7 and 9-8.
+ \param "stream" "Pointer to the AVCEncBitstream."
+ \param "TotalZeros" "The total_zeros value."
+ \param "TotalCoeff" "The total coefficient variable output."
+ \return "AVCENC_SUCCESS for success or else for bitstream failure."
+ */
+ AVCEnc_Status ce_TotalZeros(AVCEncBitstream *stream, int total_zeros, int TotalCoeff);
+
+ /**
+ This function encodes total_zeros VLC syntax for chroma DC as in Table 9-9.
+ \param "stream" "Pointer to the AVCEncBitstream."
+ \param "TotalZeros" "The total_zeros value."
+ \param "TotalCoeff" "The total coefficient variable output."
+ \return "AVCENC_SUCCESS for success or else for bitstream failure."
+ */
+ AVCEnc_Status ce_TotalZerosChromaDC(AVCEncBitstream *stream, int total_zeros, int TotalCoeff);
+
+ /**
+ This function encodes run_before VLC syntax as in Table 9-10.
+ \param "stream" "Pointer to the AVCEncBitstream."
+ \param "run_before" "The run_before value."
+ \param "zerosLeft" "The context for number of zeros left."
+ \return "AVCENC_SUCCESS for success or else for bitstream failure."
+ */
+ AVCEnc_Status ce_RunBefore(AVCEncBitstream *stream, int run_before, int zerosLeft);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _AVCENC_LIB_H_ */
+
diff --git a/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp
new file mode 100644
index 0000000..75ab514
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/bitstream_io.cpp
@@ -0,0 +1,336 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+#define WORD_SIZE 32
+
+/* array for trailing bit pattern as function of number of bits */
+/* the first one is unused. */
+const static uint8 trailing_bits[9] = {0, 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80};
+
+/* ======================================================================== */
+/* Function : BitstreamInit() */
+/* Date : 11/4/2003 */
+/* Purpose : Populate bitstream structure with bitstream buffer and size */
+/* it also initializes internal data */
+/* In/out : */
+/* Return : AVCENC_SUCCESS if successed, AVCENC_FAIL if failed. */
+/* Modified : */
+/* ======================================================================== */
+/* |--------|--------|----~~~~~-----|---------|---------|---------|
+ ^ ^write_pos ^buf_size
+ bitstreamBuffer <--------->
+ current_word
+
+ |-----xxxxxxxxxxxxx| = current_word 32 or 16 bits
+ <---->
+ bit_left
+ ======================================================================== */
+
+AVCEnc_Status BitstreamEncInit(AVCEncBitstream *stream, uint8 *buffer, int buf_size,
+ uint8 *overrunBuffer, int oBSize)
+{
+ if (stream == NULL || buffer == NULL || buf_size <= 0)
+ {
+ return AVCENC_BITSTREAM_INIT_FAIL;
+ }
+
+ stream->bitstreamBuffer = buffer;
+
+ stream->buf_size = buf_size;
+
+ stream->write_pos = 0;
+
+ stream->count_zeros = 0;
+
+ stream->current_word = 0;
+
+ stream->bit_left = WORD_SIZE;
+
+ stream->overrunBuffer = overrunBuffer;
+
+ stream->oBSize = oBSize;
+
+ return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : AVCBitstreamSaveWord() */
+/* Date : 3/29/2004 */
+/* Purpose : Save the current_word into the buffer, byte-swap, and */
+/* add emulation prevention insertion. */
+/* In/out : */
+/* Return : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is */
+/* full. */
+/* Modified : */
+/* ======================================================================== */
+AVCEnc_Status AVCBitstreamSaveWord(AVCEncBitstream *stream)
+{
+ int num_bits;
+ uint8 *write_pnt, byte;
+ uint current_word;
+
+ /* check number of bytes in current_word, must always be byte-aligned!!!! */
+ num_bits = WORD_SIZE - stream->bit_left; /* must be multiple of 8 !!*/
+
+ if (stream->buf_size - stream->write_pos <= (num_bits >> 3) + 2) /* 2 more bytes for possible EPBS */
+ {
+ if (AVCENC_SUCCESS != AVCBitstreamUseOverrunBuffer(stream, (num_bits >> 3) + 2))
+ {
+ return AVCENC_BITSTREAM_BUFFER_FULL;
+ }
+ }
+
+ /* write word, byte-by-byte */
+ write_pnt = stream->bitstreamBuffer + stream->write_pos;
+ current_word = stream->current_word;
+ while (num_bits) /* no need to check stream->buf_size and stream->write_pos, taken care already */
+ {
+ num_bits -= 8;
+ byte = (current_word >> num_bits) & 0xFF;
+ if (byte != 0)
+ {
+ *write_pnt++ = byte;
+ stream->write_pos++;
+ stream->count_zeros = 0;
+ }
+ else
+ {
+ stream->count_zeros++;
+ *write_pnt++ = byte;
+ stream->write_pos++;
+ if (stream->count_zeros == 2)
+ { /* for num_bits = 32, this can add 2 more bytes extra for EPBS */
+ *write_pnt++ = 0x3;
+ stream->write_pos++;
+ stream->count_zeros = 0;
+ }
+ }
+ }
+
+ /* reset current_word and bit_left */
+ stream->current_word = 0;
+ stream->bit_left = WORD_SIZE;
+
+ return AVCENC_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamWriteBits() */
+/* Date : 3/29/2004 */
+/* Purpose : Write up to machine word. */
+/* In/out : Unused bits in 'code' must be all zeros. */
+/* Return : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is */
+/* full. */
+/* Modified : */
+/* ======================================================================== */
+AVCEnc_Status BitstreamWriteBits(AVCEncBitstream *stream, int nBits, uint code)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ int bit_left = stream->bit_left;
+ uint current_word = stream->current_word;
+
+ //DEBUG_LOG(userData,AVC_LOGTYPE_INFO,"BitstreamWriteBits",nBits,-1);
+
+ if (nBits > WORD_SIZE) /* has to be taken care of specially */
+ {
+ return AVCENC_FAIL; /* for now */
+ /* otherwise, break it down to 2 write of less than 16 bits at a time. */
+ }
+
+ if (nBits <= bit_left) /* more bits left in current_word */
+ {
+ stream->current_word = (current_word << nBits) | code;
+ stream->bit_left -= nBits;
+ if (stream->bit_left == 0) /* prepare for the next word */
+ {
+ status = AVCBitstreamSaveWord(stream);
+ return status;
+ }
+ }
+ else
+ {
+ stream->current_word = (current_word << bit_left) | (code >> (nBits - bit_left));
+
+ nBits -= bit_left;
+
+ stream->bit_left = 0;
+
+ status = AVCBitstreamSaveWord(stream); /* save current word */
+
+ stream->bit_left = WORD_SIZE - nBits;
+
+ stream->current_word = code; /* no extra masking for code, must be handled before saving */
+ }
+
+ return status;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamWrite1Bit() */
+/* Date : 3/30/2004 */
+/* Purpose : Write 1 bit */
+/* In/out : Unused bits in 'code' must be all zeros. */
+/* Return : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is */
+/* full. */
+/* Modified : */
+/* ======================================================================== */
+AVCEnc_Status BitstreamWrite1Bit(AVCEncBitstream *stream, uint code)
+{
+ AVCEnc_Status status;
+ uint current_word = stream->current_word;
+
+ //DEBUG_LOG(userData,AVC_LOGTYPE_INFO,"BitstreamWrite1Bit",code,-1);
+
+ //if(1 <= bit_left) /* more bits left in current_word */
+ /* we can assume that there always be positive bit_left in the current word */
+ stream->current_word = (current_word << 1) | code;
+ stream->bit_left--;
+ if (stream->bit_left == 0) /* prepare for the next word */
+ {
+ status = AVCBitstreamSaveWord(stream);
+ return status;
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamTrailingBits() */
+/* Date : 3/31/2004 */
+/* Purpose : Add trailing bits and report the final EBSP size. */
+/* In/out : */
+/* Return : AVCENC_SUCCESS if successed, AVCENC_WRITE_FAIL if buffer is */
+/* full. */
+/* Modified : */
+/* ======================================================================== */
+AVCEnc_Status BitstreamTrailingBits(AVCEncBitstream *bitstream, uint *nal_size)
+{
+ (void)(nal_size);
+
+ AVCEnc_Status status;
+ int bit_left = bitstream->bit_left;
+
+ bit_left &= 0x7; /* modulo by 8 */
+ if (bit_left == 0) bit_left = 8;
+ /* bitstream->bit_left == 0 cannot happen here since it would have been Saved already */
+
+ status = BitstreamWriteBits(bitstream, bit_left, trailing_bits[bit_left]);
+
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ /* if it's not saved, save it. */
+ //if(bitstream->bit_left<(WORD_SIZE<<3)) /* in fact, no need to check */
+ {
+ status = AVCBitstreamSaveWord(bitstream);
+ }
+
+ return status;
+}
+
+/* check whether it's byte-aligned */
+bool byte_aligned(AVCEncBitstream *stream)
+{
+ if (stream->bit_left % 8)
+ return false;
+ else
+ return true;
+}
+
+
+/* determine whether overrun buffer can be used or not */
+AVCEnc_Status AVCBitstreamUseOverrunBuffer(AVCEncBitstream* stream, int numExtraBytes)
+{
+ AVCEncObject *encvid = (AVCEncObject*)stream->encvid;
+
+ if (stream->overrunBuffer != NULL) // overrunBuffer is set
+ {
+ if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
+ {
+ if (stream->write_pos + numExtraBytes >= stream->oBSize)
+ {
+ stream->oBSize = stream->write_pos + numExtraBytes + 100;
+ stream->oBSize &= (~0x3); // make it multiple of 4
+
+ // allocate new overrun Buffer
+ if (encvid->overrunBuffer)
+ {
+ encvid->avcHandle->CBAVC_Free((uint32*)encvid->avcHandle->userData,
+ (int)encvid->overrunBuffer);
+ }
+
+ encvid->oBSize = stream->oBSize;
+ encvid->overrunBuffer = (uint8*) encvid->avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+ stream->oBSize, DEFAULT_ATTR);
+
+ stream->overrunBuffer = encvid->overrunBuffer;
+ if (stream->overrunBuffer == NULL)
+ {
+ return AVCENC_FAIL;
+ }
+ }
+
+ // copy everything to overrun buffer and start using it.
+ memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->write_pos);
+ stream->bitstreamBuffer = stream->overrunBuffer;
+ stream->buf_size = stream->oBSize;
+ }
+ else // overrun buffer is already used
+ {
+ stream->oBSize = stream->write_pos + numExtraBytes + 100;
+ stream->oBSize &= (~0x3); // make it multiple of 4
+
+ // allocate new overrun buffer
+ encvid->oBSize = stream->oBSize;
+ encvid->overrunBuffer = (uint8*) encvid->avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+ stream->oBSize, DEFAULT_ATTR);
+
+ if (encvid->overrunBuffer == NULL)
+ {
+ return AVCENC_FAIL;
+ }
+
+
+ // copy from the old buffer to new buffer
+ memcpy(encvid->overrunBuffer, stream->overrunBuffer, stream->write_pos);
+ // free old buffer
+ encvid->avcHandle->CBAVC_Free((uint32*)encvid->avcHandle->userData,
+ (int)stream->overrunBuffer);
+
+ // assign pointer to new buffer
+ stream->overrunBuffer = encvid->overrunBuffer;
+ stream->bitstreamBuffer = stream->overrunBuffer;
+ stream->buf_size = stream->oBSize;
+ }
+
+ return AVCENC_SUCCESS;
+ }
+ else // overrunBuffer is not enable.
+ {
+ return AVCENC_FAIL;
+ }
+
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/block.cpp b/media/libstagefright/codecs/avc/enc/src/block.cpp
new file mode 100644
index 0000000..01e26a6
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/block.cpp
@@ -0,0 +1,1283 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+/* subtract with the prediction and do transformation */
+void trans(uint8 *cur, int pitch, uint8 *predBlock, int16 *dataBlock)
+{
+ int16 *ptr = dataBlock;
+ int r0, r1, r2, r3, j;
+ int curpitch = (uint)pitch >> 16;
+ int predpitch = (pitch & 0xFFFF);
+
+ /* horizontal */
+ j = 4;
+ while (j > 0)
+ {
+ /* calculate the residue first */
+ r0 = cur[0] - predBlock[0];
+ r1 = cur[1] - predBlock[1];
+ r2 = cur[2] - predBlock[2];
+ r3 = cur[3] - predBlock[3];
+
+ r0 += r3; //ptr[0] + ptr[3];
+ r3 = r0 - (r3 << 1); //ptr[0] - ptr[3];
+ r1 += r2; //ptr[1] + ptr[2];
+ r2 = r1 - (r2 << 1); //ptr[1] - ptr[2];
+
+ ptr[0] = r0 + r1;
+ ptr[2] = r0 - r1;
+ ptr[1] = (r3 << 1) + r2;
+ ptr[3] = r3 - (r2 << 1);
+
+ ptr += 16;
+ predBlock += predpitch;
+ cur += curpitch;
+ j--;
+ }
+ /* vertical */
+ ptr = dataBlock;
+ j = 4;
+ while (j > 0)
+ {
+ r0 = ptr[0] + ptr[48];
+ r3 = ptr[0] - ptr[48];
+ r1 = ptr[16] + ptr[32];
+ r2 = ptr[16] - ptr[32];
+
+ ptr[0] = r0 + r1;
+ ptr[32] = r0 - r1;
+ ptr[16] = (r3 << 1) + r2;
+ ptr[48] = r3 - (r2 << 1);
+
+ ptr++;
+ j--;
+ }
+
+ return ;
+}
+
+
+/* do residue transform quant invquant, invtrans and write output out */
+int dct_luma(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org, int *coef_cost)
+{
+ AVCCommonObj *video = encvid->common;
+ int org_pitch = encvid->currInput->pitch;
+ int pitch = video->currPic->pitch;
+ int16 *coef = video->block;
+ uint8 *pred = video->pred_block; // size 16 for a 4x4 block
+ int pred_pitch = video->pred_pitch;
+ int r0, r1, r2, r3, j, k, idx;
+ int *level, *run;
+ int Qq, Rq, q_bits, qp_const, quant;
+ int data, lev, zero_run;
+ int numcoeff;
+
+ coef += ((blkidx & 0x3) << 2) + ((blkidx >> 2) << 6); /* point to the 4x4 block */
+
+ /* first take a 4x4 transform */
+ /* horizontal */
+ j = 4;
+ while (j > 0)
+ {
+ /* calculate the residue first */
+ r0 = org[0] - pred[0]; /* OPTIMIZEABLE */
+ r1 = org[1] - pred[1];
+ r2 = org[2] - pred[2];
+ r3 = org[3] - pred[3];
+
+ r0 += r3; //ptr[0] + ptr[3];
+ r3 = r0 - (r3 << 1); //ptr[0] - ptr[3];
+ r1 += r2; //ptr[1] + ptr[2];
+ r2 = r1 - (r2 << 1); //ptr[1] - ptr[2];
+
+ coef[0] = r0 + r1;
+ coef[2] = r0 - r1;
+ coef[1] = (r3 << 1) + r2;
+ coef[3] = r3 - (r2 << 1);
+
+ coef += 16;
+ org += org_pitch;
+ pred += pred_pitch;
+ j--;
+ }
+ /* vertical */
+ coef -= 64;
+ pred -= (pred_pitch << 2);
+ j = 4;
+ while (j > 0) /* OPTIMIZABLE */
+ {
+ r0 = coef[0] + coef[48];
+ r3 = coef[0] - coef[48];
+ r1 = coef[16] + coef[32];
+ r2 = coef[16] - coef[32];
+
+ coef[0] = r0 + r1;
+ coef[32] = r0 - r1;
+ coef[16] = (r3 << 1) + r2;
+ coef[48] = r3 - (r2 << 1);
+
+ coef++;
+ j--;
+ }
+
+ coef -= 4;
+
+ /* quant */
+ level = encvid->level[ras2dec[blkidx]];
+ run = encvid->run[ras2dec[blkidx]];
+
+ Rq = video->QPy_mod_6;
+ Qq = video->QPy_div_6;
+ qp_const = encvid->qp_const;
+ q_bits = 15 + Qq;
+
+ zero_run = 0;
+ numcoeff = 0;
+ for (k = 0; k < 16; k++)
+ {
+ idx = ZZ_SCAN_BLOCK[k]; /* map back to raster scan order */
+ data = coef[idx];
+ quant = quant_coef[Rq][k];
+ if (data > 0)
+ {
+ lev = data * quant + qp_const;
+ }
+ else
+ {
+ lev = -data * quant + qp_const;
+ }
+ lev >>= q_bits;
+ if (lev)
+ {
+ *coef_cost += ((lev > 1) ? MAX_VALUE : COEFF_COST[DISABLE_THRESHOLDING][zero_run]);
+
+ /* dequant */
+ quant = dequant_coefres[Rq][k];
+ if (data > 0)
+ {
+ level[numcoeff] = lev;
+ coef[idx] = (lev * quant) << Qq;
+ }
+ else
+ {
+ level[numcoeff] = -lev;
+ coef[idx] = (-lev * quant) << Qq;
+ }
+ run[numcoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ coef[idx] = 0;
+ }
+ }
+
+ if (video->currMB->mb_intra) // only do inverse transform with intra block
+ {
+ if (numcoeff) /* then do inverse transform */
+ {
+ for (j = 4; j > 0; j--) /* horizontal */
+ {
+ r0 = coef[0] + coef[2];
+ r1 = coef[0] - coef[2];
+ r2 = (coef[1] >> 1) - coef[3];
+ r3 = coef[1] + (coef[3] >> 1);
+
+ coef[0] = r0 + r3;
+ coef[1] = r1 + r2;
+ coef[2] = r1 - r2;
+ coef[3] = r0 - r3;
+
+ coef += 16;
+ }
+
+ coef -= 64;
+ for (j = 4; j > 0; j--) /* vertical, has to be done after horizontal */
+ {
+ r0 = coef[0] + coef[32];
+ r1 = coef[0] - coef[32];
+ r2 = (coef[16] >> 1) - coef[48];
+ r3 = coef[16] + (coef[48] >> 1);
+ r0 += r3;
+ r3 = (r0 - (r3 << 1)); /* r0-r3 */
+ r1 += r2;
+ r2 = (r1 - (r2 << 1)); /* r1-r2 */
+ r0 += 32;
+ r1 += 32;
+ r2 += 32;
+ r3 += 32;
+
+ r0 = pred[0] + (r0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ r1 = *(pred += pred_pitch) + (r1 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ r2 = *(pred += pred_pitch) + (r2 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ r3 = pred[pred_pitch] + (r3 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+
+ *cur = r0;
+ *(cur += pitch) = r1;
+ *(cur += pitch) = r2;
+ cur[pitch] = r3;
+ cur -= (pitch << 1);
+ cur++;
+ pred -= (pred_pitch << 1);
+ pred++;
+ coef++;
+ }
+ }
+ else // copy from pred to cur
+ {
+ *((uint32*)cur) = *((uint32*)pred);
+ *((uint32*)(cur += pitch)) = *((uint32*)(pred += pred_pitch));
+ *((uint32*)(cur += pitch)) = *((uint32*)(pred += pred_pitch));
+ *((uint32*)(cur += pitch)) = *((uint32*)(pred += pred_pitch));
+ }
+ }
+
+ return numcoeff;
+}
+
+
+void MBInterIdct(AVCCommonObj *video, uint8 *curL, AVCMacroblock *currMB, int picPitch)
+{
+ int16 *coef, *coef8 = video->block;
+ uint8 *cur; // the same as curL
+ int b8, b4;
+ int r0, r1, r2, r3, j, blkidx;
+
+ for (b8 = 0; b8 < 4; b8++)
+ {
+ cur = curL;
+ coef = coef8;
+
+ if (currMB->CBP&(1 << b8))
+ {
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ blkidx = blkIdx2blkXY[b8][b4];
+ /* do IDCT */
+ if (currMB->nz_coeff[blkidx])
+ {
+ for (j = 4; j > 0; j--) /* horizontal */
+ {
+ r0 = coef[0] + coef[2];
+ r1 = coef[0] - coef[2];
+ r2 = (coef[1] >> 1) - coef[3];
+ r3 = coef[1] + (coef[3] >> 1);
+
+ coef[0] = r0 + r3;
+ coef[1] = r1 + r2;
+ coef[2] = r1 - r2;
+ coef[3] = r0 - r3;
+
+ coef += 16;
+ }
+
+ coef -= 64;
+ for (j = 4; j > 0; j--) /* vertical, has to be done after horizontal */
+ {
+ r0 = coef[0] + coef[32];
+ r1 = coef[0] - coef[32];
+ r2 = (coef[16] >> 1) - coef[48];
+ r3 = coef[16] + (coef[48] >> 1);
+ r0 += r3;
+ r3 = (r0 - (r3 << 1)); /* r0-r3 */
+ r1 += r2;
+ r2 = (r1 - (r2 << 1)); /* r1-r2 */
+ r0 += 32;
+ r1 += 32;
+ r2 += 32;
+ r3 += 32;
+
+ r0 = cur[0] + (r0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ *cur = r0;
+ r1 = *(cur += picPitch) + (r1 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ *cur = r1;
+ r2 = *(cur += picPitch) + (r2 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ *cur = r2;
+ r3 = cur[picPitch] + (r3 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+ cur[picPitch] = r3;
+
+ cur -= (picPitch << 1);
+ cur++;
+ coef++;
+ }
+ cur -= 4;
+ coef -= 4;
+ }
+ if (b4&1)
+ {
+ cur += ((picPitch << 2) - 4);
+ coef += 60;
+ }
+ else
+ {
+ cur += 4;
+ coef += 4;
+ }
+ }
+ }
+
+ if (b8&1)
+ {
+ curL += ((picPitch << 3) - 8);
+ coef8 += 120;
+ }
+ else
+ {
+ curL += 8;
+ coef8 += 8;
+ }
+ }
+
+ return ;
+}
+
+/* performa dct, quant, iquant, idct for the entire MB */
+void dct_luma_16x16(AVCEncObject *encvid, uint8 *curL, uint8 *orgL)
+{
+ AVCCommonObj *video = encvid->common;
+ int pitch = video->currPic->pitch;
+ int org_pitch = encvid->currInput->pitch;
+ AVCMacroblock *currMB = video->currMB;
+ int16 *coef = video->block;
+ uint8 *pred = encvid->pred_i16[currMB->i16Mode];
+ int blk_x, blk_y, j, k, idx, b8, b4;
+ int r0, r1, r2, r3, m0, m1, m2 , m3;
+ int data, lev;
+ int *level, *run, zero_run, ncoeff;
+ int Rq, Qq, quant, q_bits, qp_const;
+ int offset_cur[4], offset_pred[4], offset;
+
+ /* horizontal */
+ for (j = 16; j > 0; j--)
+ {
+ for (blk_x = 4; blk_x > 0; blk_x--)
+ {
+ /* calculate the residue first */
+ r0 = *orgL++ - *pred++;
+ r1 = *orgL++ - *pred++;
+ r2 = *orgL++ - *pred++;
+ r3 = *orgL++ - *pred++;
+
+ r0 += r3; //ptr[0] + ptr[3];
+ r3 = r0 - (r3 << 1); //ptr[0] - ptr[3];
+ r1 += r2; //ptr[1] + ptr[2];
+ r2 = r1 - (r2 << 1); //ptr[1] - ptr[2];
+
+ *coef++ = r0 + r1;
+ *coef++ = (r3 << 1) + r2;
+ *coef++ = r0 - r1;
+ *coef++ = r3 - (r2 << 1);
+ }
+ orgL += (org_pitch - 16);
+ }
+ pred -= 256;
+ coef -= 256;
+ /* vertical */
+ for (blk_y = 4; blk_y > 0; blk_y--)
+ {
+ for (j = 16; j > 0; j--)
+ {
+ r0 = coef[0] + coef[48];
+ r3 = coef[0] - coef[48];
+ r1 = coef[16] + coef[32];
+ r2 = coef[16] - coef[32];
+
+ coef[0] = r0 + r1;
+ coef[32] = r0 - r1;
+ coef[16] = (r3 << 1) + r2;
+ coef[48] = r3 - (r2 << 1);
+
+ coef++;
+ }
+ coef += 48;
+ }
+
+ /* then perform DC transform */
+ coef -= 256;
+ for (j = 4; j > 0; j--)
+ {
+ r0 = coef[0] + coef[12];
+ r3 = coef[0] - coef[12];
+ r1 = coef[4] + coef[8];
+ r2 = coef[4] - coef[8];
+
+ coef[0] = r0 + r1;
+ coef[8] = r0 - r1;
+ coef[4] = r3 + r2;
+ coef[12] = r3 - r2;
+ coef += 64;
+ }
+ coef -= 256;
+ for (j = 4; j > 0; j--)
+ {
+ r0 = coef[0] + coef[192];
+ r3 = coef[0] - coef[192];
+ r1 = coef[64] + coef[128];
+ r2 = coef[64] - coef[128];
+
+ coef[0] = (r0 + r1) >> 1;
+ coef[128] = (r0 - r1) >> 1;
+ coef[64] = (r3 + r2) >> 1;
+ coef[192] = (r3 - r2) >> 1;
+ coef += 4;
+ }
+
+ coef -= 16;
+ // then quantize DC
+ level = encvid->leveldc;
+ run = encvid->rundc;
+
+ Rq = video->QPy_mod_6;
+ Qq = video->QPy_div_6;
+ quant = quant_coef[Rq][0];
+ q_bits = 15 + Qq;
+ qp_const = encvid->qp_const;
+
+ zero_run = 0;
+ ncoeff = 0;
+ for (k = 0; k < 16; k++) /* in zigzag scan order */
+ {
+ idx = ZIGZAG2RASTERDC[k];
+ data = coef[idx];
+ if (data > 0) // quant
+ {
+ lev = data * quant + (qp_const << 1);
+ }
+ else
+ {
+ lev = -data * quant + (qp_const << 1);
+ }
+ lev >>= (q_bits + 1);
+ if (lev) // dequant
+ {
+ if (data > 0)
+ {
+ level[ncoeff] = lev;
+ coef[idx] = lev;
+ }
+ else
+ {
+ level[ncoeff] = -lev;
+ coef[idx] = -lev;
+ }
+ run[ncoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ coef[idx] = 0;
+ }
+ }
+
+ /* inverse transform DC */
+ encvid->numcoefdc = ncoeff;
+ if (ncoeff)
+ {
+ quant = dequant_coefres[Rq][0];
+
+ for (j = 0; j < 4; j++)
+ {
+ m0 = coef[0] + coef[4];
+ m1 = coef[0] - coef[4];
+ m2 = coef[8] + coef[12];
+ m3 = coef[8] - coef[12];
+
+
+ coef[0] = m0 + m2;
+ coef[4] = m0 - m2;
+ coef[8] = m1 - m3;
+ coef[12] = m1 + m3;
+ coef += 64;
+ }
+
+ coef -= 256;
+
+ if (Qq >= 2) /* this way should be faster than JM */
+ { /* they use (((m4*scale)<<(QPy/6))+2)>>2 for both cases. */
+ Qq -= 2;
+ for (j = 0; j < 4; j++)
+ {
+ m0 = coef[0] + coef[64];
+ m1 = coef[0] - coef[64];
+ m2 = coef[128] + coef[192];
+ m3 = coef[128] - coef[192];
+
+ coef[0] = ((m0 + m2) * quant) << Qq;
+ coef[64] = ((m0 - m2) * quant) << Qq;
+ coef[128] = ((m1 - m3) * quant) << Qq;
+ coef[192] = ((m1 + m3) * quant) << Qq;
+ coef += 4;
+ }
+ Qq += 2; /* restore the value */
+ }
+ else
+ {
+ Qq = 2 - Qq;
+ offset = 1 << (Qq - 1);
+
+ for (j = 0; j < 4; j++)
+ {
+ m0 = coef[0] + coef[64];
+ m1 = coef[0] - coef[64];
+ m2 = coef[128] + coef[192];
+ m3 = coef[128] - coef[192];
+
+ coef[0] = (((m0 + m2) * quant + offset) >> Qq);
+ coef[64] = (((m0 - m2) * quant + offset) >> Qq);
+ coef[128] = (((m1 - m3) * quant + offset) >> Qq);
+ coef[192] = (((m1 + m3) * quant + offset) >> Qq);
+ coef += 4;
+ }
+ Qq = 2 - Qq; /* restore the value */
+ }
+ coef -= 16; /* back to the origin */
+ }
+
+ /* now zigzag scan ac coefs, quant, iquant and itrans */
+ run = encvid->run[0];
+ level = encvid->level[0];
+
+ /* offset btw 4x4 block */
+ offset_cur[0] = 0;
+ offset_cur[1] = (pitch << 2) - 8;
+
+ /* offset btw 8x8 block */
+ offset_cur[2] = 8 - (pitch << 3);
+ offset_cur[3] = -8;
+
+ /* similarly for pred */
+ offset_pred[0] = 0;
+ offset_pred[1] = 56;
+ offset_pred[2] = -120;
+ offset_pred[3] = -8;
+
+ currMB->CBP = 0;
+
+ for (b8 = 0; b8 < 4; b8++)
+ {
+ for (b4 = 0; b4 < 4; b4++)
+ {
+
+ zero_run = 0;
+ ncoeff = 0;
+
+ for (k = 1; k < 16; k++)
+ {
+ idx = ZZ_SCAN_BLOCK[k]; /* map back to raster scan order */
+ data = coef[idx];
+ quant = quant_coef[Rq][k];
+ if (data > 0)
+ {
+ lev = data * quant + qp_const;
+ }
+ else
+ {
+ lev = -data * quant + qp_const;
+ }
+ lev >>= q_bits;
+ if (lev)
+ { /* dequant */
+ quant = dequant_coefres[Rq][k];
+ if (data > 0)
+ {
+ level[ncoeff] = lev;
+ coef[idx] = (lev * quant) << Qq;
+ }
+ else
+ {
+ level[ncoeff] = -lev;
+ coef[idx] = (-lev * quant) << Qq;
+ }
+ run[ncoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ coef[idx] = 0;
+ }
+ }
+
+ currMB->nz_coeff[blkIdx2blkXY[b8][b4]] = ncoeff; /* in raster scan !!! */
+ if (ncoeff)
+ {
+ currMB->CBP |= (1 << b8);
+
+ // do inverse transform here
+ for (j = 4; j > 0; j--)
+ {
+ r0 = coef[0] + coef[2];
+ r1 = coef[0] - coef[2];
+ r2 = (coef[1] >> 1) - coef[3];
+ r3 = coef[1] + (coef[3] >> 1);
+
+ coef[0] = r0 + r3;
+ coef[1] = r1 + r2;
+ coef[2] = r1 - r2;
+ coef[3] = r0 - r3;
+
+ coef += 16;
+ }
+ coef -= 64;
+ for (j = 4; j > 0; j--)
+ {
+ r0 = coef[0] + coef[32];
+ r1 = coef[0] - coef[32];
+ r2 = (coef[16] >> 1) - coef[48];
+ r3 = coef[16] + (coef[48] >> 1);
+
+ r0 += r3;
+ r3 = (r0 - (r3 << 1)); /* r0-r3 */
+ r1 += r2;
+ r2 = (r1 - (r2 << 1)); /* r1-r2 */
+ r0 += 32;
+ r1 += 32;
+ r2 += 32;
+ r3 += 32;
+ r0 = pred[0] + (r0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ r1 = pred[16] + (r1 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ r2 = pred[32] + (r2 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ r3 = pred[48] + (r3 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+ *curL = r0;
+ *(curL += pitch) = r1;
+ *(curL += pitch) = r2;
+ curL[pitch] = r3;
+ curL -= (pitch << 1);
+ curL++;
+ pred++;
+ coef++;
+ }
+ }
+ else // do DC-only inverse
+ {
+ m0 = coef[0] + 32;
+
+ for (j = 4; j > 0; j--)
+ {
+ r0 = pred[0] + (m0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ r1 = pred[16] + (m0 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ r2 = pred[32] + (m0 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ r3 = pred[48] + (m0 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+ *curL = r0;
+ *(curL += pitch) = r1;
+ *(curL += pitch) = r2;
+ curL[pitch] = r3;
+ curL -= (pitch << 1);
+ curL++;
+ pred++;
+ }
+ coef += 4;
+ }
+
+ run += 16; // follow coding order
+ level += 16;
+ curL += offset_cur[b4&1];
+ pred += offset_pred[b4&1];
+ coef += offset_pred[b4&1];
+ }
+
+ curL += offset_cur[2 + (b8&1)];
+ pred += offset_pred[2 + (b8&1)];
+ coef += offset_pred[2 + (b8&1)];
+ }
+
+ return ;
+}
+
+
+void dct_chroma(AVCEncObject *encvid, uint8 *curC, uint8 *orgC, int cr)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCMacroblock *currMB = video->currMB;
+ int org_pitch = (encvid->currInput->pitch) >> 1;
+ int pitch = (video->currPic->pitch) >> 1;
+ int pred_pitch = 16;
+ int16 *coef = video->block + 256;
+ uint8 *pred = video->pred_block;
+ int j, blk_x, blk_y, k, idx, b4;
+ int r0, r1, r2, r3, m0;
+ int Qq, Rq, qp_const, q_bits, quant;
+ int *level, *run, zero_run, ncoeff;
+ int data, lev;
+ int offset_cur[2], offset_pred[2], offset_coef[2];
+ uint8 nz_temp[4];
+ int coeff_cost;
+
+ if (cr)
+ {
+ coef += 8;
+ pred += 8;
+ }
+
+ if (currMB->mb_intra == 0) // inter mode
+ {
+ pred = curC;
+ pred_pitch = pitch;
+ }
+
+ /* do 4x4 transform */
+ /* horizontal */
+ for (j = 8; j > 0; j--)
+ {
+ for (blk_x = 2; blk_x > 0; blk_x--)
+ {
+ /* calculate the residue first */
+ r0 = *orgC++ - *pred++;
+ r1 = *orgC++ - *pred++;
+ r2 = *orgC++ - *pred++;
+ r3 = *orgC++ - *pred++;
+
+ r0 += r3; //ptr[0] + ptr[3];
+ r3 = r0 - (r3 << 1); //ptr[0] - ptr[3];
+ r1 += r2; //ptr[1] + ptr[2];
+ r2 = r1 - (r2 << 1); //ptr[1] - ptr[2];
+
+ *coef++ = r0 + r1;
+ *coef++ = (r3 << 1) + r2;
+ *coef++ = r0 - r1;
+ *coef++ = r3 - (r2 << 1);
+
+ }
+ coef += 8; // coef pitch is 16
+ pred += (pred_pitch - 8); // pred_pitch is 16
+ orgC += (org_pitch - 8);
+ }
+ pred -= (pred_pitch << 3);
+ coef -= 128;
+ /* vertical */
+ for (blk_y = 2; blk_y > 0; blk_y--)
+ {
+ for (j = 8; j > 0; j--)
+ {
+ r0 = coef[0] + coef[48];
+ r3 = coef[0] - coef[48];
+ r1 = coef[16] + coef[32];
+ r2 = coef[16] - coef[32];
+
+ coef[0] = r0 + r1;
+ coef[32] = r0 - r1;
+ coef[16] = (r3 << 1) + r2;
+ coef[48] = r3 - (r2 << 1);
+
+ coef++;
+ }
+ coef += 56;
+ }
+ /* then perform DC transform */
+ coef -= 128;
+
+ /* 2x2 transform of DC components*/
+ r0 = coef[0];
+ r1 = coef[4];
+ r2 = coef[64];
+ r3 = coef[68];
+
+ coef[0] = r0 + r1 + r2 + r3;
+ coef[4] = r0 - r1 + r2 - r3;
+ coef[64] = r0 + r1 - r2 - r3;
+ coef[68] = r0 - r1 - r2 + r3;
+
+ Qq = video->QPc_div_6;
+ Rq = video->QPc_mod_6;
+ quant = quant_coef[Rq][0];
+ q_bits = 15 + Qq;
+ qp_const = encvid->qp_const_c;
+
+ zero_run = 0;
+ ncoeff = 0;
+ run = encvid->runcdc + (cr << 2);
+ level = encvid->levelcdc + (cr << 2);
+
+ /* in zigzag scan order */
+ for (k = 0; k < 4; k++)
+ {
+ idx = ((k >> 1) << 6) + ((k & 1) << 2);
+ data = coef[idx];
+ if (data > 0)
+ {
+ lev = data * quant + (qp_const << 1);
+ }
+ else
+ {
+ lev = -data * quant + (qp_const << 1);
+ }
+ lev >>= (q_bits + 1);
+ if (lev)
+ {
+ if (data > 0)
+ {
+ level[ncoeff] = lev;
+ coef[idx] = lev;
+ }
+ else
+ {
+ level[ncoeff] = -lev;
+ coef[idx] = -lev;
+ }
+ run[ncoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ coef[idx] = 0;
+ }
+ }
+
+ encvid->numcoefcdc[cr] = ncoeff;
+
+ if (ncoeff)
+ {
+ currMB->CBP |= (1 << 4); // DC present
+ // do inverse transform
+ quant = dequant_coefres[Rq][0];
+
+ r0 = coef[0] + coef[4];
+ r1 = coef[0] - coef[4];
+ r2 = coef[64] + coef[68];
+ r3 = coef[64] - coef[68];
+
+ r0 += r2;
+ r2 = r0 - (r2 << 1);
+ r1 += r3;
+ r3 = r1 - (r3 << 1);
+
+ if (Qq >= 1)
+ {
+ Qq -= 1;
+ coef[0] = (r0 * quant) << Qq;
+ coef[4] = (r1 * quant) << Qq;
+ coef[64] = (r2 * quant) << Qq;
+ coef[68] = (r3 * quant) << Qq;
+ Qq++;
+ }
+ else
+ {
+ coef[0] = (r0 * quant) >> 1;
+ coef[4] = (r1 * quant) >> 1;
+ coef[64] = (r2 * quant) >> 1;
+ coef[68] = (r3 * quant) >> 1;
+ }
+ }
+
+ /* now do AC zigzag scan, quant, iquant and itrans */
+ if (cr)
+ {
+ run = encvid->run[20];
+ level = encvid->level[20];
+ }
+ else
+ {
+ run = encvid->run[16];
+ level = encvid->level[16];
+ }
+
+ /* offset btw 4x4 block */
+ offset_cur[0] = 0;
+ offset_cur[1] = (pitch << 2) - 8;
+ offset_pred[0] = 0;
+ offset_pred[1] = (pred_pitch << 2) - 8;
+ offset_coef[0] = 0;
+ offset_coef[1] = 56;
+
+ coeff_cost = 0;
+
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ zero_run = 0;
+ ncoeff = 0;
+ for (k = 1; k < 16; k++) /* in zigzag scan order */
+ {
+ idx = ZZ_SCAN_BLOCK[k]; /* map back to raster scan order */
+ data = coef[idx];
+ quant = quant_coef[Rq][k];
+ if (data > 0)
+ {
+ lev = data * quant + qp_const;
+ }
+ else
+ {
+ lev = -data * quant + qp_const;
+ }
+ lev >>= q_bits;
+ if (lev)
+ {
+ /* for RD performance*/
+ if (lev > 1)
+ coeff_cost += MAX_VALUE; // set high cost, shall not be discarded
+ else
+ coeff_cost += COEFF_COST[DISABLE_THRESHOLDING][zero_run];
+
+ /* dequant */
+ quant = dequant_coefres[Rq][k];
+ if (data > 0)
+ {
+ level[ncoeff] = lev;
+ coef[idx] = (lev * quant) << Qq;
+ }
+ else
+ {
+ level[ncoeff] = -lev;
+ coef[idx] = (-lev * quant) << Qq;
+ }
+ run[ncoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ coef[idx] = 0;
+ }
+ }
+
+ nz_temp[b4] = ncoeff; // raster scan
+
+ // just advance the pointers for now, do IDCT later
+ coef += 4;
+ run += 16;
+ level += 16;
+ coef += offset_coef[b4&1];
+ }
+
+ /* rewind the pointers */
+ coef -= 128;
+
+ if (coeff_cost < _CHROMA_COEFF_COST_)
+ {
+ /* if it's not efficient to encode any blocks.
+ Just do DC only */
+ /* We can reset level and run also, but setting nz to zero should be enough. */
+ currMB->nz_coeff[16+(cr<<1)] = 0;
+ currMB->nz_coeff[17+(cr<<1)] = 0;
+ currMB->nz_coeff[20+(cr<<1)] = 0;
+ currMB->nz_coeff[21+(cr<<1)] = 0;
+
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ // do DC-only inverse
+ m0 = coef[0] + 32;
+
+ for (j = 4; j > 0; j--)
+ {
+ r0 = pred[0] + (m0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ r1 = *(pred += pred_pitch) + (m0 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ r2 = pred[pred_pitch] + (m0 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ r3 = pred[pred_pitch<<1] + (m0 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+ *curC = r0;
+ *(curC += pitch) = r1;
+ *(curC += pitch) = r2;
+ curC[pitch] = r3;
+ curC -= (pitch << 1);
+ curC++;
+ pred += (1 - pred_pitch);
+ }
+ coef += 4;
+ curC += offset_cur[b4&1];
+ pred += offset_pred[b4&1];
+ coef += offset_coef[b4&1];
+ }
+ }
+ else // not dropping anything, continue with the IDCT
+ {
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ ncoeff = nz_temp[b4] ; // in raster scan
+ currMB->nz_coeff[16+(b4&1)+(cr<<1)+((b4>>1)<<2)] = ncoeff; // in raster scan
+
+ if (ncoeff) // do a check on the nonzero-coeff
+ {
+ currMB->CBP |= (2 << 4);
+
+ // do inverse transform here
+ for (j = 4; j > 0; j--)
+ {
+ r0 = coef[0] + coef[2];
+ r1 = coef[0] - coef[2];
+ r2 = (coef[1] >> 1) - coef[3];
+ r3 = coef[1] + (coef[3] >> 1);
+
+ coef[0] = r0 + r3;
+ coef[1] = r1 + r2;
+ coef[2] = r1 - r2;
+ coef[3] = r0 - r3;
+
+ coef += 16;
+ }
+ coef -= 64;
+ for (j = 4; j > 0; j--)
+ {
+ r0 = coef[0] + coef[32];
+ r1 = coef[0] - coef[32];
+ r2 = (coef[16] >> 1) - coef[48];
+ r3 = coef[16] + (coef[48] >> 1);
+
+ r0 += r3;
+ r3 = (r0 - (r3 << 1)); /* r0-r3 */
+ r1 += r2;
+ r2 = (r1 - (r2 << 1)); /* r1-r2 */
+ r0 += 32;
+ r1 += 32;
+ r2 += 32;
+ r3 += 32;
+ r0 = pred[0] + (r0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ r1 = *(pred += pred_pitch) + (r1 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ r2 = pred[pred_pitch] + (r2 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ r3 = pred[pred_pitch<<1] + (r3 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+ *curC = r0;
+ *(curC += pitch) = r1;
+ *(curC += pitch) = r2;
+ curC[pitch] = r3;
+ curC -= (pitch << 1);
+ curC++;
+ pred += (1 - pred_pitch);
+ coef++;
+ }
+ }
+ else
+ {
+ // do DC-only inverse
+ m0 = coef[0] + 32;
+
+ for (j = 4; j > 0; j--)
+ {
+ r0 = pred[0] + (m0 >> 6);
+ if ((uint)r0 > 0xFF) r0 = 0xFF & (~(r0 >> 31)); /* clip */
+ r1 = *(pred += pred_pitch) + (m0 >> 6);
+ if ((uint)r1 > 0xFF) r1 = 0xFF & (~(r1 >> 31)); /* clip */
+ r2 = pred[pred_pitch] + (m0 >> 6);
+ if ((uint)r2 > 0xFF) r2 = 0xFF & (~(r2 >> 31)); /* clip */
+ r3 = pred[pred_pitch<<1] + (m0 >> 6);
+ if ((uint)r3 > 0xFF) r3 = 0xFF & (~(r3 >> 31)); /* clip */
+ *curC = r0;
+ *(curC += pitch) = r1;
+ *(curC += pitch) = r2;
+ curC[pitch] = r3;
+ curC -= (pitch << 1);
+ curC++;
+ pred += (1 - pred_pitch);
+ }
+ coef += 4;
+ }
+ curC += offset_cur[b4&1];
+ pred += offset_pred[b4&1];
+ coef += offset_coef[b4&1];
+ }
+ }
+
+ return ;
+}
+
+
+/* only DC transform */
+int TransQuantIntra16DC(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ int16 *block = video->block;
+ int *level = encvid->leveldc;
+ int *run = encvid->rundc;
+ int16 *ptr = block;
+ int r0, r1, r2, r3, j;
+ int Qq = video->QPy_div_6;
+ int Rq = video->QPy_mod_6;
+ int q_bits, qp_const, quant;
+ int data, lev, zero_run;
+ int k, ncoeff, idx;
+
+ /* DC transform */
+ /* horizontal */
+ j = 4;
+ while (j)
+ {
+ r0 = ptr[0] + ptr[12];
+ r3 = ptr[0] - ptr[12];
+ r1 = ptr[4] + ptr[8];
+ r2 = ptr[4] - ptr[8];
+
+ ptr[0] = r0 + r1;
+ ptr[8] = r0 - r1;
+ ptr[4] = r3 + r2;
+ ptr[12] = r3 - r2;
+ ptr += 64;
+ j--;
+ }
+ /* vertical */
+ ptr = block;
+ j = 4;
+ while (j)
+ {
+ r0 = ptr[0] + ptr[192];
+ r3 = ptr[0] - ptr[192];
+ r1 = ptr[64] + ptr[128];
+ r2 = ptr[64] - ptr[128];
+
+ ptr[0] = (r0 + r1) >> 1;
+ ptr[128] = (r0 - r1) >> 1;
+ ptr[64] = (r3 + r2) >> 1;
+ ptr[192] = (r3 - r2) >> 1;
+ ptr += 4;
+ j--;
+ }
+
+ quant = quant_coef[Rq][0];
+ q_bits = 15 + Qq;
+ qp_const = (1 << q_bits) / 3; // intra
+
+ zero_run = 0;
+ ncoeff = 0;
+
+ for (k = 0; k < 16; k++) /* in zigzag scan order */
+ {
+ idx = ZIGZAG2RASTERDC[k];
+ data = block[idx];
+ if (data > 0)
+ {
+ lev = data * quant + (qp_const << 1);
+ }
+ else
+ {
+ lev = -data * quant + (qp_const << 1);
+ }
+ lev >>= (q_bits + 1);
+ if (lev)
+ {
+ if (data > 0)
+ {
+ level[ncoeff] = lev;
+ block[idx] = lev;
+ }
+ else
+ {
+ level[ncoeff] = -lev;
+ block[idx] = -lev;
+ }
+ run[ncoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ block[idx] = 0;
+ }
+ }
+ return ncoeff;
+}
+
+int TransQuantChromaDC(AVCEncObject *encvid, int16 *block, int slice_type, int cr)
+{
+ AVCCommonObj *video = encvid->common;
+ int *level, *run;
+ int r0, r1, r2, r3;
+ int Qq, Rq, q_bits, qp_const, quant;
+ int data, lev, zero_run;
+ int k, ncoeff, idx;
+
+ level = encvid->levelcdc + (cr << 2); /* cb or cr */
+ run = encvid->runcdc + (cr << 2);
+
+ /* 2x2 transform of DC components*/
+ r0 = block[0];
+ r1 = block[4];
+ r2 = block[64];
+ r3 = block[68];
+
+ block[0] = r0 + r1 + r2 + r3;
+ block[4] = r0 - r1 + r2 - r3;
+ block[64] = r0 + r1 - r2 - r3;
+ block[68] = r0 - r1 - r2 + r3;
+
+ Qq = video->QPc_div_6;
+ Rq = video->QPc_mod_6;
+ quant = quant_coef[Rq][0];
+ q_bits = 15 + Qq;
+ if (slice_type == AVC_I_SLICE)
+ {
+ qp_const = (1 << q_bits) / 3;
+ }
+ else
+ {
+ qp_const = (1 << q_bits) / 6;
+ }
+
+ zero_run = 0;
+ ncoeff = 0;
+
+ for (k = 0; k < 4; k++) /* in zigzag scan order */
+ {
+ idx = ((k >> 1) << 6) + ((k & 1) << 2);
+ data = block[idx];
+ if (data > 0)
+ {
+ lev = data * quant + (qp_const << 1);
+ }
+ else
+ {
+ lev = -data * quant + (qp_const << 1);
+ }
+ lev >>= (q_bits + 1);
+ if (lev)
+ {
+ if (data > 0)
+ {
+ level[ncoeff] = lev;
+ block[idx] = lev;
+ }
+ else
+ {
+ level[ncoeff] = -lev;
+ block[idx] = -lev;
+ }
+ run[ncoeff++] = zero_run;
+ zero_run = 0;
+ }
+ else
+ {
+ zero_run++;
+ block[idx] = 0;
+ }
+ }
+ return ncoeff;
+}
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
new file mode 100644
index 0000000..38a2a15
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/findhalfpel.cpp
@@ -0,0 +1,622 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+/* 3/29/01 fast half-pel search based on neighboring guess */
+/* value ranging from 0 to 4, high complexity (more accurate) to
+ low complexity (less accurate) */
+#define HP_DISTANCE_TH 5 // 2 /* half-pel distance threshold */
+
+#define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/
+
+const static int distance_tab[9][9] = /* [hp_guess][k] */
+{
+ {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ {1, 0, 1, 2, 3, 4, 3, 2, 1},
+ {1, 0, 0, 0, 1, 2, 3, 2, 1},
+ {1, 2, 1, 0, 1, 2, 3, 4, 3},
+ {1, 2, 1, 0, 0, 0, 1, 2, 3},
+ {1, 4, 3, 2, 1, 0, 1, 2, 3},
+ {1, 2, 3, 2, 1, 0, 0, 0, 1},
+ {1, 2, 3, 4, 3, 2, 1, 0, 1},
+ {1, 0, 1, 2, 3, 2, 1, 0, 0}
+};
+
+#define CLIP_RESULT(x) if((uint)x > 0xFF){ \
+ x = 0xFF & (~(x>>31));}
+
+#define CLIP_UPPER16(x) if((uint)x >= 0x20000000){ \
+ x = 0xFF0000 & (~(x>>31));} \
+ else { \
+ x = (x>>5)&0xFF0000; \
+ }
+
+/*=====================================================================
+ Function: AVCFindHalfPelMB
+ Date: 10/31/2007
+ Purpose: Find half pel resolution MV surrounding the full-pel MV
+=====================================================================*/
+
+int AVCFindHalfPelMB(AVCEncObject *encvid, uint8 *cur, AVCMV *mot, uint8 *ncand,
+ int xpos, int ypos, int hp_guess, int cmvx, int cmvy)
+{
+ AVCPictureData *currPic = encvid->common->currPic;
+ int lx = currPic->pitch;
+ int d, dmin, satd_min;
+ uint8* cand;
+ int lambda_motion = encvid->lambda_motion;
+ uint8 *mvbits = encvid->mvbits;
+ int mvcost;
+ /* list of candidate to go through for half-pel search*/
+ uint8 *subpel_pred = (uint8*) encvid->subpel_pred; // all 16 sub-pel positions
+ uint8 **hpel_cand = (uint8**) encvid->hpel_cand; /* half-pel position */
+
+ int xh[9] = {0, 0, 2, 2, 2, 0, -2, -2, -2};
+ int yh[9] = {0, -2, -2, 0, 2, 2, 2, 0, -2};
+ int xq[8] = {0, 1, 1, 1, 0, -1, -1, -1};
+ int yq[8] = { -1, -1, 0, 1, 1, 1, 0, -1};
+ int h, hmin, q, qmin;
+
+ OSCL_UNUSED_ARG(xpos);
+ OSCL_UNUSED_ARG(ypos);
+ OSCL_UNUSED_ARG(hp_guess);
+
+ GenerateHalfPelPred(subpel_pred, ncand, lx);
+
+ cur = encvid->currYMB; // pre-load current original MB
+
+ cand = hpel_cand[0];
+
+ // find cost for the current full-pel position
+ dmin = SATD_MB(cand, cur, 65535); // get Hadamaard transform SAD
+ mvcost = MV_COST_S(lambda_motion, mot->x, mot->y, cmvx, cmvy);
+ satd_min = dmin;
+ dmin += mvcost;
+ hmin = 0;
+
+ /* find half-pel */
+ for (h = 1; h < 9; h++)
+ {
+ d = SATD_MB(hpel_cand[h], cur, dmin);
+ mvcost = MV_COST_S(lambda_motion, mot->x + xh[h], mot->y + yh[h], cmvx, cmvy);
+ d += mvcost;
+
+ if (d < dmin)
+ {
+ dmin = d;
+ hmin = h;
+ satd_min = d - mvcost;
+ }
+ }
+
+ mot->sad = dmin;
+ mot->x += xh[hmin];
+ mot->y += yh[hmin];
+ encvid->best_hpel_pos = hmin;
+
+ /*** search for quarter-pel ****/
+ GenerateQuartPelPred(encvid->bilin_base[hmin], &(encvid->qpel_cand[0][0]), hmin);
+
+ encvid->best_qpel_pos = qmin = -1;
+
+ for (q = 0; q < 8; q++)
+ {
+ d = SATD_MB(encvid->qpel_cand[q], cur, dmin);
+ mvcost = MV_COST_S(lambda_motion, mot->x + xq[q], mot->y + yq[q], cmvx, cmvy);
+ d += mvcost;
+ if (d < dmin)
+ {
+ dmin = d;
+ qmin = q;
+ satd_min = d - mvcost;
+ }
+ }
+
+ if (qmin != -1)
+ {
+ mot->sad = dmin;
+ mot->x += xq[qmin];
+ mot->y += yq[qmin];
+ encvid->best_qpel_pos = qmin;
+ }
+
+ return satd_min;
+}
+
+
+
+/** This function generates sub-pel prediction around the full-pel candidate.
+Each sub-pel position array is 20 pixel wide (for word-alignment) and 17 pixel tall. */
+/** The sub-pel position is labeled in spiral manner from the center. */
+
+void GenerateHalfPelPred(uint8* subpel_pred, uint8 *ncand, int lx)
+{
+ /* let's do straightforward way first */
+ uint8 *ref;
+ uint8 *dst;
+ uint8 tmp8;
+ int32 tmp32;
+ int16 tmp_horz[18*22], *dst_16, *src_16;
+ register int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; // temp register
+ int msk;
+ int i, j;
+
+ /* first copy full-pel to the first array */
+ /* to be optimized later based on byte-offset load */
+ ref = ncand - 3 - lx - (lx << 1); /* move back (-3,-3) */
+ dst = subpel_pred;
+
+ dst -= 4; /* offset */
+ for (j = 0; j < 22; j++) /* 24x22 */
+ {
+ i = 6;
+ while (i > 0)
+ {
+ tmp32 = *ref++;
+ tmp8 = *ref++;
+ tmp32 |= (tmp8 << 8);
+ tmp8 = *ref++;
+ tmp32 |= (tmp8 << 16);
+ tmp8 = *ref++;
+ tmp32 |= (tmp8 << 24);
+ *((uint32*)(dst += 4)) = tmp32;
+ i--;
+ }
+ ref += (lx - 24);
+ }
+
+ /* from the first array, we do horizontal interp */
+ ref = subpel_pred + 2;
+ dst_16 = tmp_horz; /* 17 x 22 */
+
+ for (j = 4; j > 0; j--)
+ {
+ for (i = 16; i > 0; i -= 4)
+ {
+ a = ref[-2];
+ b = ref[-1];
+ c = ref[0];
+ d = ref[1];
+ e = ref[2];
+ f = ref[3];
+ *dst_16++ = a + f - 5 * (b + e) + 20 * (c + d);
+ a = ref[4];
+ *dst_16++ = b + a - 5 * (c + f) + 20 * (d + e);
+ b = ref[5];
+ *dst_16++ = c + b - 5 * (d + a) + 20 * (e + f);
+ c = ref[6];
+ *dst_16++ = d + c - 5 * (e + b) + 20 * (f + a);
+
+ ref += 4;
+ }
+ /* do the 17th column here */
+ d = ref[3];
+ *dst_16 = e + d - 5 * (f + c) + 20 * (a + b);
+ dst_16 += 2; /* stride for tmp_horz is 18 */
+ ref += 8; /* stride for ref is 24 */
+ if (j == 3) // move 18 lines down
+ {
+ dst_16 += 324;//18*18;
+ ref += 432;//18*24;
+ }
+ }
+
+ ref -= 480;//20*24;
+ dst_16 -= 360;//20*18;
+ dst = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE; /* go to the 14th array 17x18*/
+
+ for (j = 18; j > 0; j--)
+ {
+ for (i = 16; i > 0; i -= 4)
+ {
+ a = ref[-2];
+ b = ref[-1];
+ c = ref[0];
+ d = ref[1];
+ e = ref[2];
+ f = ref[3];
+ tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+ *dst_16++ = tmp32;
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *dst++ = tmp32;
+
+ a = ref[4];
+ tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+ *dst_16++ = tmp32;
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *dst++ = tmp32;
+
+ b = ref[5];
+ tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+ *dst_16++ = tmp32;
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *dst++ = tmp32;
+
+ c = ref[6];
+ tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+ *dst_16++ = tmp32;
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *dst++ = tmp32;
+
+ ref += 4;
+ }
+ /* do the 17th column here */
+ d = ref[3];
+ tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+ *dst_16 = tmp32;
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *dst = tmp32;
+
+ dst += 8; /* stride for dst is 24 */
+ dst_16 += 2; /* stride for tmp_horz is 18 */
+ ref += 8; /* stride for ref is 24 */
+ }
+
+
+ /* Do middle point filtering*/
+ src_16 = tmp_horz; /* 17 x 22 */
+ dst = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE; /* 12th array 17x17*/
+ dst -= 24; // offset
+ for (i = 0; i < 17; i++)
+ {
+ for (j = 16; j > 0; j -= 4)
+ {
+ a = *src_16;
+ b = *(src_16 += 18);
+ c = *(src_16 += 18);
+ d = *(src_16 += 18);
+ e = *(src_16 += 18);
+ f = *(src_16 += 18);
+
+ tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+ tmp32 = (tmp32 + 512) >> 10;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32;
+
+ a = *(src_16 += 18);
+ tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+ tmp32 = (tmp32 + 512) >> 10;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32;
+
+ b = *(src_16 += 18);
+ tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+ tmp32 = (tmp32 + 512) >> 10;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32;
+
+ c = *(src_16 += 18);
+ tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+ tmp32 = (tmp32 + 512) >> 10;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32;
+
+ src_16 -= (18 << 2);
+ }
+
+ d = src_16[90]; // 18*5
+ tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+ tmp32 = (tmp32 + 512) >> 10;
+ CLIP_RESULT(tmp32)
+ dst[24] = tmp32;
+
+ src_16 -= ((18 << 4) - 1);
+ dst -= ((24 << 4) - 1);
+ }
+
+ /* do vertical interpolation */
+ ref = subpel_pred + 2;
+ dst = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE; /* 10th array 18x17 */
+ dst -= 24; // offset
+
+ for (i = 2; i > 0; i--)
+ {
+ for (j = 16; j > 0; j -= 4)
+ {
+ a = *ref;
+ b = *(ref += 24);
+ c = *(ref += 24);
+ d = *(ref += 24);
+ e = *(ref += 24);
+ f = *(ref += 24);
+
+ tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ a = *(ref += 24);
+ tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ b = *(ref += 24);
+ tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ c = *(ref += 24);
+ tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ ref -= (24 << 2);
+ }
+
+ d = ref[120]; // 24*5
+ tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ dst[24] = tmp32; // 10th
+
+ dst -= ((24 << 4) - 1);
+ ref -= ((24 << 4) - 1);
+ }
+
+ // note that using SIMD here doesn't help much, the cycle almost stays the same
+ // one can just use the above code and change the for(i=2 to for(i=18
+ for (i = 16; i > 0; i -= 4)
+ {
+ msk = 0;
+ for (j = 17; j > 0; j--)
+ {
+ a = *((uint32*)ref); /* load 4 bytes */
+ b = (a >> 8) & 0xFF00FF; /* second and fourth byte */
+ a &= 0xFF00FF;
+
+ c = *((uint32*)(ref + 120));
+ d = (c >> 8) & 0xFF00FF;
+ c &= 0xFF00FF;
+
+ a += c;
+ b += d;
+
+ e = *((uint32*)(ref + 72)); /* e, f */
+ f = (e >> 8) & 0xFF00FF;
+ e &= 0xFF00FF;
+
+ c = *((uint32*)(ref + 48)); /* c, d */
+ d = (c >> 8) & 0xFF00FF;
+ c &= 0xFF00FF;
+
+ c += e;
+ d += f;
+
+ a += 20 * c;
+ b += 20 * d;
+ a += 0x100010;
+ b += 0x100010;
+
+ e = *((uint32*)(ref += 24)); /* e, f */
+ f = (e >> 8) & 0xFF00FF;
+ e &= 0xFF00FF;
+
+ c = *((uint32*)(ref + 72)); /* c, d */
+ d = (c >> 8) & 0xFF00FF;
+ c &= 0xFF00FF;
+
+ c += e;
+ d += f;
+
+ a -= 5 * c;
+ b -= 5 * d;
+
+ c = a << 16;
+ d = b << 16;
+ CLIP_UPPER16(a)
+ CLIP_UPPER16(c)
+ CLIP_UPPER16(b)
+ CLIP_UPPER16(d)
+
+ a |= (c >> 16);
+ b |= (d >> 16);
+ // a>>=5;
+ // b>>=5;
+ /* clip */
+ // msk |= b; msk|=a;
+ // a &= 0xFF00FF;
+ // b &= 0xFF00FF;
+ a |= (b << 8); /* pack it back */
+
+ *((uint16*)(dst += 24)) = a & 0xFFFF; //dst is not word-aligned.
+ *((uint16*)(dst + 2)) = a >> 16;
+
+ }
+ dst -= 404; // 24*17-4
+ ref -= 404;
+ /* if(msk & 0xFF00FF00) // need clipping
+ {
+ VertInterpWClip(dst,ref); // re-do 4 column with clip
+ }*/
+ }
+
+ return ;
+}
+
+void VertInterpWClip(uint8 *dst, uint8 *ref)
+{
+ int i, j;
+ int a, b, c, d, e, f;
+ int32 tmp32;
+
+ dst -= 4;
+ ref -= 4;
+
+ for (i = 4; i > 0; i--)
+ {
+ for (j = 16; j > 0; j -= 4)
+ {
+ a = *ref;
+ b = *(ref += 24);
+ c = *(ref += 24);
+ d = *(ref += 24);
+ e = *(ref += 24);
+ f = *(ref += 24);
+
+ tmp32 = a + f - 5 * (b + e) + 20 * (c + d);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ a = *(ref += 24);
+ tmp32 = b + a - 5 * (c + f) + 20 * (d + e);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ b = *(ref += 24);
+ tmp32 = c + b - 5 * (d + a) + 20 * (e + f);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ c = *(ref += 24);
+ tmp32 = d + c - 5 * (e + b) + 20 * (f + a);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ *(dst += 24) = tmp32; // 10th
+
+ ref -= (24 << 2);
+ }
+
+ d = ref[120]; // 24*5
+ tmp32 = e + d - 5 * (f + c) + 20 * (a + b);
+ tmp32 = (tmp32 + 16) >> 5;
+ CLIP_RESULT(tmp32)
+ dst[24] = tmp32; // 10th
+
+ dst -= ((24 << 4) - 1);
+ ref -= ((24 << 4) - 1);
+ }
+
+ return ;
+}
+
+
+void GenerateQuartPelPred(uint8 **bilin_base, uint8 *qpel_cand, int hpel_pos)
+{
+ // for even value of hpel_pos, start with pattern 1, otherwise, start with pattern 2
+ int i, j;
+
+ uint8 *c1 = qpel_cand;
+ uint8 *tl = bilin_base[0];
+ uint8 *tr = bilin_base[1];
+ uint8 *bl = bilin_base[2];
+ uint8 *br = bilin_base[3];
+ int a, b, c, d;
+ int offset = 1 - (384 * 7);
+
+ if (!(hpel_pos&1)) // diamond pattern
+ {
+ j = 16;
+ while (j--)
+ {
+ i = 16;
+ while (i--)
+ {
+ d = tr[24];
+ a = *tr++;
+ b = bl[1];
+ c = *br++;
+
+ *c1 = (c + a + 1) >> 1;
+ *(c1 += 384) = (b + a + 1) >> 1; /* c2 */
+ *(c1 += 384) = (b + c + 1) >> 1; /* c3 */
+ *(c1 += 384) = (b + d + 1) >> 1; /* c4 */
+
+ b = *bl++;
+
+ *(c1 += 384) = (c + d + 1) >> 1; /* c5 */
+ *(c1 += 384) = (b + d + 1) >> 1; /* c6 */
+ *(c1 += 384) = (b + c + 1) >> 1; /* c7 */
+ *(c1 += 384) = (b + a + 1) >> 1; /* c8 */
+
+ c1 += offset;
+ }
+ // advance to the next line, pitch is 24
+ tl += 8;
+ tr += 8;
+ bl += 8;
+ br += 8;
+ c1 += 8;
+ }
+ }
+ else // star pattern
+ {
+ j = 16;
+ while (j--)
+ {
+ i = 16;
+ while (i--)
+ {
+ a = *br++;
+ b = *tr++;
+ c = tl[1];
+ *c1 = (a + b + 1) >> 1;
+ b = bl[1];
+ *(c1 += 384) = (a + c + 1) >> 1; /* c2 */
+ c = tl[25];
+ *(c1 += 384) = (a + b + 1) >> 1; /* c3 */
+ b = tr[23];
+ *(c1 += 384) = (a + c + 1) >> 1; /* c4 */
+ c = tl[24];
+ *(c1 += 384) = (a + b + 1) >> 1; /* c5 */
+ b = *bl++;
+ *(c1 += 384) = (a + c + 1) >> 1; /* c6 */
+ c = *tl++;
+ *(c1 += 384) = (a + b + 1) >> 1; /* c7 */
+ *(c1 += 384) = (a + c + 1) >> 1; /* c8 */
+
+ c1 += offset;
+ }
+ // advance to the next line, pitch is 24
+ tl += 8;
+ tr += 8;
+ bl += 8;
+ br += 8;
+ c1 += 8;
+ }
+ }
+
+ return ;
+}
+
+
+/* assuming cand always has a pitch of 24 */
+int SATD_MB(uint8 *cand, uint8 *cur, int dmin)
+{
+ int cost;
+
+
+ dmin = (dmin << 16) | 24;
+ cost = AVCSAD_Macroblock_C(cand, cur, dmin, NULL);
+
+ return cost;
+}
+
+
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/header.cpp b/media/libstagefright/codecs/avc/enc/src/header.cpp
new file mode 100644
index 0000000..9acff9e
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/header.cpp
@@ -0,0 +1,917 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "avcenc_api.h"
+
+/** see subclause 7.4.2.1 */
+/* no need for checking the valid range , already done in SetEncodeParam(),
+if we have to send another SPS, the ranges should be verified first before
+users call PVAVCEncodeSPS() */
+AVCEnc_Status EncodeSPS(AVCEncObject *encvid, AVCEncBitstream *stream)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCSeqParamSet *seqParam = video->currSeqParams;
+ AVCVUIParams *vui = &(seqParam->vui_parameters);
+ int i;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+
+ //DEBUG_LOG(userData,AVC_LOGTYPE_INFO,"EncodeSPS",-1,-1);
+
+ status = BitstreamWriteBits(stream, 8, seqParam->profile_idc);
+ status = BitstreamWrite1Bit(stream, seqParam->constrained_set0_flag);
+ status = BitstreamWrite1Bit(stream, seqParam->constrained_set1_flag);
+ status = BitstreamWrite1Bit(stream, seqParam->constrained_set2_flag);
+ status = BitstreamWrite1Bit(stream, seqParam->constrained_set3_flag);
+ status = BitstreamWriteBits(stream, 4, 0); /* forbidden zero bits */
+ if (status != AVCENC_SUCCESS) /* we can check after each write also */
+ {
+ return status;
+ }
+
+ status = BitstreamWriteBits(stream, 8, seqParam->level_idc);
+ status = ue_v(stream, seqParam->seq_parameter_set_id);
+ status = ue_v(stream, seqParam->log2_max_frame_num_minus4);
+ status = ue_v(stream, seqParam->pic_order_cnt_type);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ if (seqParam->pic_order_cnt_type == 0)
+ {
+ status = ue_v(stream, seqParam->log2_max_pic_order_cnt_lsb_minus4);
+ }
+ else if (seqParam->pic_order_cnt_type == 1)
+ {
+ status = BitstreamWrite1Bit(stream, seqParam->delta_pic_order_always_zero_flag);
+ status = se_v(stream, seqParam->offset_for_non_ref_pic); /* upto 32 bits */
+ status = se_v(stream, seqParam->offset_for_top_to_bottom_field); /* upto 32 bits */
+ status = ue_v(stream, seqParam->num_ref_frames_in_pic_order_cnt_cycle);
+
+ for (i = 0; i < (int)(seqParam->num_ref_frames_in_pic_order_cnt_cycle); i++)
+ {
+ status = se_v(stream, seqParam->offset_for_ref_frame[i]); /* upto 32 bits */
+ }
+ }
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = ue_v(stream, seqParam->num_ref_frames);
+ status = BitstreamWrite1Bit(stream, seqParam->gaps_in_frame_num_value_allowed_flag);
+ status = ue_v(stream, seqParam->pic_width_in_mbs_minus1);
+ status = ue_v(stream, seqParam->pic_height_in_map_units_minus1);
+ status = BitstreamWrite1Bit(stream, seqParam->frame_mbs_only_flag);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ /* if frame_mbs_only_flag is 0, then write, mb_adaptive_frame_field_frame here */
+
+ status = BitstreamWrite1Bit(stream, seqParam->direct_8x8_inference_flag);
+ status = BitstreamWrite1Bit(stream, seqParam->frame_cropping_flag);
+ if (seqParam->frame_cropping_flag)
+ {
+ status = ue_v(stream, seqParam->frame_crop_left_offset);
+ status = ue_v(stream, seqParam->frame_crop_right_offset);
+ status = ue_v(stream, seqParam->frame_crop_top_offset);
+ status = ue_v(stream, seqParam->frame_crop_bottom_offset);
+ }
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = BitstreamWrite1Bit(stream, seqParam->vui_parameters_present_flag);
+ if (seqParam->vui_parameters_present_flag)
+ {
+ /* not supported */
+ //return AVCENC_SPS_FAIL;
+ EncodeVUI(stream, vui);
+ }
+
+ return status;
+}
+
+
+void EncodeVUI(AVCEncBitstream* stream, AVCVUIParams* vui)
+{
+ int temp;
+
+ temp = vui->aspect_ratio_info_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ BitstreamWriteBits(stream, 8, vui->aspect_ratio_idc);
+ if (vui->aspect_ratio_idc == 255)
+ {
+ BitstreamWriteBits(stream, 16, vui->sar_width);
+ BitstreamWriteBits(stream, 16, vui->sar_height);
+ }
+ }
+ temp = vui->overscan_info_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ BitstreamWrite1Bit(stream, vui->overscan_appropriate_flag);
+ }
+ temp = vui->video_signal_type_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ BitstreamWriteBits(stream, 3, vui->video_format);
+ BitstreamWrite1Bit(stream, vui->video_full_range_flag);
+ temp = vui->colour_description_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ BitstreamWriteBits(stream, 8, vui->colour_primaries);
+ BitstreamWriteBits(stream, 8, vui->transfer_characteristics);
+ BitstreamWriteBits(stream, 8, vui->matrix_coefficients);
+ }
+ }
+ temp = vui->chroma_location_info_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ ue_v(stream, vui->chroma_sample_loc_type_top_field);
+ ue_v(stream, vui->chroma_sample_loc_type_bottom_field);
+ }
+
+ temp = vui->timing_info_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ BitstreamWriteBits(stream, 32, vui->num_units_in_tick);
+ BitstreamWriteBits(stream, 32, vui->time_scale);
+ BitstreamWrite1Bit(stream, vui->fixed_frame_rate_flag);
+ }
+
+ temp = vui->nal_hrd_parameters_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ EncodeHRD(stream, &(vui->nal_hrd_parameters));
+ }
+ temp = vui->vcl_hrd_parameters_present_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ EncodeHRD(stream, &(vui->vcl_hrd_parameters));
+ }
+ if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag)
+ {
+ BitstreamWrite1Bit(stream, vui->low_delay_hrd_flag);
+ }
+ BitstreamWrite1Bit(stream, vui->pic_struct_present_flag);
+ temp = vui->bitstream_restriction_flag;
+ BitstreamWrite1Bit(stream, temp);
+ if (temp)
+ {
+ BitstreamWrite1Bit(stream, vui->motion_vectors_over_pic_boundaries_flag);
+ ue_v(stream, vui->max_bytes_per_pic_denom);
+ ue_v(stream, vui->max_bits_per_mb_denom);
+ ue_v(stream, vui->log2_max_mv_length_horizontal);
+ ue_v(stream, vui->log2_max_mv_length_vertical);
+ ue_v(stream, vui->max_dec_frame_reordering);
+ ue_v(stream, vui->max_dec_frame_buffering);
+ }
+
+ return ;
+}
+
+
+void EncodeHRD(AVCEncBitstream* stream, AVCHRDParams* hrd)
+{
+ int i;
+
+ ue_v(stream, hrd->cpb_cnt_minus1);
+ BitstreamWriteBits(stream, 4, hrd->bit_rate_scale);
+ BitstreamWriteBits(stream, 4, hrd->cpb_size_scale);
+ for (i = 0; i <= (int)hrd->cpb_cnt_minus1; i++)
+ {
+ ue_v(stream, hrd->bit_rate_value_minus1[i]);
+ ue_v(stream, hrd->cpb_size_value_minus1[i]);
+ ue_v(stream, hrd->cbr_flag[i]);
+ }
+ BitstreamWriteBits(stream, 5, hrd->initial_cpb_removal_delay_length_minus1);
+ BitstreamWriteBits(stream, 5, hrd->cpb_removal_delay_length_minus1);
+ BitstreamWriteBits(stream, 5, hrd->dpb_output_delay_length_minus1);
+ BitstreamWriteBits(stream, 5, hrd->time_offset_length);
+
+ return ;
+}
+
+
+
+/** see subclause 7.4.2.2 */
+/* no need for checking the valid range , already done in SetEncodeParam().
+If we have to send another SPS, the ranges should be verified first before
+users call PVAVCEncodeSPS()*/
+AVCEnc_Status EncodePPS(AVCEncObject *encvid, AVCEncBitstream *stream)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ AVCPicParamSet *picParam = video->currPicParams;
+ int i, iGroup, numBits;
+ uint temp;
+
+ status = ue_v(stream, picParam->pic_parameter_set_id);
+ status = ue_v(stream, picParam->seq_parameter_set_id);
+ status = BitstreamWrite1Bit(stream, picParam->entropy_coding_mode_flag);
+ status = BitstreamWrite1Bit(stream, picParam->pic_order_present_flag);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = ue_v(stream, picParam->num_slice_groups_minus1);
+ if (picParam->num_slice_groups_minus1 > 0)
+ {
+ status = ue_v(stream, picParam->slice_group_map_type);
+ if (picParam->slice_group_map_type == 0)
+ {
+ for (iGroup = 0; iGroup <= (int)picParam->num_slice_groups_minus1; iGroup++)
+ {
+ status = ue_v(stream, picParam->run_length_minus1[iGroup]);
+ }
+ }
+ else if (picParam->slice_group_map_type == 2)
+ {
+ for (iGroup = 0; iGroup < (int)picParam->num_slice_groups_minus1; iGroup++)
+ {
+ status = ue_v(stream, picParam->top_left[iGroup]);
+ status = ue_v(stream, picParam->bottom_right[iGroup]);
+ }
+ }
+ else if (picParam->slice_group_map_type == 3 ||
+ picParam->slice_group_map_type == 4 ||
+ picParam->slice_group_map_type == 5)
+ {
+ status = BitstreamWrite1Bit(stream, picParam->slice_group_change_direction_flag);
+ status = ue_v(stream, picParam->slice_group_change_rate_minus1);
+ }
+ else /*if(picParam->slice_group_map_type == 6)*/
+ {
+ status = ue_v(stream, picParam->pic_size_in_map_units_minus1);
+
+ numBits = 0;/* ceil(log2(num_slice_groups_minus1+1)) bits */
+ i = picParam->num_slice_groups_minus1;
+ while (i > 0)
+ {
+ numBits++;
+ i >>= 1;
+ }
+
+ for (i = 0; i <= (int)picParam->pic_size_in_map_units_minus1; i++)
+ {
+ status = BitstreamWriteBits(stream, numBits, picParam->slice_group_id[i]);
+ }
+ }
+ }
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = ue_v(stream, picParam->num_ref_idx_l0_active_minus1);
+ status = ue_v(stream, picParam->num_ref_idx_l1_active_minus1);
+ status = BitstreamWrite1Bit(stream, picParam->weighted_pred_flag);
+ status = BitstreamWriteBits(stream, 2, picParam->weighted_bipred_idc);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = se_v(stream, picParam->pic_init_qp_minus26);
+ status = se_v(stream, picParam->pic_init_qs_minus26);
+ status = se_v(stream, picParam->chroma_qp_index_offset);
+
+ temp = picParam->deblocking_filter_control_present_flag << 2;
+ temp |= (picParam->constrained_intra_pred_flag << 1);
+ temp |= picParam->redundant_pic_cnt_present_flag;
+
+ status = BitstreamWriteBits(stream, 3, temp);
+
+ return status;
+}
+
+/** see subclause 7.4.3 */
+AVCEnc_Status EncodeSliceHeader(AVCEncObject *encvid, AVCEncBitstream *stream)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCPicParamSet *currPPS = video->currPicParams;
+ AVCSeqParamSet *currSPS = video->currSeqParams;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ int slice_type, temp, i;
+ int num_bits;
+
+ num_bits = (stream->write_pos << 3) - stream->bit_left;
+
+ status = ue_v(stream, sliceHdr->first_mb_in_slice);
+
+ slice_type = video->slice_type;
+
+ if (video->mbNum == 0) /* first mb in frame */
+ {
+ status = ue_v(stream, sliceHdr->slice_type);
+ }
+ else
+ {
+ status = ue_v(stream, slice_type);
+ }
+
+ status = ue_v(stream, sliceHdr->pic_parameter_set_id);
+
+ status = BitstreamWriteBits(stream, currSPS->log2_max_frame_num_minus4 + 4, sliceHdr->frame_num);
+
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ /* if frame_mbs_only_flag is 0, encode field_pic_flag, bottom_field_flag here */
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ status = ue_v(stream, sliceHdr->idr_pic_id);
+ }
+
+ if (currSPS->pic_order_cnt_type == 0)
+ {
+ status = BitstreamWriteBits(stream, currSPS->log2_max_pic_order_cnt_lsb_minus4 + 4,
+ sliceHdr->pic_order_cnt_lsb);
+
+ if (currPPS->pic_order_present_flag && !sliceHdr->field_pic_flag)
+ {
+ status = se_v(stream, sliceHdr->delta_pic_order_cnt_bottom); /* 32 bits */
+ }
+ }
+ if (currSPS->pic_order_cnt_type == 1 && !currSPS->delta_pic_order_always_zero_flag)
+ {
+ status = se_v(stream, sliceHdr->delta_pic_order_cnt[0]); /* 32 bits */
+ if (currPPS->pic_order_present_flag && !sliceHdr->field_pic_flag)
+ {
+ status = se_v(stream, sliceHdr->delta_pic_order_cnt[1]); /* 32 bits */
+ }
+ }
+
+ if (currPPS->redundant_pic_cnt_present_flag)
+ {
+ status = ue_v(stream, sliceHdr->redundant_pic_cnt);
+ }
+
+ if (slice_type == AVC_B_SLICE)
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->direct_spatial_mv_pred_flag);
+ }
+
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ if (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE || slice_type == AVC_B_SLICE)
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->num_ref_idx_active_override_flag);
+ if (sliceHdr->num_ref_idx_active_override_flag)
+ {
+ /* we shouldn't enter this part at all */
+ status = ue_v(stream, sliceHdr->num_ref_idx_l0_active_minus1);
+ if (slice_type == AVC_B_SLICE)
+ {
+ status = ue_v(stream, sliceHdr->num_ref_idx_l1_active_minus1);
+ }
+ }
+ }
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ /* ref_pic_list_reordering() */
+ status = ref_pic_list_reordering(video, stream, sliceHdr, slice_type);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ if ((currPPS->weighted_pred_flag && (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE)) ||
+ (currPPS->weighted_bipred_idc == 1 && slice_type == AVC_B_SLICE))
+ {
+ // pred_weight_table(); // not supported !!
+ return AVCENC_PRED_WEIGHT_TAB_FAIL;
+ }
+
+ if (video->nal_ref_idc != 0)
+ {
+ status = dec_ref_pic_marking(video, stream, sliceHdr);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ if (currPPS->entropy_coding_mode_flag && slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
+ {
+ return AVCENC_CABAC_FAIL;
+ /* ue_v(stream,&(sliceHdr->cabac_init_idc));
+ if(sliceHdr->cabac_init_idc > 2){
+ // not supported !!!!
+ }*/
+ }
+
+ status = se_v(stream, sliceHdr->slice_qp_delta);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ if (slice_type == AVC_SP_SLICE || slice_type == AVC_SI_SLICE)
+ {
+ if (slice_type == AVC_SP_SLICE)
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->sp_for_switch_flag);
+ /* if sp_for_switch_flag is 0, P macroblocks in SP slice is decoded using
+ SP decoding process for non-switching pictures in 8.6.1 */
+ /* else, P macroblocks in SP slice is decoded using SP and SI decoding
+ process for switching picture in 8.6.2 */
+ }
+ status = se_v(stream, sliceHdr->slice_qs_delta);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ if (currPPS->deblocking_filter_control_present_flag)
+ {
+
+ status = ue_v(stream, sliceHdr->disable_deblocking_filter_idc);
+
+ if (sliceHdr->disable_deblocking_filter_idc != 1)
+ {
+ status = se_v(stream, sliceHdr->slice_alpha_c0_offset_div2);
+
+ status = se_v(stream, sliceHdr->slice_beta_offset_div_2);
+ }
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ if (currPPS->num_slice_groups_minus1 > 0 && currPPS->slice_group_map_type >= 3
+ && currPPS->slice_group_map_type <= 5)
+ {
+ /* Ceil(Log2(PicSizeInMapUnits/(float)SliceGroupChangeRate + 1)) */
+ temp = video->PicSizeInMapUnits / video->SliceGroupChangeRate;
+ if (video->PicSizeInMapUnits % video->SliceGroupChangeRate)
+ {
+ temp++;
+ }
+ i = 0;
+ while (temp > 1)
+ {
+ temp >>= 1;
+ i++;
+ }
+
+ BitstreamWriteBits(stream, i, sliceHdr->slice_group_change_cycle);
+ }
+
+
+ encvid->rateCtrl->NumberofHeaderBits += (stream->write_pos << 3) - stream->bit_left - num_bits;
+
+ return AVCENC_SUCCESS;
+}
+
+/** see subclause 7.4.3.1 */
+AVCEnc_Status ref_pic_list_reordering(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr, int slice_type)
+{
+ (void)(video);
+ int i;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+
+ if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->ref_pic_list_reordering_flag_l0);
+ if (sliceHdr->ref_pic_list_reordering_flag_l0)
+ {
+ i = 0;
+ do
+ {
+ status = ue_v(stream, sliceHdr->reordering_of_pic_nums_idc_l0[i]);
+ if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 ||
+ sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1)
+ {
+ status = ue_v(stream, sliceHdr->abs_diff_pic_num_minus1_l0[i]);
+ /* this check should be in InitSlice(), if we ever use it */
+ /*if(sliceHdr->reordering_of_pic_nums_idc_l0[i] == 0 &&
+ sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum/2 -1)
+ {
+ return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+ }
+ if(sliceHdr->reordering_of_pic_nums_idc_l0[i] == 1 &&
+ sliceHdr->abs_diff_pic_num_minus1_l0[i] > video->MaxPicNum/2 -2)
+ {
+ return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+ }*/
+ }
+ else if (sliceHdr->reordering_of_pic_nums_idc_l0[i] == 2)
+ {
+ status = ue_v(stream, sliceHdr->long_term_pic_num_l0[i]);
+ }
+ i++;
+ }
+ while (sliceHdr->reordering_of_pic_nums_idc_l0[i] != 3
+ && i <= (int)sliceHdr->num_ref_idx_l0_active_minus1 + 1) ;
+ }
+ }
+ if (slice_type == AVC_B_SLICE)
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->ref_pic_list_reordering_flag_l1);
+ if (sliceHdr->ref_pic_list_reordering_flag_l1)
+ {
+ i = 0;
+ do
+ {
+ status = ue_v(stream, sliceHdr->reordering_of_pic_nums_idc_l1[i]);
+ if (sliceHdr->reordering_of_pic_nums_idc_l1[i] == 0 ||
+ sliceHdr->reordering_of_pic_nums_idc_l1[i] == 1)
+ {
+ status = ue_v(stream, sliceHdr->abs_diff_pic_num_minus1_l1[i]);
+ /* This check should be in InitSlice() if we ever use it
+ if(sliceHdr->reordering_of_pic_nums_idc_l1[i] == 0 &&
+ sliceHdr->abs_diff_pic_num_minus1_l1[i] > video->MaxPicNum/2 -1)
+ {
+ return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+ }
+ if(sliceHdr->reordering_of_pic_nums_idc_l1[i] == 1 &&
+ sliceHdr->abs_diff_pic_num_minus1_l1[i] > video->MaxPicNum/2 -2)
+ {
+ return AVCENC_REF_PIC_REORDER_FAIL; // out of range
+ }*/
+ }
+ else if (sliceHdr->reordering_of_pic_nums_idc_l1[i] == 2)
+ {
+ status = ue_v(stream, sliceHdr->long_term_pic_num_l1[i]);
+ }
+ i++;
+ }
+ while (sliceHdr->reordering_of_pic_nums_idc_l1[i] != 3
+ && i <= (int)sliceHdr->num_ref_idx_l1_active_minus1 + 1) ;
+ }
+ }
+
+ return status;
+}
+
+/** see subclause 7.4.3.3 */
+AVCEnc_Status dec_ref_pic_marking(AVCCommonObj *video, AVCEncBitstream *stream, AVCSliceHeader *sliceHdr)
+{
+ int i;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->no_output_of_prior_pics_flag);
+ status = BitstreamWrite1Bit(stream, sliceHdr->long_term_reference_flag);
+ if (sliceHdr->long_term_reference_flag == 0) /* used for short-term */
+ {
+ video->MaxLongTermFrameIdx = -1; /* no long-term frame indx */
+ }
+ else /* used for long-term */
+ {
+ video->MaxLongTermFrameIdx = 0;
+ video->LongTermFrameIdx = 0;
+ }
+ }
+ else
+ {
+ status = BitstreamWrite1Bit(stream, sliceHdr->adaptive_ref_pic_marking_mode_flag); /* default to zero */
+ if (sliceHdr->adaptive_ref_pic_marking_mode_flag)
+ {
+ i = 0;
+ do
+ {
+ status = ue_v(stream, sliceHdr->memory_management_control_operation[i]);
+ if (sliceHdr->memory_management_control_operation[i] == 1 ||
+ sliceHdr->memory_management_control_operation[i] == 3)
+ {
+ status = ue_v(stream, sliceHdr->difference_of_pic_nums_minus1[i]);
+ }
+ if (sliceHdr->memory_management_control_operation[i] == 2)
+ {
+ status = ue_v(stream, sliceHdr->long_term_pic_num[i]);
+ }
+ if (sliceHdr->memory_management_control_operation[i] == 3 ||
+ sliceHdr->memory_management_control_operation[i] == 6)
+ {
+ status = ue_v(stream, sliceHdr->long_term_frame_idx[i]);
+ }
+ if (sliceHdr->memory_management_control_operation[i] == 4)
+ {
+ status = ue_v(stream, sliceHdr->max_long_term_frame_idx_plus1[i]);
+ }
+ i++;
+ }
+ while (sliceHdr->memory_management_control_operation[i] != 0 && i < MAX_DEC_REF_PIC_MARKING);
+ if (i >= MAX_DEC_REF_PIC_MARKING && sliceHdr->memory_management_control_operation[i] != 0)
+ {
+ return AVCENC_DEC_REF_PIC_MARK_FAIL; /* we're screwed!!, not enough memory */
+ }
+ }
+ }
+
+ return status;
+}
+
+/* see subclause 8.2.1 Decoding process for picture order count.
+See also PostPOC() for initialization of some variables. */
+AVCEnc_Status InitPOC(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCSeqParamSet *currSPS = video->currSeqParams;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCFrameIO *currInput = encvid->currInput;
+ int i;
+
+ switch (currSPS->pic_order_cnt_type)
+ {
+ case 0: /* POC MODE 0 , subclause 8.2.1.1 */
+ /* encoding part */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ encvid->dispOrdPOCRef = currInput->disp_order;
+ }
+ while (currInput->disp_order < encvid->dispOrdPOCRef)
+ {
+ encvid->dispOrdPOCRef -= video->MaxPicOrderCntLsb;
+ }
+ sliceHdr->pic_order_cnt_lsb = currInput->disp_order - encvid->dispOrdPOCRef;
+ while (sliceHdr->pic_order_cnt_lsb >= video->MaxPicOrderCntLsb)
+ {
+ sliceHdr->pic_order_cnt_lsb -= video->MaxPicOrderCntLsb;
+ }
+ /* decoding part */
+ /* Calculate the MSBs of current picture */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->prevPicOrderCntMsb = 0;
+ video->prevPicOrderCntLsb = 0;
+ }
+ if (sliceHdr->pic_order_cnt_lsb < video->prevPicOrderCntLsb &&
+ (video->prevPicOrderCntLsb - sliceHdr->pic_order_cnt_lsb) >= (video->MaxPicOrderCntLsb / 2))
+ video->PicOrderCntMsb = video->prevPicOrderCntMsb + video->MaxPicOrderCntLsb;
+ else if (sliceHdr->pic_order_cnt_lsb > video->prevPicOrderCntLsb &&
+ (sliceHdr->pic_order_cnt_lsb - video->prevPicOrderCntLsb) > (video->MaxPicOrderCntLsb / 2))
+ video->PicOrderCntMsb = video->prevPicOrderCntMsb - video->MaxPicOrderCntLsb;
+ else
+ video->PicOrderCntMsb = video->prevPicOrderCntMsb;
+
+ /* JVT-I010 page 81 is different from JM7.3 */
+ if (!sliceHdr->field_pic_flag || !sliceHdr->bottom_field_flag)
+ {
+ video->PicOrderCnt = video->TopFieldOrderCnt = video->PicOrderCntMsb + sliceHdr->pic_order_cnt_lsb;
+ }
+
+ if (!sliceHdr->field_pic_flag)
+ {
+ video->BottomFieldOrderCnt = video->TopFieldOrderCnt + sliceHdr->delta_pic_order_cnt_bottom;
+ }
+ else if (sliceHdr->bottom_field_flag)
+ {
+ video->PicOrderCnt = video->BottomFieldOrderCnt = video->PicOrderCntMsb + sliceHdr->pic_order_cnt_lsb;
+ }
+
+ if (!sliceHdr->field_pic_flag)
+ {
+ video->PicOrderCnt = AVC_MIN(video->TopFieldOrderCnt, video->BottomFieldOrderCnt);
+ }
+
+ if (video->currPicParams->pic_order_present_flag && !sliceHdr->field_pic_flag)
+ {
+ sliceHdr->delta_pic_order_cnt_bottom = 0; /* defaulted to zero */
+ }
+
+ break;
+ case 1: /* POC MODE 1, subclause 8.2.1.2 */
+ /* calculate FrameNumOffset */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ encvid->dispOrdPOCRef = currInput->disp_order; /* reset the reference point */
+ video->prevFrameNumOffset = 0;
+ video->FrameNumOffset = 0;
+ }
+ else if (video->prevFrameNum > sliceHdr->frame_num)
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
+ }
+ else
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset;
+ }
+ /* calculate absFrameNum */
+ if (currSPS->num_ref_frames_in_pic_order_cnt_cycle)
+ {
+ video->absFrameNum = video->FrameNumOffset + sliceHdr->frame_num;
+ }
+ else
+ {
+ video->absFrameNum = 0;
+ }
+
+ if (video->absFrameNum > 0 && video->nal_ref_idc == 0)
+ {
+ video->absFrameNum--;
+ }
+
+ /* derive picOrderCntCycleCnt and frameNumInPicOrderCntCycle */
+ if (video->absFrameNum > 0)
+ {
+ video->picOrderCntCycleCnt = (video->absFrameNum - 1) / currSPS->num_ref_frames_in_pic_order_cnt_cycle;
+ video->frameNumInPicOrderCntCycle = (video->absFrameNum - 1) % currSPS->num_ref_frames_in_pic_order_cnt_cycle;
+ }
+ /* derive expectedDeltaPerPicOrderCntCycle, this value can be computed up front. */
+ video->expectedDeltaPerPicOrderCntCycle = 0;
+ for (i = 0; i < (int)currSPS->num_ref_frames_in_pic_order_cnt_cycle; i++)
+ {
+ video->expectedDeltaPerPicOrderCntCycle += currSPS->offset_for_ref_frame[i];
+ }
+ /* derive expectedPicOrderCnt */
+ if (video->absFrameNum)
+ {
+ video->expectedPicOrderCnt = video->picOrderCntCycleCnt * video->expectedDeltaPerPicOrderCntCycle;
+ for (i = 0; i <= video->frameNumInPicOrderCntCycle; i++)
+ {
+ video->expectedPicOrderCnt += currSPS->offset_for_ref_frame[i];
+ }
+ }
+ else
+ {
+ video->expectedPicOrderCnt = 0;
+ }
+
+ if (video->nal_ref_idc == 0)
+ {
+ video->expectedPicOrderCnt += currSPS->offset_for_non_ref_pic;
+ }
+ /* derive TopFieldOrderCnt and BottomFieldOrderCnt */
+ /* encoding part */
+ if (!currSPS->delta_pic_order_always_zero_flag)
+ {
+ sliceHdr->delta_pic_order_cnt[0] = currInput->disp_order - encvid->dispOrdPOCRef - video->expectedPicOrderCnt;
+
+ if (video->currPicParams->pic_order_present_flag && !sliceHdr->field_pic_flag)
+ {
+ sliceHdr->delta_pic_order_cnt[1] = sliceHdr->delta_pic_order_cnt[0]; /* should be calculated from currInput->bottom_field->disp_order */
+ }
+ else
+ {
+ sliceHdr->delta_pic_order_cnt[1] = 0;
+ }
+ }
+ else
+ {
+ sliceHdr->delta_pic_order_cnt[0] = sliceHdr->delta_pic_order_cnt[1] = 0;
+ }
+
+ if (sliceHdr->field_pic_flag == 0)
+ {
+ video->TopFieldOrderCnt = video->expectedPicOrderCnt + sliceHdr->delta_pic_order_cnt[0];
+ video->BottomFieldOrderCnt = video->TopFieldOrderCnt + currSPS->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[1];
+
+ video->PicOrderCnt = AVC_MIN(video->TopFieldOrderCnt, video->BottomFieldOrderCnt);
+ }
+ else if (sliceHdr->bottom_field_flag == 0)
+ {
+ video->TopFieldOrderCnt = video->expectedPicOrderCnt + sliceHdr->delta_pic_order_cnt[0];
+ video->PicOrderCnt = video->TopFieldOrderCnt;
+ }
+ else
+ {
+ video->BottomFieldOrderCnt = video->expectedPicOrderCnt + currSPS->offset_for_top_to_bottom_field + sliceHdr->delta_pic_order_cnt[0];
+ video->PicOrderCnt = video->BottomFieldOrderCnt;
+ }
+ break;
+
+
+ case 2: /* POC MODE 2, subclause 8.2.1.3 */
+ /* decoding order must be the same as display order */
+ /* we don't check for that. The decoder will just output in decoding order. */
+ /* Check for 2 consecutive non-reference frame */
+ if (video->nal_ref_idc == 0)
+ {
+ if (encvid->dispOrdPOCRef == 1)
+ {
+ return AVCENC_CONSECUTIVE_NONREF;
+ }
+ encvid->dispOrdPOCRef = 1; /* act as a flag for non ref */
+ }
+ else
+ {
+ encvid->dispOrdPOCRef = 0;
+ }
+
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->FrameNumOffset = 0;
+ }
+ else if (video->prevFrameNum > sliceHdr->frame_num)
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset + video->MaxFrameNum;
+ }
+ else
+ {
+ video->FrameNumOffset = video->prevFrameNumOffset;
+ }
+ /* derive tempPicOrderCnt, we just use PicOrderCnt */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->PicOrderCnt = 0;
+ }
+ else if (video->nal_ref_idc == 0)
+ {
+ video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num) - 1;
+ }
+ else
+ {
+ video->PicOrderCnt = 2 * (video->FrameNumOffset + sliceHdr->frame_num);
+ }
+ /* derive TopFieldOrderCnt and BottomFieldOrderCnt */
+ if (sliceHdr->field_pic_flag == 0)
+ {
+ video->TopFieldOrderCnt = video->BottomFieldOrderCnt = video->PicOrderCnt;
+ }
+ else if (sliceHdr->bottom_field_flag)
+ {
+ video->BottomFieldOrderCnt = video->PicOrderCnt;
+ }
+ else
+ {
+ video->TopFieldOrderCnt = video->PicOrderCnt;
+ }
+ break;
+ default:
+ return AVCENC_POC_FAIL;
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+/** see subclause 8.2.1 */
+AVCEnc_Status PostPOC(AVCCommonObj *video)
+{
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCSeqParamSet *currSPS = video->currSeqParams;
+
+ video->prevFrameNum = sliceHdr->frame_num;
+
+ switch (currSPS->pic_order_cnt_type)
+ {
+ case 0: /* subclause 8.2.1.1 */
+ if (video->mem_mgr_ctrl_eq_5)
+ {
+ video->prevPicOrderCntMsb = 0;
+ video->prevPicOrderCntLsb = video->TopFieldOrderCnt;
+ }
+ else
+ {
+ video->prevPicOrderCntMsb = video->PicOrderCntMsb;
+ video->prevPicOrderCntLsb = sliceHdr->pic_order_cnt_lsb;
+ }
+ break;
+ case 1: /* subclause 8.2.1.2 and 8.2.1.3 */
+ case 2:
+ if (video->mem_mgr_ctrl_eq_5)
+ {
+ video->prevFrameNumOffset = 0;
+ }
+ else
+ {
+ video->prevFrameNumOffset = video->FrameNumOffset;
+ }
+ break;
+ }
+
+ return AVCENC_SUCCESS;
+}
+
diff --git a/media/libstagefright/codecs/avc/enc/src/init.cpp b/media/libstagefright/codecs/avc/enc/src/init.cpp
new file mode 100644
index 0000000..c258b57
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/init.cpp
@@ -0,0 +1,899 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "avcenc_api.h"
+
+#define LOG2_MAX_FRAME_NUM_MINUS4 12 /* 12 default */
+#define SLICE_GROUP_CHANGE_CYCLE 1 /* default */
+
+/* initialized variables to be used in SPS*/
+AVCEnc_Status SetEncodeParam(AVCHandle* avcHandle, AVCEncParams* encParam,
+ void* extSPS, void* extPPS)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+ AVCCommonObj *video = encvid->common;
+ AVCSeqParamSet *seqParam = video->currSeqParams;
+ AVCPicParamSet *picParam = video->currPicParams;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ AVCEnc_Status status;
+ void *userData = avcHandle->userData;
+ int ii, maxFrameNum;
+
+ AVCSeqParamSet* extS = NULL;
+ AVCPicParamSet* extP = NULL;
+
+ if (extSPS) extS = (AVCSeqParamSet*) extSPS;
+ if (extPPS) extP = (AVCPicParamSet*) extPPS;
+
+ /* This part sets the default values of the encoding options this
+ library supports in seqParam, picParam and sliceHdr structures and
+ also copy the values from the encParam into the above 3 structures.
+
+ Some parameters will be assigned later when we encode SPS or PPS such as
+ the seq_parameter_id or pic_parameter_id. Also some of the slice parameters
+ have to be re-assigned per slice basis such as frame_num, slice_type,
+ first_mb_in_slice, pic_order_cnt_lsb, slice_qp_delta, slice_group_change_cycle */
+
+ /* profile_idc, constrained_setx_flag and level_idc is set by VerifyProfile(),
+ and VerifyLevel() functions later. */
+
+ encvid->fullsearch_enable = encParam->fullsearch;
+
+ encvid->outOfBandParamSet = ((encParam->out_of_band_param_set == AVC_ON) ? TRUE : FALSE);
+
+ /* parameters derived from the the encParam that are used in SPS */
+ if (extS)
+ {
+ video->MaxPicOrderCntLsb = 1 << (extS->log2_max_pic_order_cnt_lsb_minus4 + 4);
+ video->PicWidthInMbs = extS->pic_width_in_mbs_minus1 + 1;
+ video->PicHeightInMapUnits = extS->pic_height_in_map_units_minus1 + 1 ;
+ video->FrameHeightInMbs = (2 - extS->frame_mbs_only_flag) * video->PicHeightInMapUnits ;
+ }
+ else
+ {
+ video->MaxPicOrderCntLsb = 1 << (encParam->log2_max_poc_lsb_minus_4 + 4);
+ video->PicWidthInMbs = (encParam->width + 15) >> 4; /* round it to multiple of 16 */
+ video->FrameHeightInMbs = (encParam->height + 15) >> 4; /* round it to multiple of 16 */
+ video->PicHeightInMapUnits = video->FrameHeightInMbs;
+ }
+
+ video->PicWidthInSamplesL = video->PicWidthInMbs * 16 ;
+ if (video->PicWidthInSamplesL + 32 > 0xFFFF)
+ {
+ return AVCENC_NOT_SUPPORTED; // we use 2-bytes for pitch
+ }
+
+ video->PicWidthInSamplesC = video->PicWidthInMbs * 8 ;
+ video->PicHeightInMbs = video->FrameHeightInMbs;
+ video->PicSizeInMapUnits = video->PicWidthInMbs * video->PicHeightInMapUnits ;
+ video->PicHeightInSamplesL = video->PicHeightInMbs * 16;
+ video->PicHeightInSamplesC = video->PicHeightInMbs * 8;
+ video->PicSizeInMbs = video->PicWidthInMbs * video->PicHeightInMbs;
+
+ if (!extS && !extP)
+ {
+ maxFrameNum = (encParam->idr_period == -1) ? (1 << 16) : encParam->idr_period;
+ ii = 0;
+ while (maxFrameNum > 0)
+ {
+ ii++;
+ maxFrameNum >>= 1;
+ }
+ if (ii < 4) ii = 4;
+ else if (ii > 16) ii = 16;
+
+ seqParam->log2_max_frame_num_minus4 = ii - 4;//LOG2_MAX_FRAME_NUM_MINUS4; /* default */
+
+ video->MaxFrameNum = 1 << ii; //(LOG2_MAX_FRAME_NUM_MINUS4 + 4); /* default */
+ video->MaxPicNum = video->MaxFrameNum;
+
+ /************* set the SPS *******************/
+ seqParam->seq_parameter_set_id = 0; /* start with zero */
+ /* POC */
+ seqParam->pic_order_cnt_type = encParam->poc_type; /* POC type */
+ if (encParam->poc_type == 0)
+ {
+ if (/*encParam->log2_max_poc_lsb_minus_4<0 || (no need, it's unsigned)*/
+ encParam->log2_max_poc_lsb_minus_4 > 12)
+ {
+ return AVCENC_INVALID_POC_LSB;
+ }
+ seqParam->log2_max_pic_order_cnt_lsb_minus4 = encParam->log2_max_poc_lsb_minus_4;
+ }
+ else if (encParam->poc_type == 1)
+ {
+ seqParam->delta_pic_order_always_zero_flag = encParam->delta_poc_zero_flag;
+ seqParam->offset_for_non_ref_pic = encParam->offset_poc_non_ref;
+ seqParam->offset_for_top_to_bottom_field = encParam->offset_top_bottom;
+ seqParam->num_ref_frames_in_pic_order_cnt_cycle = encParam->num_ref_in_cycle;
+ if (encParam->offset_poc_ref == NULL)
+ {
+ return AVCENC_ENCPARAM_MEM_FAIL;
+ }
+ for (ii = 0; ii < encParam->num_ref_frame; ii++)
+ {
+ seqParam->offset_for_ref_frame[ii] = encParam->offset_poc_ref[ii];
+ }
+ }
+ /* number of reference frame */
+ if (encParam->num_ref_frame > 16 || encParam->num_ref_frame < 0)
+ {
+ return AVCENC_INVALID_NUM_REF;
+ }
+ seqParam->num_ref_frames = encParam->num_ref_frame; /* num reference frame range 0...16*/
+ seqParam->gaps_in_frame_num_value_allowed_flag = FALSE;
+ seqParam->pic_width_in_mbs_minus1 = video->PicWidthInMbs - 1;
+ seqParam->pic_height_in_map_units_minus1 = video->PicHeightInMapUnits - 1;
+ seqParam->frame_mbs_only_flag = TRUE;
+ seqParam->mb_adaptive_frame_field_flag = FALSE;
+ seqParam->direct_8x8_inference_flag = FALSE; /* default */
+ seqParam->frame_cropping_flag = FALSE;
+ seqParam->frame_crop_bottom_offset = 0;
+ seqParam->frame_crop_left_offset = 0;
+ seqParam->frame_crop_right_offset = 0;
+ seqParam->frame_crop_top_offset = 0;
+ seqParam->vui_parameters_present_flag = FALSE; /* default */
+ }
+ else if (extS) // use external SPS and PPS
+ {
+ seqParam->seq_parameter_set_id = extS->seq_parameter_set_id;
+ seqParam->log2_max_frame_num_minus4 = extS->log2_max_frame_num_minus4;
+ video->MaxFrameNum = 1 << (extS->log2_max_frame_num_minus4 + 4);
+ video->MaxPicNum = video->MaxFrameNum;
+ if (encParam->idr_period > (int)(video->MaxFrameNum) || (encParam->idr_period == -1))
+ {
+ encParam->idr_period = (int)video->MaxFrameNum;
+ }
+
+ seqParam->pic_order_cnt_type = extS->pic_order_cnt_type;
+ if (seqParam->pic_order_cnt_type == 0)
+ {
+ if (/*extS->log2_max_pic_order_cnt_lsb_minus4<0 || (no need it's unsigned)*/
+ extS->log2_max_pic_order_cnt_lsb_minus4 > 12)
+ {
+ return AVCENC_INVALID_POC_LSB;
+ }
+ seqParam->log2_max_pic_order_cnt_lsb_minus4 = extS->log2_max_pic_order_cnt_lsb_minus4;
+ }
+ else if (seqParam->pic_order_cnt_type == 1)
+ {
+ seqParam->delta_pic_order_always_zero_flag = extS->delta_pic_order_always_zero_flag;
+ seqParam->offset_for_non_ref_pic = extS->offset_for_non_ref_pic;
+ seqParam->offset_for_top_to_bottom_field = extS->offset_for_top_to_bottom_field;
+ seqParam->num_ref_frames_in_pic_order_cnt_cycle = extS->num_ref_frames_in_pic_order_cnt_cycle;
+ if (extS->offset_for_ref_frame == NULL)
+ {
+ return AVCENC_ENCPARAM_MEM_FAIL;
+ }
+ for (ii = 0; ii < (int) extS->num_ref_frames; ii++)
+ {
+ seqParam->offset_for_ref_frame[ii] = extS->offset_for_ref_frame[ii];
+ }
+ }
+ /* number of reference frame */
+ if (extS->num_ref_frames > 16 /*|| extS->num_ref_frames<0 (no need, it's unsigned)*/)
+ {
+ return AVCENC_INVALID_NUM_REF;
+ }
+ seqParam->num_ref_frames = extS->num_ref_frames; /* num reference frame range 0...16*/
+ seqParam->gaps_in_frame_num_value_allowed_flag = extS->gaps_in_frame_num_value_allowed_flag;
+ seqParam->pic_width_in_mbs_minus1 = extS->pic_width_in_mbs_minus1;
+ seqParam->pic_height_in_map_units_minus1 = extS->pic_height_in_map_units_minus1;
+ seqParam->frame_mbs_only_flag = extS->frame_mbs_only_flag;
+ if (extS->frame_mbs_only_flag != TRUE)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+ seqParam->mb_adaptive_frame_field_flag = extS->mb_adaptive_frame_field_flag;
+ if (extS->mb_adaptive_frame_field_flag != FALSE)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ seqParam->direct_8x8_inference_flag = extS->direct_8x8_inference_flag;
+ seqParam->frame_cropping_flag = extS->frame_cropping_flag ;
+ if (extS->frame_cropping_flag != FALSE)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ seqParam->frame_crop_bottom_offset = 0;
+ seqParam->frame_crop_left_offset = 0;
+ seqParam->frame_crop_right_offset = 0;
+ seqParam->frame_crop_top_offset = 0;
+ seqParam->vui_parameters_present_flag = extS->vui_parameters_present_flag;
+ if (extS->vui_parameters_present_flag)
+ {
+ memcpy(&(seqParam->vui_parameters), &(extS->vui_parameters), sizeof(AVCVUIParams));
+ }
+ }
+ else
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ /***************** now PPS ******************************/
+ if (!extP && !extS)
+ {
+ picParam->pic_parameter_set_id = (uint)(-1); /* start with zero */
+ picParam->seq_parameter_set_id = (uint)(-1); /* start with zero */
+ picParam->entropy_coding_mode_flag = 0; /* default to CAVLC */
+ picParam->pic_order_present_flag = 0; /* default for now, will need it for B-slice */
+ /* FMO */
+ if (encParam->num_slice_group < 1 || encParam->num_slice_group > MAX_NUM_SLICE_GROUP)
+ {
+ return AVCENC_INVALID_NUM_SLICEGROUP;
+ }
+ picParam->num_slice_groups_minus1 = encParam->num_slice_group - 1;
+
+ if (picParam->num_slice_groups_minus1 > 0)
+ {
+ picParam->slice_group_map_type = encParam->fmo_type;
+ switch (encParam->fmo_type)
+ {
+ case 0:
+ for (ii = 0; ii <= (int)picParam->num_slice_groups_minus1; ii++)
+ {
+ picParam->run_length_minus1[ii] = encParam->run_length_minus1[ii];
+ }
+ break;
+ case 2:
+ for (ii = 0; ii < (int)picParam->num_slice_groups_minus1; ii++)
+ {
+ picParam->top_left[ii] = encParam->top_left[ii];
+ picParam->bottom_right[ii] = encParam->bottom_right[ii];
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ if (encParam->change_dir_flag == AVC_ON)
+ {
+ picParam->slice_group_change_direction_flag = TRUE;
+ }
+ else
+ {
+ picParam->slice_group_change_direction_flag = FALSE;
+ }
+ if (/*encParam->change_rate_minus1 < 0 || (no need it's unsigned) */
+ encParam->change_rate_minus1 > video->PicSizeInMapUnits - 1)
+ {
+ return AVCENC_INVALID_CHANGE_RATE;
+ }
+ picParam->slice_group_change_rate_minus1 = encParam->change_rate_minus1;
+ video->SliceGroupChangeRate = picParam->slice_group_change_rate_minus1 + 1;
+ break;
+ case 6:
+ picParam->pic_size_in_map_units_minus1 = video->PicSizeInMapUnits - 1;
+
+ /* allocate picParam->slice_group_id */
+ picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits, DEFAULT_ATTR);
+ if (picParam->slice_group_id == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ if (encParam->slice_group == NULL)
+ {
+ return AVCENC_ENCPARAM_MEM_FAIL;
+ }
+ for (ii = 0; ii < (int)video->PicSizeInMapUnits; ii++)
+ {
+ picParam->slice_group_id[ii] = encParam->slice_group[ii];
+ }
+ break;
+ default:
+ return AVCENC_INVALID_FMO_TYPE;
+ }
+ }
+ picParam->num_ref_idx_l0_active_minus1 = encParam->num_ref_frame - 1; /* assume frame only */
+ picParam->num_ref_idx_l1_active_minus1 = 0; /* default value */
+ picParam->weighted_pred_flag = 0; /* no weighted prediction supported */
+ picParam->weighted_bipred_idc = 0; /* range 0,1,2 */
+ if (/*picParam->weighted_bipred_idc < 0 || (no need, it's unsigned) */
+ picParam->weighted_bipred_idc > 2)
+ {
+ return AVCENC_WEIGHTED_BIPRED_FAIL;
+ }
+ picParam->pic_init_qp_minus26 = 0; /* default, will be changed at slice level anyway */
+ if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
+ {
+ return AVCENC_INIT_QP_FAIL; /* out of range */
+ }
+ picParam->pic_init_qs_minus26 = 0;
+ if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
+ {
+ return AVCENC_INIT_QS_FAIL; /* out of range */
+ }
+
+ picParam->chroma_qp_index_offset = 0; /* default to zero for now */
+ if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
+ {
+ return AVCENC_CHROMA_QP_FAIL; /* out of range */
+ }
+ /* deblocking */
+ picParam->deblocking_filter_control_present_flag = (encParam->db_filter == AVC_ON) ? TRUE : FALSE ;
+ /* constrained intra prediction */
+ picParam->constrained_intra_pred_flag = (encParam->constrained_intra_pred == AVC_ON) ? TRUE : FALSE;
+ picParam->redundant_pic_cnt_present_flag = 0; /* default */
+ }
+ else if (extP)// external PPS
+ {
+ picParam->pic_parameter_set_id = extP->pic_parameter_set_id - 1; /* to be increased by one */
+ picParam->seq_parameter_set_id = extP->seq_parameter_set_id;
+ picParam->entropy_coding_mode_flag = extP->entropy_coding_mode_flag;
+ if (extP->entropy_coding_mode_flag != 0) /* default to CAVLC */
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+ picParam->pic_order_present_flag = extP->pic_order_present_flag; /* default for now, will need it for B-slice */
+ if (extP->pic_order_present_flag != 0)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+ /* FMO */
+ if (/*(extP->num_slice_groups_minus1<0) || (no need it's unsigned) */
+ (extP->num_slice_groups_minus1 > MAX_NUM_SLICE_GROUP - 1))
+ {
+ return AVCENC_INVALID_NUM_SLICEGROUP;
+ }
+ picParam->num_slice_groups_minus1 = extP->num_slice_groups_minus1;
+
+ if (picParam->num_slice_groups_minus1 > 0)
+ {
+ picParam->slice_group_map_type = extP->slice_group_map_type;
+ switch (extP->slice_group_map_type)
+ {
+ case 0:
+ for (ii = 0; ii <= (int)extP->num_slice_groups_minus1; ii++)
+ {
+ picParam->run_length_minus1[ii] = extP->run_length_minus1[ii];
+ }
+ break;
+ case 2:
+ for (ii = 0; ii < (int)picParam->num_slice_groups_minus1; ii++)
+ {
+ picParam->top_left[ii] = extP->top_left[ii];
+ picParam->bottom_right[ii] = extP->bottom_right[ii];
+ }
+ break;
+ case 3:
+ case 4:
+ case 5:
+ picParam->slice_group_change_direction_flag = extP->slice_group_change_direction_flag;
+ if (/*extP->slice_group_change_rate_minus1 < 0 || (no need, it's unsigned) */
+ extP->slice_group_change_rate_minus1 > video->PicSizeInMapUnits - 1)
+ {
+ return AVCENC_INVALID_CHANGE_RATE;
+ }
+ picParam->slice_group_change_rate_minus1 = extP->slice_group_change_rate_minus1;
+ video->SliceGroupChangeRate = picParam->slice_group_change_rate_minus1 + 1;
+ break;
+ case 6:
+ if (extP->pic_size_in_map_units_minus1 != video->PicSizeInMapUnits - 1)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ picParam->pic_size_in_map_units_minus1 = extP->pic_size_in_map_units_minus1;
+
+ /* allocate picParam->slice_group_id */
+ picParam->slice_group_id = (uint*)avcHandle->CBAVC_Malloc(userData, sizeof(uint) * video->PicSizeInMapUnits, DEFAULT_ATTR);
+ if (picParam->slice_group_id == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ if (extP->slice_group_id == NULL)
+ {
+ return AVCENC_ENCPARAM_MEM_FAIL;
+ }
+ for (ii = 0; ii < (int)video->PicSizeInMapUnits; ii++)
+ {
+ picParam->slice_group_id[ii] = extP->slice_group_id[ii];
+ }
+ break;
+ default:
+ return AVCENC_INVALID_FMO_TYPE;
+ }
+ }
+ picParam->num_ref_idx_l0_active_minus1 = extP->num_ref_idx_l0_active_minus1;
+ picParam->num_ref_idx_l1_active_minus1 = extP->num_ref_idx_l1_active_minus1; /* default value */
+ if (picParam->num_ref_idx_l1_active_minus1 != 0)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ if (extP->weighted_pred_flag)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ picParam->weighted_pred_flag = 0; /* no weighted prediction supported */
+ picParam->weighted_bipred_idc = extP->weighted_bipred_idc; /* range 0,1,2 */
+ if (/*picParam->weighted_bipred_idc < 0 || (no need, it's unsigned) */
+ picParam->weighted_bipred_idc > 2)
+ {
+ return AVCENC_WEIGHTED_BIPRED_FAIL;
+ }
+ picParam->pic_init_qp_minus26 = extP->pic_init_qp_minus26; /* default, will be changed at slice level anyway */
+ if (picParam->pic_init_qp_minus26 < -26 || picParam->pic_init_qp_minus26 > 25)
+ {
+ return AVCENC_INIT_QP_FAIL; /* out of range */
+ }
+ picParam->pic_init_qs_minus26 = extP->pic_init_qs_minus26;
+ if (picParam->pic_init_qs_minus26 < -26 || picParam->pic_init_qs_minus26 > 25)
+ {
+ return AVCENC_INIT_QS_FAIL; /* out of range */
+ }
+
+ picParam->chroma_qp_index_offset = extP->chroma_qp_index_offset; /* default to zero for now */
+ if (picParam->chroma_qp_index_offset < -12 || picParam->chroma_qp_index_offset > 12)
+ {
+ return AVCENC_CHROMA_QP_FAIL; /* out of range */
+ }
+ /* deblocking */
+ picParam->deblocking_filter_control_present_flag = extP->deblocking_filter_control_present_flag;
+ /* constrained intra prediction */
+ picParam->constrained_intra_pred_flag = extP->constrained_intra_pred_flag;
+ if (extP->redundant_pic_cnt_present_flag != 0)
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+ picParam->redundant_pic_cnt_present_flag = extP->redundant_pic_cnt_present_flag; /* default */
+ }
+ else
+ {
+ return AVCENC_NOT_SUPPORTED;
+ }
+
+ /****************** now set up some SliceHeader parameters ***********/
+ if (picParam->deblocking_filter_control_present_flag == TRUE)
+ {
+ /* these values only present when db_filter is ON */
+ if (encParam->disable_db_idc > 2)
+ {
+ return AVCENC_INVALID_DEBLOCK_IDC; /* out of range */
+ }
+ sliceHdr->disable_deblocking_filter_idc = encParam->disable_db_idc;
+
+ if (encParam->alpha_offset < -6 || encParam->alpha_offset > 6)
+ {
+ return AVCENC_INVALID_ALPHA_OFFSET;
+ }
+ sliceHdr->slice_alpha_c0_offset_div2 = encParam->alpha_offset;
+
+ if (encParam->beta_offset < -6 || encParam->beta_offset > 6)
+ {
+ return AVCENC_INVALID_BETA_OFFSET;
+ }
+ sliceHdr->slice_beta_offset_div_2 = encParam->beta_offset;
+ }
+ if (encvid->outOfBandParamSet == TRUE)
+ {
+ sliceHdr->idr_pic_id = 0;
+ }
+ else
+ {
+ sliceHdr->idr_pic_id = (uint)(-1); /* start with zero */
+ }
+ sliceHdr->field_pic_flag = FALSE;
+ sliceHdr->bottom_field_flag = FALSE; /* won't be used anyway */
+ video->MbaffFrameFlag = (seqParam->mb_adaptive_frame_field_flag && !sliceHdr->field_pic_flag);
+
+ /* the rest will be set in InitSlice() */
+
+ /* now the rate control and performance related parameters */
+ rateCtrl->scdEnable = (encParam->auto_scd == AVC_ON) ? TRUE : FALSE;
+ rateCtrl->idrPeriod = encParam->idr_period + 1;
+ rateCtrl->intraMBRate = encParam->intramb_refresh;
+ rateCtrl->dpEnable = (encParam->data_par == AVC_ON) ? TRUE : FALSE;
+
+ rateCtrl->subPelEnable = (encParam->sub_pel == AVC_ON) ? TRUE : FALSE;
+ rateCtrl->mvRange = encParam->search_range;
+
+ rateCtrl->subMBEnable = (encParam->submb_pred == AVC_ON) ? TRUE : FALSE;
+ rateCtrl->rdOptEnable = (encParam->rdopt_mode == AVC_ON) ? TRUE : FALSE;
+ rateCtrl->bidirPred = (encParam->bidir_pred == AVC_ON) ? TRUE : FALSE;
+
+ rateCtrl->rcEnable = (encParam->rate_control == AVC_ON) ? TRUE : FALSE;
+ rateCtrl->initQP = encParam->initQP;
+ rateCtrl->initQP = AVC_CLIP3(0, 51, rateCtrl->initQP);
+
+ rateCtrl->bitRate = encParam->bitrate;
+ rateCtrl->cpbSize = encParam->CPB_size;
+ rateCtrl->initDelayOffset = (rateCtrl->bitRate * encParam->init_CBP_removal_delay / 1000);
+
+ if (encParam->frame_rate == 0)
+ {
+ return AVCENC_INVALID_FRAMERATE;
+ }
+
+ rateCtrl->frame_rate = (OsclFloat)(encParam->frame_rate * 1.0 / 1000);
+// rateCtrl->srcInterval = encParam->src_interval;
+ rateCtrl->first_frame = 1; /* set this flag for the first time */
+
+ /* contrained_setx_flag will be set inside the VerifyProfile called below.*/
+ if (!extS && !extP)
+ {
+ seqParam->profile_idc = encParam->profile;
+ seqParam->constrained_set0_flag = FALSE;
+ seqParam->constrained_set1_flag = FALSE;
+ seqParam->constrained_set2_flag = FALSE;
+ seqParam->constrained_set3_flag = FALSE;
+ seqParam->level_idc = encParam->level;
+ }
+ else
+ {
+ seqParam->profile_idc = extS->profile_idc;
+ seqParam->constrained_set0_flag = extS->constrained_set0_flag;
+ seqParam->constrained_set1_flag = extS->constrained_set1_flag;
+ seqParam->constrained_set2_flag = extS->constrained_set2_flag;
+ seqParam->constrained_set3_flag = extS->constrained_set3_flag;
+ seqParam->level_idc = extS->level_idc;
+ }
+
+
+ status = VerifyProfile(encvid, seqParam, picParam);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ status = VerifyLevel(encvid, seqParam, picParam);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+/* verify the profile setting */
+AVCEnc_Status VerifyProfile(AVCEncObject *encvid, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam)
+{
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+
+ if (seqParam->profile_idc == 0) /* find profile for this setting */
+ {
+ /* find the right profile for it */
+ if (seqParam->direct_8x8_inference_flag == TRUE &&
+ picParam->entropy_coding_mode_flag == FALSE &&
+ picParam->num_slice_groups_minus1 <= 7 /*&&
+ picParam->num_slice_groups_minus1>=0 (no need, it's unsigned) */)
+ {
+ seqParam->profile_idc = AVC_EXTENDED;
+ seqParam->constrained_set2_flag = TRUE;
+ }
+
+ if (rateCtrl->dpEnable == FALSE &&
+ picParam->num_slice_groups_minus1 == 0 &&
+ picParam->redundant_pic_cnt_present_flag == FALSE)
+ {
+ seqParam->profile_idc = AVC_MAIN;
+ seqParam->constrained_set1_flag = TRUE;
+ }
+
+ if (rateCtrl->bidirPred == FALSE &&
+ rateCtrl->dpEnable == FALSE &&
+ seqParam->frame_mbs_only_flag == TRUE &&
+ picParam->weighted_pred_flag == FALSE &&
+ picParam->weighted_bipred_idc == 0 &&
+ picParam->entropy_coding_mode_flag == FALSE &&
+ picParam->num_slice_groups_minus1 <= 7 /*&&
+ picParam->num_slice_groups_minus1>=0 (no need, it's unsigned)*/)
+ {
+ seqParam->profile_idc = AVC_BASELINE;
+ seqParam->constrained_set0_flag = TRUE;
+ }
+
+ if (seqParam->profile_idc == 0) /* still zero */
+ {
+ return AVCENC_PROFILE_NOT_SUPPORTED;
+ }
+ }
+
+ /* check the list of supported profile by this library */
+ switch (seqParam->profile_idc)
+ {
+ case AVC_BASELINE:
+ if (rateCtrl->bidirPred == TRUE ||
+ rateCtrl->dpEnable == TRUE ||
+ seqParam->frame_mbs_only_flag != TRUE ||
+ picParam->weighted_pred_flag == TRUE ||
+ picParam->weighted_bipred_idc != 0 ||
+ picParam->entropy_coding_mode_flag == TRUE ||
+ picParam->num_slice_groups_minus1 > 7 /*||
+ picParam->num_slice_groups_minus1<0 (no need, it's unsigned) */)
+ {
+ status = AVCENC_TOOLS_NOT_SUPPORTED;
+ }
+ break;
+
+ case AVC_MAIN:
+ case AVC_EXTENDED:
+ status = AVCENC_PROFILE_NOT_SUPPORTED;
+ }
+
+ return status;
+}
+
+/* verify the level setting */
+AVCEnc_Status VerifyLevel(AVCEncObject *encvid, AVCSeqParamSet *seqParam, AVCPicParamSet *picParam)
+{
+ (void)(picParam);
+
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ AVCCommonObj *video = encvid->common;
+ int mb_per_sec, ii;
+ int lev_idx;
+ int dpb_size;
+
+ mb_per_sec = (int)(video->PicSizeInMbs * rateCtrl->frame_rate + 0.5);
+ dpb_size = (seqParam->num_ref_frames * video->PicSizeInMbs * 3) >> 6;
+
+ if (seqParam->level_idc == 0) /* find level for this setting */
+ {
+ for (ii = 0; ii < MAX_LEVEL_IDX; ii++)
+ {
+ if (mb_per_sec <= MaxMBPS[ii] &&
+ video->PicSizeInMbs <= (uint)MaxFS[ii] &&
+ rateCtrl->bitRate <= (int32)MaxBR[ii]*1000 &&
+ rateCtrl->cpbSize <= (int32)MaxCPB[ii]*1000 &&
+ rateCtrl->mvRange <= MaxVmvR[ii] &&
+ dpb_size <= MaxDPBX2[ii]*512)
+ {
+ seqParam->level_idc = mapIdx2Lev[ii];
+ break;
+ }
+ }
+ if (seqParam->level_idc == 0)
+ {
+ return AVCENC_LEVEL_NOT_SUPPORTED;
+ }
+ }
+
+ /* check if this level is supported by this library */
+ lev_idx = mapLev2Idx[seqParam->level_idc];
+ if (seqParam->level_idc == AVC_LEVEL1_B)
+ {
+ seqParam->constrained_set3_flag = 1;
+ }
+
+
+ if (lev_idx == 255) /* not defined */
+ {
+ return AVCENC_LEVEL_NOT_SUPPORTED;
+ }
+
+ /* check if the encoding setting complies with the level */
+ if (mb_per_sec > MaxMBPS[lev_idx] ||
+ video->PicSizeInMbs > (uint)MaxFS[lev_idx] ||
+ rateCtrl->bitRate > (int32)MaxBR[lev_idx]*1000 ||
+ rateCtrl->cpbSize > (int32)MaxCPB[lev_idx]*1000 ||
+ rateCtrl->mvRange > MaxVmvR[lev_idx])
+ {
+ return AVCENC_LEVEL_FAIL;
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+/* initialize variables at the beginning of each frame */
+/* determine the picture type */
+/* encode POC */
+/* maybe we should do more stuff here. MotionEstimation+SCD and generate a new SPS and PPS */
+AVCEnc_Status InitFrame(AVCEncObject *encvid)
+{
+ AVCStatus ret;
+ AVCEnc_Status status;
+ AVCCommonObj *video = encvid->common;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+
+ /* look for the next frame in coding_order and look for available picture
+ in the DPB. Note, video->currFS->PicOrderCnt, currFS->FrameNum and currPic->PicNum
+ are set to wrong number in this function (right for decoder). */
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ // call init DPB in here.
+ ret = AVCConfigureSequence(encvid->avcHandle, video, TRUE);
+ if (ret != AVC_SUCCESS)
+ {
+ return AVCENC_FAIL;
+ }
+ }
+
+ /* flexible macroblock ordering (every frame)*/
+ /* populate video->mapUnitToSliceGroupMap and video->MbToSliceGroupMap */
+ /* It changes once per each PPS. */
+ FMOInit(video);
+
+ ret = DPBInitBuffer(encvid->avcHandle, video); // get new buffer
+
+ if (ret != AVC_SUCCESS)
+ {
+ return (AVCEnc_Status)ret; // AVCENC_PICTURE_READY, FAIL
+ }
+
+ DPBInitPic(video, 0); /* 0 is dummy */
+
+ /************* determine picture type IDR or non-IDR ***********/
+ video->currPicType = AVC_FRAME;
+ video->slice_data_partitioning = FALSE;
+ encvid->currInput->is_reference = 1; /* default to all frames */
+ video->nal_ref_idc = 1; /* need to set this for InitPOC */
+ video->currPic->isReference = TRUE;
+
+ /************* set frame_num ********************/
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ video->prevFrameNum = video->MaxFrameNum;
+ video->PrevRefFrameNum = 0;
+ sliceHdr->frame_num = 0;
+ }
+ /* otherwise, it's set to previous reference frame access unit's frame_num in decoding order,
+ see the end of PVAVCDecodeSlice()*/
+ /* There's also restriction on the frame_num, see page 59 of JVT-I1010.doc. */
+ /* Basically, frame_num can't be repeated unless it's opposite fields or non reference fields */
+ else
+ {
+ sliceHdr->frame_num = (video->PrevRefFrameNum + 1) % video->MaxFrameNum;
+ }
+ video->CurrPicNum = sliceHdr->frame_num; /* for field_pic_flag = 0 */
+ //video->CurrPicNum = 2*sliceHdr->frame_num + 1; /* for field_pic_flag = 1 */
+
+ /* assign pic_order_cnt, video->PicOrderCnt */
+ status = InitPOC(encvid);
+ if (status != AVCENC_SUCCESS) /* incorrigable fail */
+ {
+ return status;
+ }
+
+ /* Initialize refListIdx for this picture */
+ RefListInit(video);
+
+ /************* motion estimation and scene analysis ************/
+ // , to move this to MB-based MV search for comparison
+ // use sub-optimal QP for mv search
+ AVCMotionEstimation(encvid); /* AVCENC_SUCCESS or AVCENC_NEW_IDR */
+
+ /* after this point, the picture type will be fixed to either IDR or non-IDR */
+ video->currFS->PicOrderCnt = video->PicOrderCnt;
+ video->currFS->FrameNum = video->sliceHdr->frame_num;
+ video->currPic->PicNum = video->CurrPicNum;
+ video->mbNum = 0; /* start from zero MB */
+ encvid->currSliceGroup = 0; /* start from slice group #0 */
+ encvid->numIntraMB = 0; /* reset this counter */
+
+ if (video->nal_unit_type == AVC_NALTYPE_IDR)
+ {
+ RCInitGOP(encvid);
+
+ /* calculate picture QP */
+ RCInitFrameQP(encvid);
+
+ return AVCENC_NEW_IDR;
+ }
+
+ /* calculate picture QP */
+ RCInitFrameQP(encvid); /* get QP after MV search */
+
+ return AVCENC_SUCCESS;
+}
+
+/* initialize variables for this slice */
+AVCEnc_Status InitSlice(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCPicParamSet *currPPS = video->currPicParams;
+ AVCSeqParamSet *currSPS = video->currSeqParams;
+ int slice_type = video->slice_type;
+
+ sliceHdr->first_mb_in_slice = video->mbNum;
+ if (video->mbNum) // not first slice of a frame
+ {
+ video->sliceHdr->slice_type = (AVCSliceType)slice_type;
+ }
+
+ /* sliceHdr->slice_type already set in InitFrame */
+
+ sliceHdr->pic_parameter_set_id = video->currPicParams->pic_parameter_set_id;
+
+ /* sliceHdr->frame_num already set in InitFrame */
+
+ if (!currSPS->frame_mbs_only_flag) /* we shouldn't need this check */
+ {
+ sliceHdr->field_pic_flag = sliceHdr->bottom_field_flag = FALSE;
+ return AVCENC_TOOLS_NOT_SUPPORTED;
+ }
+
+ /* sliceHdr->idr_pic_id already set in PVAVCEncodeNAL
+
+ sliceHdr->pic_order_cnt_lsb already set in InitFrame..InitPOC
+ sliceHdr->delta_pic_order_cnt_bottom already set in InitPOC
+
+ sliceHdr->delta_pic_order_cnt[0] already set in InitPOC
+ sliceHdr->delta_pic_order_cnt[1] already set in InitPOC
+ */
+
+ sliceHdr->redundant_pic_cnt = 0; /* default if(currPPS->redundant_pic_cnt_present_flag), range 0..127 */
+ sliceHdr->direct_spatial_mv_pred_flag = 0; // default if(slice_type == AVC_B_SLICE)
+
+ sliceHdr->num_ref_idx_active_override_flag = FALSE; /* default, if(slice_type== P,SP or B)*/
+ sliceHdr->num_ref_idx_l0_active_minus1 = 0; /* default, if (num_ref_idx_active_override_flag) */
+ sliceHdr->num_ref_idx_l1_active_minus1 = 0; /* default, if above and B_slice */
+ /* the above 2 values range from 0..15 for frame picture and 0..31 for field picture */
+
+ /* ref_pic_list_reordering(), currently we don't do anything */
+ sliceHdr->ref_pic_list_reordering_flag_l0 = FALSE; /* default */
+ sliceHdr->ref_pic_list_reordering_flag_l1 = FALSE; /* default */
+ /* if the above are TRUE, some other params must be set */
+
+ if ((currPPS->weighted_pred_flag && (slice_type == AVC_P_SLICE || slice_type == AVC_SP_SLICE)) ||
+ (currPPS->weighted_bipred_idc == 1 && slice_type == AVC_B_SLICE))
+ {
+ // pred_weight_table(); // not supported !!
+ return AVCENC_TOOLS_NOT_SUPPORTED;
+ }
+
+ /* dec_ref_pic_marking(), this will be done later*/
+ sliceHdr->no_output_of_prior_pics_flag = FALSE; /* default */
+ sliceHdr->long_term_reference_flag = FALSE; /* for IDR frame, do not make it long term */
+ sliceHdr->adaptive_ref_pic_marking_mode_flag = FALSE; /* default */
+ /* other params are not set here because they are not used */
+
+ sliceHdr->cabac_init_idc = 0; /* default, if entropy_coding_mode_flag && slice_type==I or SI, range 0..2 */
+ sliceHdr->slice_qp_delta = 0; /* default for now */
+ sliceHdr->sp_for_switch_flag = FALSE; /* default, if slice_type == SP */
+ sliceHdr->slice_qs_delta = 0; /* default, if slice_type == SP or SI */
+
+ /* derived variables from encParam */
+ /* deblocking filter */
+ video->FilterOffsetA = video->FilterOffsetB = 0;
+ if (currPPS->deblocking_filter_control_present_flag == TRUE)
+ {
+ video->FilterOffsetA = sliceHdr->slice_alpha_c0_offset_div2 << 1;
+ video->FilterOffsetB = sliceHdr->slice_beta_offset_div_2 << 1;
+ }
+
+ /* flexible macroblock ordering */
+ /* populate video->mapUnitToSliceGroupMap and video->MbToSliceGroupMap */
+ /* We already call it at the end of PVAVCEncInitialize(). It changes once per each PPS. */
+ if (video->currPicParams->num_slice_groups_minus1 > 0 && video->currPicParams->slice_group_map_type >= 3
+ && video->currPicParams->slice_group_map_type <= 5)
+ {
+ sliceHdr->slice_group_change_cycle = SLICE_GROUP_CHANGE_CYCLE; /* default, don't understand how to set it!!!*/
+
+ video->MapUnitsInSliceGroup0 =
+ AVC_MIN(sliceHdr->slice_group_change_cycle * video->SliceGroupChangeRate, video->PicSizeInMapUnits);
+
+ FMOInit(video);
+ }
+
+ /* calculate SliceQPy first */
+ /* calculate QSy first */
+
+ sliceHdr->slice_qp_delta = video->QPy - 26 - currPPS->pic_init_qp_minus26;
+ //sliceHdr->slice_qs_delta = video->QSy - 26 - currPPS->pic_init_qs_minus26;
+
+ return AVCENC_SUCCESS;
+}
+
diff --git a/media/libstagefright/codecs/avc/enc/src/intra_est.cpp b/media/libstagefright/codecs/avc/enc/src/intra_est.cpp
new file mode 100644
index 0000000..17e5985
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/intra_est.cpp
@@ -0,0 +1,2199 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+#define TH_I4 0 /* threshold biasing toward I16 mode instead of I4 mode */
+#define TH_Intra 0 /* threshold biasing toward INTER mode instead of intra mode */
+
+#define FIXED_INTRAPRED_MODE AVC_I16
+#define FIXED_I16_MODE AVC_I16_DC
+#define FIXED_I4_MODE AVC_I4_Diagonal_Down_Left
+#define FIXED_INTRA_CHROMA_MODE AVC_IC_DC
+
+#define CLIP_RESULT(x) if((uint)x > 0xFF){ \
+ x = 0xFF & (~(x>>31));}
+
+
+bool IntraDecisionABE(AVCEncObject *encvid, int min_cost, uint8 *curL, int picPitch)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCFrameIO *currInput = encvid->currInput;
+ int orgPitch = currInput->pitch;
+ int x_pos = (video->mb_x) << 4;
+ int y_pos = (video->mb_y) << 4;
+ uint8 *orgY = currInput->YCbCr[0] + y_pos * orgPitch + x_pos;
+ int j;
+ uint8 *topL, *leftL, *orgY_2, *orgY_3;
+ int temp, SBE, offset;
+ OsclFloat ABE;
+ bool intra = true;
+
+ if (((x_pos >> 4) != (int)video->PicWidthInMbs - 1) &&
+ ((y_pos >> 4) != (int)video->PicHeightInMbs - 1) &&
+ video->intraAvailA &&
+ video->intraAvailB)
+ {
+ SBE = 0;
+ /* top neighbor */
+ topL = curL - picPitch;
+ /* left neighbor */
+ leftL = curL - 1;
+ orgY_2 = orgY - orgPitch;
+
+ for (j = 0; j < 16; j++)
+ {
+ temp = *topL++ - orgY[j];
+ SBE += ((temp >= 0) ? temp : -temp);
+ temp = *(leftL += picPitch) - *(orgY_2 += orgPitch);
+ SBE += ((temp >= 0) ? temp : -temp);
+ }
+
+ /* calculate chroma */
+ offset = (y_pos >> 2) * picPitch + (x_pos >> 1);
+ topL = video->currPic->Scb + offset;
+ orgY_2 = currInput->YCbCr[1] + offset + (y_pos >> 2) * (orgPitch - picPitch);
+
+ leftL = topL - 1;
+ topL -= (picPitch >> 1);
+ orgY_3 = orgY_2 - (orgPitch >> 1);
+ for (j = 0; j < 8; j++)
+ {
+ temp = *topL++ - orgY_2[j];
+ SBE += ((temp >= 0) ? temp : -temp);
+ temp = *(leftL += (picPitch >> 1)) - *(orgY_3 += (orgPitch >> 1));
+ SBE += ((temp >= 0) ? temp : -temp);
+ }
+
+ topL = video->currPic->Scr + offset;
+ orgY_2 = currInput->YCbCr[2] + offset + (y_pos >> 2) * (orgPitch - picPitch);
+
+ leftL = topL - 1;
+ topL -= (picPitch >> 1);
+ orgY_3 = orgY_2 - (orgPitch >> 1);
+ for (j = 0; j < 8; j++)
+ {
+ temp = *topL++ - orgY_2[j];
+ SBE += ((temp >= 0) ? temp : -temp);
+ temp = *(leftL += (picPitch >> 1)) - *(orgY_3 += (orgPitch >> 1));
+ SBE += ((temp >= 0) ? temp : -temp);
+ }
+
+ /* compare mincost/384 and SBE/64 */
+ ABE = SBE / 64.0;
+ if (ABE*0.8 >= min_cost / 384.0)
+ {
+ intra = false;
+ }
+ }
+
+ return intra;
+}
+
+/* perform searching for MB mode */
+/* assuming that this is done inside the encoding loop,
+no need to call InitNeighborAvailability */
+
+void MBIntraSearch(AVCEncObject *encvid, int mbnum, uint8 *curL, int picPitch)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCFrameIO *currInput = encvid->currInput;
+ AVCMacroblock *currMB = video->currMB;
+ int min_cost;
+ uint8 *orgY;
+ int x_pos = (video->mb_x) << 4;
+ int y_pos = (video->mb_y) << 4;
+ uint32 *saved_inter;
+ int j;
+ int orgPitch = currInput->pitch;
+ bool intra = true;
+
+ currMB->CBP = 0;
+
+ /* first do motion vector and variable block size search */
+ min_cost = encvid->min_cost[mbnum];
+
+ /* now perform intra prediction search */
+ /* need to add the check for encvid->intraSearch[video->mbNum] to skip intra
+ if it's not worth checking. */
+ if (video->slice_type == AVC_P_SLICE)
+ {
+ /* Decide whether intra search is necessary or not */
+ /* This one, we do it in the encoding loop so the neighboring pixel are the
+ actual reconstructed pixels. */
+ intra = IntraDecisionABE(encvid, min_cost, curL, picPitch);
+ }
+
+ if (intra == true || video->slice_type == AVC_I_SLICE)
+ {
+ orgY = currInput->YCbCr[0] + y_pos * orgPitch + x_pos;
+
+ /* i16 mode search */
+ /* generate all the predictions */
+ intrapred_luma_16x16(encvid);
+
+ /* evaluate them one by one */
+ find_cost_16x16(encvid, orgY, &min_cost);
+
+ if (video->slice_type == AVC_P_SLICE)
+ {
+ /* save current inter prediction */
+ saved_inter = encvid->subpel_pred; /* reuse existing buffer */
+ j = 16;
+ curL -= 4;
+ picPitch -= 16;
+ while (j--)
+ {
+ *saved_inter++ = *((uint32*)(curL += 4));
+ *saved_inter++ = *((uint32*)(curL += 4));
+ *saved_inter++ = *((uint32*)(curL += 4));
+ *saved_inter++ = *((uint32*)(curL += 4));
+ curL += picPitch;
+ }
+
+ }
+
+ /* i4 mode search */
+ mb_intra4x4_search(encvid, &min_cost);
+
+ encvid->min_cost[mbnum] = min_cost; /* update min_cost */
+ }
+
+
+ if (currMB->mb_intra)
+ {
+ chroma_intra_search(encvid);
+
+ /* need to set this in order for the MBInterPrediction to work!! */
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] =
+ currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = -1;
+ }
+ else if (video->slice_type == AVC_P_SLICE && intra == true)
+ {
+ /* restore current inter prediction */
+ saved_inter = encvid->subpel_pred; /* reuse existing buffer */
+ j = 16;
+ curL -= ((picPitch + 16) << 4);
+ while (j--)
+ {
+ *((uint32*)(curL += 4)) = *saved_inter++;
+ *((uint32*)(curL += 4)) = *saved_inter++;
+ *((uint32*)(curL += 4)) = *saved_inter++;
+ *((uint32*)(curL += 4)) = *saved_inter++;
+ curL += picPitch;
+ }
+ }
+
+ return ;
+}
+
+/* generate all the prediction values */
+void intrapred_luma_16x16(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCPictureData *currPic = video->currPic;
+
+ int x_pos = (video->mb_x) << 4;
+ int y_pos = (video->mb_y) << 4;
+ int pitch = currPic->pitch;
+
+ int offset = y_pos * pitch + x_pos;
+
+ uint8 *pred, *top, *left;
+ uint8 *curL = currPic->Sl + offset; /* point to reconstructed frame */
+ uint32 word1, word2, word3, word4;
+ uint32 sum = 0;
+
+ int a_16, b, c, factor_c;
+ uint8 *comp_ref_x0, *comp_ref_x1, *comp_ref_y0, *comp_ref_y1;
+ int H = 0, V = 0, tmp, value;
+ int i;
+
+ if (video->intraAvailB)
+ {
+ //get vertical prediction mode
+ top = curL - pitch;
+
+ pred = encvid->pred_i16[AVC_I16_Vertical] - 16;
+
+ word1 = *((uint32*)(top)); /* read 4 bytes from top */
+ word2 = *((uint32*)(top + 4)); /* read 4 bytes from top */
+ word3 = *((uint32*)(top + 8)); /* read 4 bytes from top */
+ word4 = *((uint32*)(top + 12)); /* read 4 bytes from top */
+
+ for (i = 0; i < 16; i++)
+ {
+ *((uint32*)(pred += 16)) = word1;
+ *((uint32*)(pred + 4)) = word2;
+ *((uint32*)(pred + 8)) = word3;
+ *((uint32*)(pred + 12)) = word4;
+
+ }
+
+ sum = word1 & 0xFF00FF;
+ word1 = (word1 >> 8) & 0xFF00FF;
+ sum += word1;
+ word1 = (word2 & 0xFF00FF);
+ sum += word1;
+ word2 = (word2 >> 8) & 0xFF00FF;
+ sum += word2;
+ word1 = (word3 & 0xFF00FF);
+ sum += word1;
+ word3 = (word3 >> 8) & 0xFF00FF;
+ sum += word3;
+ word1 = (word4 & 0xFF00FF);
+ sum += word1;
+ word4 = (word4 >> 8) & 0xFF00FF;
+ sum += word4;
+
+ sum += (sum >> 16);
+ sum &= 0xFFFF;
+
+ if (!video->intraAvailA)
+ {
+ sum = (sum + 8) >> 4;
+ }
+ }
+
+ if (video->intraAvailA)
+ {
+ // get horizontal mode
+ left = curL - 1 - pitch;
+
+ pred = encvid->pred_i16[AVC_I16_Horizontal] - 16;
+
+ for (i = 0; i < 16; i++)
+ {
+ word1 = *(left += pitch);
+ sum += word1;
+
+ word1 = (word1 << 8) | word1;
+ word1 = (word1 << 16) | word1; /* make it 4 */
+
+ *(uint32*)(pred += 16) = word1;
+ *(uint32*)(pred + 4) = word1;
+ *(uint32*)(pred + 8) = word1;
+ *(uint32*)(pred + 12) = word1;
+ }
+
+ if (!video->intraAvailB)
+ {
+ sum = (sum + 8) >> 4;
+ }
+ else
+ {
+ sum = (sum + 16) >> 5;
+ }
+ }
+
+ // get DC mode
+ if (!video->intraAvailA && !video->intraAvailB)
+ {
+ sum = 0x80808080;
+ }
+ else
+ {
+ sum = (sum << 8) | sum;
+ sum = (sum << 16) | sum;
+ }
+
+ pred = encvid->pred_i16[AVC_I16_DC] - 16;
+ for (i = 0; i < 16; i++)
+ {
+ *((uint32*)(pred += 16)) = sum;
+ *((uint32*)(pred + 4)) = sum;
+ *((uint32*)(pred + 8)) = sum;
+ *((uint32*)(pred + 12)) = sum;
+ }
+
+ // get plane mode
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ pred = encvid->pred_i16[AVC_I16_Plane] - 16;
+
+ comp_ref_x0 = curL - pitch + 8;
+ comp_ref_x1 = curL - pitch + 6;
+ comp_ref_y0 = curL - 1 + (pitch << 3);
+ comp_ref_y1 = curL - 1 + 6 * pitch;
+
+ for (i = 1; i < 8; i++)
+ {
+ H += i * (*comp_ref_x0++ - *comp_ref_x1--);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+ comp_ref_y0 += pitch;
+ comp_ref_y1 -= pitch;
+ }
+
+ H += i * (*comp_ref_x0++ - curL[-pitch-1]);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+
+
+ a_16 = ((*(curL - pitch + 15) + *(curL - 1 + 15 * pitch)) << 4) + 16;;
+ b = (5 * H + 32) >> 6;
+ c = (5 * V + 32) >> 6;
+
+ tmp = 0;
+ for (i = 0; i < 16; i++)
+ {
+ factor_c = a_16 + c * (tmp++ - 7);
+ factor_c -= 7 * b;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 8);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 16);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 24);
+ *((uint32*)(pred += 16)) = word1;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 8);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 16);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 24);
+ *((uint32*)(pred + 4)) = word1;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 8);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 16);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 24);
+ *((uint32*)(pred + 8)) = word1;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 8);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 16);
+ value = factor_c >> 5;
+ CLIP_RESULT(value)
+ word1 = (word1) | (value << 24);
+ *((uint32*)(pred + 12)) = word1;
+ }
+ }
+
+ return ;
+}
+
+
+/* evaluate each prediction mode of I16 */
+void find_cost_16x16(AVCEncObject *encvid, uint8 *orgY, int *min_cost)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCMacroblock *currMB = video->currMB;
+ int cost;
+ int org_pitch = encvid->currInput->pitch;
+
+ /* evaluate vertical mode */
+ if (video->intraAvailB)
+ {
+ cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_Vertical], *min_cost);
+ if (cost < *min_cost)
+ {
+ *min_cost = cost;
+ currMB->mbMode = AVC_I16;
+ currMB->mb_intra = 1;
+ currMB->i16Mode = AVC_I16_Vertical;
+ }
+ }
+
+
+ /* evaluate horizontal mode */
+ if (video->intraAvailA)
+ {
+ cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_Horizontal], *min_cost);
+ if (cost < *min_cost)
+ {
+ *min_cost = cost;
+ currMB->mbMode = AVC_I16;
+ currMB->mb_intra = 1;
+ currMB->i16Mode = AVC_I16_Horizontal;
+ }
+ }
+
+ /* evaluate DC mode */
+ cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_DC], *min_cost);
+ if (cost < *min_cost)
+ {
+ *min_cost = cost;
+ currMB->mbMode = AVC_I16;
+ currMB->mb_intra = 1;
+ currMB->i16Mode = AVC_I16_DC;
+ }
+
+ /* evaluate plane mode */
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ cost = cost_i16(orgY, org_pitch, encvid->pred_i16[AVC_I16_Plane], *min_cost);
+ if (cost < *min_cost)
+ {
+ *min_cost = cost;
+ currMB->mbMode = AVC_I16;
+ currMB->mb_intra = 1;
+ currMB->i16Mode = AVC_I16_Plane;
+ }
+ }
+
+ return ;
+}
+
+
+int cost_i16(uint8 *org, int org_pitch, uint8 *pred, int min_cost)
+{
+
+ int cost;
+ int j, k;
+ int16 res[256], *pres; // residue
+ int m0, m1, m2, m3;
+
+ // calculate SATD
+ org_pitch -= 16;
+ pres = res;
+ // horizontal transform
+ for (j = 0; j < 16; j++)
+ {
+ k = 4;
+ while (k > 0)
+ {
+ m0 = org[0] - pred[0];
+ m3 = org[3] - pred[3];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = org[1] - pred[1];
+ m2 = org[2] - pred[2];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 + m1;
+ pres[2] = m0 - m1;
+ pres[1] = m2 + m3;
+ pres[3] = m3 - m2;
+
+ org += 4;
+ pres += 4;
+ pred += 4;
+ k--;
+ }
+ org += org_pitch;
+ }
+ /* vertical transform */
+ cost = 0;
+ for (j = 0; j < 4; j++)
+ {
+ pres = res + (j << 6);
+ k = 16;
+ while (k > 0)
+ {
+ m0 = pres[0];
+ m3 = pres[3<<4];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = pres[1<<4];
+ m2 = pres[2<<4];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 = m0 + m1;
+
+ if (k&0x3) // only sum up non DC values.
+ {
+ cost += ((m0 > 0) ? m0 : -m0);
+ }
+
+ m1 = m0 - (m1 << 1);
+ cost += ((m1 > 0) ? m1 : -m1);
+ m3 = m2 + m3;
+ cost += ((m3 > 0) ? m3 : -m3);
+ m2 = m3 - (m2 << 1);
+ cost += ((m2 > 0) ? m2 : -m2);
+
+ pres++;
+ k--;
+ }
+ if ((cost >> 1) > min_cost) /* early drop out */
+ {
+ return (cost >> 1);
+ }
+ }
+
+ /* Hadamard of the DC coefficient */
+ pres = res;
+ k = 4;
+ while (k > 0)
+ {
+ m0 = pres[0];
+ m3 = pres[3<<2];
+ m0 >>= 2;
+ m0 += (m3 >> 2);
+ m3 = m0 - (m3 >> 1);
+ m1 = pres[1<<2];
+ m2 = pres[2<<2];
+ m1 >>= 2;
+ m1 += (m2 >> 2);
+ m2 = m1 - (m2 >> 1);
+ pres[0] = (m0 + m1);
+ pres[2<<2] = (m0 - m1);
+ pres[1<<2] = (m2 + m3);
+ pres[3<<2] = (m3 - m2);
+ pres += (4 << 4);
+ k--;
+ }
+
+ pres = res;
+ k = 4;
+ while (k > 0)
+ {
+ m0 = pres[0];
+ m3 = pres[3<<6];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = pres[1<<6];
+ m2 = pres[2<<6];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ m0 = m0 + m1;
+ cost += ((m0 >= 0) ? m0 : -m0);
+ m1 = m0 - (m1 << 1);
+ cost += ((m1 >= 0) ? m1 : -m1);
+ m3 = m2 + m3;
+ cost += ((m3 >= 0) ? m3 : -m3);
+ m2 = m3 - (m2 << 1);
+ cost += ((m2 >= 0) ? m2 : -m2);
+ pres += 4;
+
+ if ((cost >> 1) > min_cost) /* early drop out */
+ {
+ return (cost >> 1);
+ }
+
+ k--;
+ }
+
+ return (cost >> 1);
+}
+
+
+void mb_intra4x4_search(AVCEncObject *encvid, int *min_cost)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCMacroblock *currMB = video->currMB;
+ AVCPictureData *currPic = video->currPic;
+ AVCFrameIO *currInput = encvid->currInput;
+ int pitch = currPic->pitch;
+ int org_pitch = currInput->pitch;
+ int offset;
+ uint8 *curL, *comp, *org4, *org8;
+ int y = video->mb_y << 4;
+ int x = video->mb_x << 4;
+
+ int b8, b4, cost4x4, blkidx;
+ int cost = 0;
+ int numcoef;
+ int dummy = 0;
+ int mb_intra = currMB->mb_intra; // save the original value
+
+ offset = y * pitch + x;
+
+ curL = currPic->Sl + offset;
+ org8 = currInput->YCbCr[0] + y * org_pitch + x;
+ video->pred_pitch = 4;
+
+ cost = (int)(6.0 * encvid->lambda_mode + 0.4999);
+ cost <<= 2;
+
+ currMB->mb_intra = 1; // temporary set this to one to enable the IDCT
+ // operation inside dct_luma
+
+ for (b8 = 0; b8 < 4; b8++)
+ {
+ comp = curL;
+ org4 = org8;
+
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ blkidx = blkIdx2blkXY[b8][b4];
+ cost4x4 = blk_intra4x4_search(encvid, blkidx, comp, org4);
+ cost += cost4x4;
+ if (cost > *min_cost)
+ {
+ currMB->mb_intra = mb_intra; // restore the value
+ return ;
+ }
+
+ /* do residue, Xfrm, Q, invQ, invXfrm, recon and save the DCT coefs.*/
+ video->pred_block = encvid->pred_i4[currMB->i4Mode[blkidx]];
+ numcoef = dct_luma(encvid, blkidx, comp, org4, &dummy);
+ currMB->nz_coeff[blkidx] = numcoef;
+ if (numcoef)
+ {
+ video->cbp4x4 |= (1 << blkidx);
+ currMB->CBP |= (1 << b8);
+ }
+
+ if (b4&1)
+ {
+ comp += ((pitch << 2) - 4);
+ org4 += ((org_pitch << 2) - 4);
+ }
+ else
+ {
+ comp += 4;
+ org4 += 4;
+ }
+ }
+
+ if (b8&1)
+ {
+ curL += ((pitch << 3) - 8);
+ org8 += ((org_pitch << 3) - 8);
+ }
+ else
+ {
+ curL += 8;
+ org8 += 8;
+ }
+ }
+
+ currMB->mb_intra = mb_intra; // restore the value
+
+ if (cost < *min_cost)
+ {
+ *min_cost = cost;
+ currMB->mbMode = AVC_I4;
+ currMB->mb_intra = 1;
+ }
+
+ return ;
+}
+
+
+/* search for i4 mode for a 4x4 block */
+int blk_intra4x4_search(AVCEncObject *encvid, int blkidx, uint8 *cur, uint8 *org)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCNeighborAvailability availability;
+ AVCMacroblock *currMB = video->currMB;
+ bool top_left = FALSE;
+ int pitch = video->currPic->pitch;
+ uint8 mode_avail[AVCNumI4PredMode];
+ uint32 temp, DC;
+ uint8 *pred;
+ int org_pitch = encvid->currInput->pitch;
+ uint16 min_cost, cost;
+
+ int P_x, Q_x, R_x, P_y, Q_y, R_y, D, D0, D1;
+ int P0, Q0, R0, S0, P1, Q1, R1, P2, Q2;
+ uint8 P_A, P_B, P_C, P_D, P_E, P_F, P_G, P_H, P_I, P_J, P_K, P_L, P_X;
+ int r0, r1, r2, r3, r4, r5, r6, r7;
+ int x0, x1, x2, x3, x4, x5;
+ uint32 temp1, temp2;
+
+ int ipmode, mostProbableMode;
+ int fixedcost = 4 * encvid->lambda_mode;
+ int min_sad = 0x7FFF;
+
+ availability.left = TRUE;
+ availability.top = TRUE;
+ if (blkidx <= 3) /* top row block (!block_y) */
+ { /* check availability up */
+ availability.top = video->intraAvailB ;
+ }
+ if (!(blkidx&0x3)) /* left column block (!block_x)*/
+ { /* check availability left */
+ availability.left = video->intraAvailA ;
+ }
+ availability.top_right = BlkTopRight[blkidx];
+
+ if (availability.top_right == 2)
+ {
+ availability.top_right = video->intraAvailB;
+ }
+ else if (availability.top_right == 3)
+ {
+ availability.top_right = video->intraAvailC;
+ }
+
+ if (availability.top == TRUE)
+ {
+ temp = *(uint32*)(cur - pitch);
+ P_A = temp & 0xFF;
+ P_B = (temp >> 8) & 0xFF;
+ P_C = (temp >> 16) & 0xFF;
+ P_D = (temp >> 24) & 0xFF;
+ }
+ else
+ {
+ P_A = P_B = P_C = P_D = 128;
+ }
+
+ if (availability.top_right == TRUE)
+ {
+ temp = *(uint32*)(cur - pitch + 4);
+ P_E = temp & 0xFF;
+ P_F = (temp >> 8) & 0xFF;
+ P_G = (temp >> 16) & 0xFF;
+ P_H = (temp >> 24) & 0xFF;
+ }
+ else
+ {
+ P_E = P_F = P_G = P_H = 128;
+ }
+
+ if (availability.left == TRUE)
+ {
+ cur--;
+ P_I = *cur;
+ P_J = *(cur += pitch);
+ P_K = *(cur += pitch);
+ P_L = *(cur + pitch);
+ cur -= (pitch << 1);
+ cur++;
+ }
+ else
+ {
+ P_I = P_J = P_K = P_L = 128;
+ }
+
+ /* check if top-left pixel is available */
+ if (((blkidx > 3) && (blkidx&0x3)) || ((blkidx > 3) && video->intraAvailA)
+ || ((blkidx&0x3) && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB))
+ {
+ top_left = TRUE;
+ P_X = *(cur - pitch - 1);
+ }
+ else
+ {
+ P_X = 128;
+ }
+
+ //===== INTRA PREDICTION FOR 4x4 BLOCK =====
+ /* vertical */
+ mode_avail[AVC_I4_Vertical] = 0;
+ if (availability.top)
+ {
+ mode_avail[AVC_I4_Vertical] = 1;
+ pred = encvid->pred_i4[AVC_I4_Vertical];
+
+ temp = (P_D << 24) | (P_C << 16) | (P_B << 8) | P_A ;
+ *((uint32*)pred) = temp; /* write 4 at a time */
+ *((uint32*)(pred += 4)) = temp;
+ *((uint32*)(pred += 4)) = temp;
+ *((uint32*)(pred += 4)) = temp;
+ }
+ /* horizontal */
+ mode_avail[AVC_I4_Horizontal] = 0;
+ mode_avail[AVC_I4_Horizontal_Up] = 0;
+ if (availability.left)
+ {
+ mode_avail[AVC_I4_Horizontal] = 1;
+ pred = encvid->pred_i4[AVC_I4_Horizontal];
+
+ temp = P_I | (P_I << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+ temp = P_J | (P_J << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)(pred += 4)) = temp;
+ temp = P_K | (P_K << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)(pred += 4)) = temp;
+ temp = P_L | (P_L << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)(pred += 4)) = temp;
+
+ mode_avail[AVC_I4_Horizontal_Up] = 1;
+ pred = encvid->pred_i4[AVC_I4_Horizontal_Up];
+
+ Q0 = (P_J + P_K + 1) >> 1;
+ Q1 = (P_J + (P_K << 1) + P_L + 2) >> 2;
+ P0 = ((P_I + P_J + 1) >> 1);
+ P1 = ((P_I + (P_J << 1) + P_K + 2) >> 2);
+
+ temp = P0 | (P1 << 8); // [P0 P1 Q0 Q1]
+ temp |= (Q0 << 16); // [Q0 Q1 R0 DO]
+ temp |= (Q1 << 24); // [R0 D0 D1 D1]
+ *((uint32*)pred) = temp; // [D1 D1 D1 D1]
+
+ D0 = (P_K + 3 * P_L + 2) >> 2;
+ R0 = (P_K + P_L + 1) >> 1;
+
+ temp = Q0 | (Q1 << 8);
+ temp |= (R0 << 16);
+ temp |= (D0 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ D1 = P_L;
+
+ temp = R0 | (D0 << 8);
+ temp |= (D1 << 16);
+ temp |= (D1 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = D1 | (D1 << 8);
+ temp |= (temp << 16);
+ *((uint32*)(pred += 4)) = temp;
+ }
+ /* DC */
+ mode_avail[AVC_I4_DC] = 1;
+ pred = encvid->pred_i4[AVC_I4_DC];
+ if (availability.left)
+ {
+ DC = P_I + P_J + P_K + P_L;
+
+ if (availability.top)
+ {
+ DC = (P_A + P_B + P_C + P_D + DC + 4) >> 3;
+ }
+ else
+ {
+ DC = (DC + 2) >> 2;
+
+ }
+ }
+ else if (availability.top)
+ {
+ DC = (P_A + P_B + P_C + P_D + 2) >> 2;
+
+ }
+ else
+ {
+ DC = 128;
+ }
+
+ temp = DC | (DC << 8);
+ temp = temp | (temp << 16);
+ *((uint32*)pred) = temp;
+ *((uint32*)(pred += 4)) = temp;
+ *((uint32*)(pred += 4)) = temp;
+ *((uint32*)(pred += 4)) = temp;
+
+ /* Down-left */
+ mode_avail[AVC_I4_Diagonal_Down_Left] = 0;
+
+ if (availability.top)
+ {
+ mode_avail[AVC_I4_Diagonal_Down_Left] = 1;
+
+ pred = encvid->pred_i4[AVC_I4_Diagonal_Down_Left];
+
+ r0 = P_A;
+ r1 = P_B;
+ r2 = P_C;
+ r3 = P_D;
+
+ r0 += (r1 << 1);
+ r0 += r2;
+ r0 += 2;
+ r0 >>= 2;
+ r1 += (r2 << 1);
+ r1 += r3;
+ r1 += 2;
+ r1 >>= 2;
+
+ if (availability.top_right)
+ {
+ r4 = P_E;
+ r5 = P_F;
+ r6 = P_G;
+ r7 = P_H;
+
+ r2 += (r3 << 1);
+ r2 += r4;
+ r2 += 2;
+ r2 >>= 2;
+ r3 += (r4 << 1);
+ r3 += r5;
+ r3 += 2;
+ r3 >>= 2;
+ r4 += (r5 << 1);
+ r4 += r6;
+ r4 += 2;
+ r4 >>= 2;
+ r5 += (r6 << 1);
+ r5 += r7;
+ r5 += 2;
+ r5 >>= 2;
+ r6 += (3 * r7);
+ r6 += 2;
+ r6 >>= 2;
+ temp = r0 | (r1 << 8);
+ temp |= (r2 << 16);
+ temp |= (r3 << 24);
+ *((uint32*)pred) = temp;
+
+ temp = (temp >> 8) | (r4 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = (temp >> 8) | (r5 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = (temp >> 8) | (r6 << 24);
+ *((uint32*)(pred += 4)) = temp;
+ }
+ else
+ {
+ r2 += (r3 * 3);
+ r2 += 2;
+ r2 >>= 2;
+ r3 = ((r3 << 2) + 2);
+ r3 >>= 2;
+
+ temp = r0 | (r1 << 8);
+ temp |= (r2 << 16);
+ temp |= (r3 << 24);
+ *((uint32*)pred) = temp;
+
+ temp = (temp >> 8) | (r3 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = (temp >> 8) | (r3 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = (temp >> 8) | (r3 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ }
+ }
+
+ /* Down Right */
+ mode_avail[AVC_I4_Diagonal_Down_Right] = 0;
+ /* Diagonal Vertical Right */
+ mode_avail[AVC_I4_Vertical_Right] = 0;
+ /* Horizontal Down */
+ mode_avail[AVC_I4_Horizontal_Down] = 0;
+
+ if (top_left == TRUE)
+ {
+ /* Down Right */
+ mode_avail[AVC_I4_Diagonal_Down_Right] = 1;
+ pred = encvid->pred_i4[AVC_I4_Diagonal_Down_Right];
+
+ Q_x = (P_A + 2 * P_B + P_C + 2) >> 2;
+ R_x = (P_B + 2 * P_C + P_D + 2) >> 2;
+ P_x = (P_X + 2 * P_A + P_B + 2) >> 2;
+ D = (P_A + 2 * P_X + P_I + 2) >> 2;
+ P_y = (P_X + 2 * P_I + P_J + 2) >> 2;
+ Q_y = (P_I + 2 * P_J + P_K + 2) >> 2;
+ R_y = (P_J + 2 * P_K + P_L + 2) >> 2;
+
+ /* we can pack these */
+ temp = D | (P_x << 8); //[D P_x Q_x R_x]
+ //[P_y D P_x Q_x]
+ temp |= (Q_x << 16); //[Q_y P_y D P_x]
+ temp |= (R_x << 24); //[R_y Q_y P_y D ]
+ *((uint32*)pred) = temp;
+
+ temp = P_y | (D << 8);
+ temp |= (P_x << 16);
+ temp |= (Q_x << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = Q_y | (P_y << 8);
+ temp |= (D << 16);
+ temp |= (P_x << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = R_y | (Q_y << 8);
+ temp |= (P_y << 16);
+ temp |= (D << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+
+ /* Diagonal Vertical Right */
+ mode_avail[AVC_I4_Vertical_Right] = 1;
+ pred = encvid->pred_i4[AVC_I4_Vertical_Right];
+
+ Q0 = P_A + P_B + 1;
+ R0 = P_B + P_C + 1;
+ S0 = P_C + P_D + 1;
+ P0 = P_X + P_A + 1;
+ D = (P_I + 2 * P_X + P_A + 2) >> 2;
+
+ P1 = (P0 + Q0) >> 2;
+ Q1 = (Q0 + R0) >> 2;
+ R1 = (R0 + S0) >> 2;
+
+ P0 >>= 1;
+ Q0 >>= 1;
+ R0 >>= 1;
+ S0 >>= 1;
+
+ P2 = (P_X + 2 * P_I + P_J + 2) >> 2;
+ Q2 = (P_I + 2 * P_J + P_K + 2) >> 2;
+
+ temp = P0 | (Q0 << 8); //[P0 Q0 R0 S0]
+ //[D P1 Q1 R1]
+ temp |= (R0 << 16); //[P2 P0 Q0 R0]
+ temp |= (S0 << 24); //[Q2 D P1 Q1]
+ *((uint32*)pred) = temp;
+
+ temp = D | (P1 << 8);
+ temp |= (Q1 << 16);
+ temp |= (R1 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = P2 | (P0 << 8);
+ temp |= (Q0 << 16);
+ temp |= (R0 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = Q2 | (D << 8);
+ temp |= (P1 << 16);
+ temp |= (Q1 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+
+ /* Horizontal Down */
+ mode_avail[AVC_I4_Horizontal_Down] = 1;
+ pred = encvid->pred_i4[AVC_I4_Horizontal_Down];
+
+
+ Q2 = (P_A + 2 * P_B + P_C + 2) >> 2;
+ P2 = (P_X + 2 * P_A + P_B + 2) >> 2;
+ D = (P_I + 2 * P_X + P_A + 2) >> 2;
+ P0 = P_X + P_I + 1;
+ Q0 = P_I + P_J + 1;
+ R0 = P_J + P_K + 1;
+ S0 = P_K + P_L + 1;
+
+ P1 = (P0 + Q0) >> 2;
+ Q1 = (Q0 + R0) >> 2;
+ R1 = (R0 + S0) >> 2;
+
+ P0 >>= 1;
+ Q0 >>= 1;
+ R0 >>= 1;
+ S0 >>= 1;
+
+
+ /* we can pack these */
+ temp = P0 | (D << 8); //[P0 D P2 Q2]
+ //[Q0 P1 P0 D ]
+ temp |= (P2 << 16); //[R0 Q1 Q0 P1]
+ temp |= (Q2 << 24); //[S0 R1 R0 Q1]
+ *((uint32*)pred) = temp;
+
+ temp = Q0 | (P1 << 8);
+ temp |= (P0 << 16);
+ temp |= (D << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = R0 | (Q1 << 8);
+ temp |= (Q0 << 16);
+ temp |= (P1 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ temp = S0 | (R1 << 8);
+ temp |= (R0 << 16);
+ temp |= (Q1 << 24);
+ *((uint32*)(pred += 4)) = temp;
+
+ }
+
+ /* vertical left */
+ mode_avail[AVC_I4_Vertical_Left] = 0;
+ if (availability.top)
+ {
+ mode_avail[AVC_I4_Vertical_Left] = 1;
+ pred = encvid->pred_i4[AVC_I4_Vertical_Left];
+
+ x0 = P_A + P_B + 1;
+ x1 = P_B + P_C + 1;
+ x2 = P_C + P_D + 1;
+ if (availability.top_right)
+ {
+ x3 = P_D + P_E + 1;
+ x4 = P_E + P_F + 1;
+ x5 = P_F + P_G + 1;
+ }
+ else
+ {
+ x3 = x4 = x5 = (P_D << 1) + 1;
+ }
+
+ temp1 = (x0 >> 1);
+ temp1 |= ((x1 >> 1) << 8);
+ temp1 |= ((x2 >> 1) << 16);
+ temp1 |= ((x3 >> 1) << 24);
+
+ *((uint32*)pred) = temp1;
+
+ temp2 = ((x0 + x1) >> 2);
+ temp2 |= (((x1 + x2) >> 2) << 8);
+ temp2 |= (((x2 + x3) >> 2) << 16);
+ temp2 |= (((x3 + x4) >> 2) << 24);
+
+ *((uint32*)(pred += 4)) = temp2;
+
+ temp1 = (temp1 >> 8) | ((x4 >> 1) << 24); /* rotate out old value */
+ *((uint32*)(pred += 4)) = temp1;
+
+ temp2 = (temp2 >> 8) | (((x4 + x5) >> 2) << 24); /* rotate out old value */
+ *((uint32*)(pred += 4)) = temp2;
+ }
+
+ //===== LOOP OVER ALL 4x4 INTRA PREDICTION MODES =====
+ // can re-order the search here instead of going in order
+
+ // find most probable mode
+ encvid->mostProbableI4Mode[blkidx] = mostProbableMode = FindMostProbableI4Mode(video, blkidx);
+
+ min_cost = 0xFFFF;
+
+ for (ipmode = 0; ipmode < AVCNumI4PredMode; ipmode++)
+ {
+ if (mode_avail[ipmode] == TRUE)
+ {
+ cost = (ipmode == mostProbableMode) ? 0 : fixedcost;
+ pred = encvid->pred_i4[ipmode];
+
+ cost_i4(org, org_pitch, pred, &cost);
+
+ if (cost < min_cost)
+ {
+ currMB->i4Mode[blkidx] = (AVCIntra4x4PredMode)ipmode;
+ min_cost = cost;
+ min_sad = cost - ((ipmode == mostProbableMode) ? 0 : fixedcost);
+ }
+ }
+ }
+
+ if (blkidx == 0)
+ {
+ encvid->i4_sad = min_sad;
+ }
+ else
+ {
+ encvid->i4_sad += min_sad;
+ }
+
+ return min_cost;
+}
+
+int FindMostProbableI4Mode(AVCCommonObj *video, int blkidx)
+{
+ int dcOnlyPredictionFlag;
+ AVCMacroblock *currMB = video->currMB;
+ int intra4x4PredModeA, intra4x4PredModeB, predIntra4x4PredMode;
+
+
+ dcOnlyPredictionFlag = 0;
+ if (blkidx&0x3)
+ {
+ intra4x4PredModeA = currMB->i4Mode[blkidx-1]; // block to the left
+ }
+ else /* for blk 0, 4, 8, 12 */
+ {
+ if (video->intraAvailA)
+ {
+ if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
+ {
+ intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[blkidx + 3];
+ }
+ else
+ {
+ intra4x4PredModeA = AVC_I4_DC;
+ }
+ }
+ else
+ {
+ dcOnlyPredictionFlag = 1;
+ goto PRED_RESULT_READY; // skip below
+ }
+ }
+
+ if (blkidx >> 2)
+ {
+ intra4x4PredModeB = currMB->i4Mode[blkidx-4]; // block above
+ }
+ else /* block 0, 1, 2, 3 */
+ {
+ if (video->intraAvailB)
+ {
+ if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
+ {
+ intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[blkidx+12];
+ }
+ else
+ {
+ intra4x4PredModeB = AVC_I4_DC;
+ }
+ }
+ else
+ {
+ dcOnlyPredictionFlag = 1;
+ }
+ }
+
+PRED_RESULT_READY:
+ if (dcOnlyPredictionFlag)
+ {
+ intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
+ }
+
+ predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
+
+ return predIntra4x4PredMode;
+}
+
+void cost_i4(uint8 *org, int org_pitch, uint8 *pred, uint16 *cost)
+{
+ int k;
+ int16 res[16], *pres;
+ int m0, m1, m2, m3, tmp1;
+ int satd = 0;
+
+ pres = res;
+ // horizontal transform
+ k = 4;
+ while (k > 0)
+ {
+ m0 = org[0] - pred[0];
+ m3 = org[3] - pred[3];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = org[1] - pred[1];
+ m2 = org[2] - pred[2];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 + m1;
+ pres[2] = m0 - m1;
+ pres[1] = m2 + m3;
+ pres[3] = m3 - m2;
+
+ org += org_pitch;
+ pres += 4;
+ pred += 4;
+ k--;
+ }
+ /* vertical transform */
+ pres = res;
+ k = 4;
+ while (k > 0)
+ {
+ m0 = pres[0];
+ m3 = pres[12];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = pres[4];
+ m2 = pres[8];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 + m1;
+ pres[8] = m0 - m1;
+ pres[4] = m2 + m3;
+ pres[12] = m3 - m2;
+
+ pres++;
+ k--;
+
+ }
+
+ pres = res;
+ k = 4;
+ while (k > 0)
+ {
+ tmp1 = *pres++;
+ satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ satd += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ k--;
+ }
+
+ satd = (satd + 1) >> 1;
+ *cost += satd;
+
+ return ;
+}
+
+void chroma_intra_search(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCPictureData *currPic = video->currPic;
+
+ int x_pos = video->mb_x << 3;
+ int y_pos = video->mb_y << 3;
+ int pitch = currPic->pitch >> 1;
+ int offset = y_pos * pitch + x_pos;
+
+ uint8 *comp_ref_x, *comp_ref_y, *pred;
+ int sum_x0, sum_x1, sum_y0, sum_y1;
+ int pred_0[2], pred_1[2], pred_2[2], pred_3[2];
+ uint32 pred_a, pred_b, pred_c, pred_d;
+ int i, j, component;
+ int a_16, b, c, factor_c, topleft;
+ int H, V, value;
+ uint8 *comp_ref_x0, *comp_ref_x1, *comp_ref_y0, *comp_ref_y1;
+
+ uint8 *curCb = currPic->Scb + offset;
+ uint8 *curCr = currPic->Scr + offset;
+
+ uint8 *orgCb, *orgCr;
+ AVCFrameIO *currInput = encvid->currInput;
+ AVCMacroblock *currMB = video->currMB;
+ int org_pitch;
+ int cost, mincost;
+
+ /* evaluate DC mode */
+ if (video->intraAvailB & video->intraAvailA)
+ {
+ comp_ref_x = curCb - pitch;
+ comp_ref_y = curCb - 1;
+
+ for (i = 0; i < 2; i++)
+ {
+ pred_a = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ pred_b = (pred_a >> 8) & 0xFF00FF;
+ pred_a &= 0xFF00FF;
+ pred_a += pred_b;
+ pred_a += (pred_a >> 16);
+ sum_x0 = pred_a & 0xFFFF;
+
+ pred_a = *((uint32*)comp_ref_x);
+ pred_b = (pred_a >> 8) & 0xFF00FF;
+ pred_a &= 0xFF00FF;
+ pred_a += pred_b;
+ pred_a += (pred_a >> 16);
+ sum_x1 = pred_a & 0xFFFF;
+
+ pred_1[i] = (sum_x1 + 2) >> 2;
+
+ sum_y0 = *comp_ref_y;
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+
+ sum_y1 = *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+
+ pred_2[i] = (sum_y1 + 2) >> 2;
+
+ pred_0[i] = (sum_y0 + sum_x0 + 4) >> 3;
+ pred_3[i] = (sum_y1 + sum_x1 + 4) >> 3;
+
+ comp_ref_x = curCr - pitch;
+ comp_ref_y = curCr - 1;
+ }
+ }
+
+ else if (video->intraAvailA)
+ {
+ comp_ref_y = curCb - 1;
+ for (i = 0; i < 2; i++)
+ {
+ sum_y0 = *comp_ref_y;
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+ sum_y0 += *(comp_ref_y += pitch);
+
+ sum_y1 = *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+ sum_y1 += *(comp_ref_y += pitch);
+
+ pred_0[i] = pred_1[i] = (sum_y0 + 2) >> 2;
+ pred_2[i] = pred_3[i] = (sum_y1 + 2) >> 2;
+
+ comp_ref_y = curCr - 1;
+ }
+ }
+ else if (video->intraAvailB)
+ {
+ comp_ref_x = curCb - pitch;
+ for (i = 0; i < 2; i++)
+ {
+ pred_a = *((uint32*)comp_ref_x);
+ comp_ref_x += 4;
+ pred_b = (pred_a >> 8) & 0xFF00FF;
+ pred_a &= 0xFF00FF;
+ pred_a += pred_b;
+ pred_a += (pred_a >> 16);
+ sum_x0 = pred_a & 0xFFFF;
+
+ pred_a = *((uint32*)comp_ref_x);
+ pred_b = (pred_a >> 8) & 0xFF00FF;
+ pred_a &= 0xFF00FF;
+ pred_a += pred_b;
+ pred_a += (pred_a >> 16);
+ sum_x1 = pred_a & 0xFFFF;
+
+ pred_0[i] = pred_2[i] = (sum_x0 + 2) >> 2;
+ pred_1[i] = pred_3[i] = (sum_x1 + 2) >> 2;
+
+ comp_ref_x = curCr - pitch;
+ }
+ }
+ else
+ {
+ pred_0[0] = pred_0[1] = pred_1[0] = pred_1[1] =
+ pred_2[0] = pred_2[1] = pred_3[0] = pred_3[1] = 128;
+ }
+
+ pred = encvid->pred_ic[AVC_IC_DC];
+
+ pred_a = pred_0[0];
+ pred_b = pred_1[0];
+ pred_a |= (pred_a << 8);
+ pred_a |= (pred_a << 16);
+ pred_b |= (pred_b << 8);
+ pred_b |= (pred_b << 16);
+
+ pred_c = pred_0[1];
+ pred_d = pred_1[1];
+ pred_c |= (pred_c << 8);
+ pred_c |= (pred_c << 16);
+ pred_d |= (pred_d << 8);
+ pred_d |= (pred_d << 16);
+
+
+ for (j = 0; j < 4; j++) /* 4 lines */
+ {
+ *((uint32*)pred) = pred_a;
+ *((uint32*)(pred + 4)) = pred_b;
+ *((uint32*)(pred + 8)) = pred_c;
+ *((uint32*)(pred + 12)) = pred_d;
+ pred += 16; /* move to the next line */
+ }
+
+ pred_a = pred_2[0];
+ pred_b = pred_3[0];
+ pred_a |= (pred_a << 8);
+ pred_a |= (pred_a << 16);
+ pred_b |= (pred_b << 8);
+ pred_b |= (pred_b << 16);
+
+ pred_c = pred_2[1];
+ pred_d = pred_3[1];
+ pred_c |= (pred_c << 8);
+ pred_c |= (pred_c << 16);
+ pred_d |= (pred_d << 8);
+ pred_d |= (pred_d << 16);
+
+ for (j = 0; j < 4; j++) /* 4 lines */
+ {
+ *((uint32*)pred) = pred_a;
+ *((uint32*)(pred + 4)) = pred_b;
+ *((uint32*)(pred + 8)) = pred_c;
+ *((uint32*)(pred + 12)) = pred_d;
+ pred += 16; /* move to the next line */
+ }
+
+ /* predict horizontal mode */
+ if (video->intraAvailA)
+ {
+ comp_ref_y = curCb - 1;
+ comp_ref_x = curCr - 1;
+ pred = encvid->pred_ic[AVC_IC_Horizontal];
+
+ for (i = 4; i < 6; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ pred_a = *comp_ref_y;
+ comp_ref_y += pitch;
+ pred_a |= (pred_a << 8);
+ pred_a |= (pred_a << 16);
+ *((uint32*)pred) = pred_a;
+ *((uint32*)(pred + 4)) = pred_a;
+
+ pred_a = *comp_ref_x;
+ comp_ref_x += pitch;
+ pred_a |= (pred_a << 8);
+ pred_a |= (pred_a << 16);
+ *((uint32*)(pred + 8)) = pred_a;
+ *((uint32*)(pred + 12)) = pred_a;
+
+ pred += 16;
+ }
+ }
+ }
+
+ /* vertical mode */
+ if (video->intraAvailB)
+ {
+ comp_ref_x = curCb - pitch;
+ comp_ref_y = curCr - pitch;
+ pred = encvid->pred_ic[AVC_IC_Vertical];
+
+ pred_a = *((uint32*)comp_ref_x);
+ pred_b = *((uint32*)(comp_ref_x + 4));
+ pred_c = *((uint32*)comp_ref_y);
+ pred_d = *((uint32*)(comp_ref_y + 4));
+
+ for (j = 0; j < 8; j++)
+ {
+ *((uint32*)pred) = pred_a;
+ *((uint32*)(pred + 4)) = pred_b;
+ *((uint32*)(pred + 8)) = pred_c;
+ *((uint32*)(pred + 12)) = pred_d;
+ pred += 16;
+ }
+ }
+
+ /* Intra_Chroma_Plane */
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ comp_ref_x = curCb - pitch;
+ comp_ref_y = curCb - 1;
+ topleft = curCb[-pitch-1];
+
+ pred = encvid->pred_ic[AVC_IC_Plane];
+ for (component = 0; component < 2; component++)
+ {
+ H = V = 0;
+ comp_ref_x0 = comp_ref_x + 4;
+ comp_ref_x1 = comp_ref_x + 2;
+ comp_ref_y0 = comp_ref_y + (pitch << 2);
+ comp_ref_y1 = comp_ref_y + (pitch << 1);
+ for (i = 1; i < 4; i++)
+ {
+ H += i * (*comp_ref_x0++ - *comp_ref_x1--);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+ comp_ref_y0 += pitch;
+ comp_ref_y1 -= pitch;
+ }
+ H += i * (*comp_ref_x0++ - topleft);
+ V += i * (*comp_ref_y0 - *comp_ref_y1);
+
+ a_16 = ((*(comp_ref_x + 7) + *(comp_ref_y + 7 * pitch)) << 4) + 16;
+ b = (17 * H + 16) >> 5;
+ c = (17 * V + 16) >> 5;
+
+ pred_a = 0;
+ for (i = 4; i < 6; i++)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ factor_c = a_16 + c * (pred_a++ - 3);
+
+ factor_c -= 3 * b;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b |= (value << 8);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b |= (value << 16);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b |= (value << 24);
+ *((uint32*)pred) = pred_b;
+
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b = value;
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b |= (value << 8);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b |= (value << 16);
+ value = factor_c >> 5;
+ factor_c += b;
+ CLIP_RESULT(value)
+ pred_b |= (value << 24);
+ *((uint32*)(pred + 4)) = pred_b;
+ pred += 16;
+ }
+ }
+
+ pred -= 120; /* point to cr */
+ comp_ref_x = curCr - pitch;
+ comp_ref_y = curCr - 1;
+ topleft = curCr[-pitch-1];
+ }
+ }
+
+ /* now evaluate it */
+
+ org_pitch = (currInput->pitch) >> 1;
+ offset = x_pos + y_pos * org_pitch;
+
+ orgCb = currInput->YCbCr[1] + offset;
+ orgCr = currInput->YCbCr[2] + offset;
+
+ mincost = 0x7fffffff;
+ cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_DC], mincost);
+ if (cost < mincost)
+ {
+ mincost = cost;
+ currMB->intra_chroma_pred_mode = AVC_IC_DC;
+ }
+
+ if (video->intraAvailA)
+ {
+ cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_Horizontal], mincost);
+ if (cost < mincost)
+ {
+ mincost = cost;
+ currMB->intra_chroma_pred_mode = AVC_IC_Horizontal;
+ }
+ }
+
+ if (video->intraAvailB)
+ {
+ cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_Vertical], mincost);
+ if (cost < mincost)
+ {
+ mincost = cost;
+ currMB->intra_chroma_pred_mode = AVC_IC_Vertical;
+ }
+ }
+
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ cost = SATDChroma(orgCb, orgCr, org_pitch, encvid->pred_ic[AVC_IC_Plane], mincost);
+ if (cost < mincost)
+ {
+ mincost = cost;
+ currMB->intra_chroma_pred_mode = AVC_IC_Plane;
+ }
+ }
+
+
+ return ;
+}
+
+
+int SATDChroma(uint8 *orgCb, uint8 *orgCr, int org_pitch, uint8 *pred, int min_cost)
+{
+ int cost;
+ /* first take difference between orgCb, orgCr and pred */
+ int16 res[128], *pres; // residue
+ int m0, m1, m2, m3, tmp1;
+ int j, k;
+
+ pres = res;
+ org_pitch -= 8;
+ // horizontal transform
+ for (j = 0; j < 8; j++)
+ {
+ k = 2;
+ while (k > 0)
+ {
+ m0 = orgCb[0] - pred[0];
+ m3 = orgCb[3] - pred[3];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = orgCb[1] - pred[1];
+ m2 = orgCb[2] - pred[2];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 + m1;
+ pres[2] = m0 - m1;
+ pres[1] = m2 + m3;
+ pres[3] = m3 - m2;
+
+ orgCb += 4;
+ pres += 4;
+ pred += 4;
+ k--;
+ }
+ orgCb += org_pitch;
+ k = 2;
+ while (k > 0)
+ {
+ m0 = orgCr[0] - pred[0];
+ m3 = orgCr[3] - pred[3];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = orgCr[1] - pred[1];
+ m2 = orgCr[2] - pred[2];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 + m1;
+ pres[2] = m0 - m1;
+ pres[1] = m2 + m3;
+ pres[3] = m3 - m2;
+
+ orgCr += 4;
+ pres += 4;
+ pred += 4;
+ k--;
+ }
+ orgCr += org_pitch;
+ }
+
+ /* vertical transform */
+ for (j = 0; j < 2; j++)
+ {
+ pres = res + (j << 6);
+ k = 16;
+ while (k > 0)
+ {
+ m0 = pres[0];
+ m3 = pres[3<<4];
+ m0 += m3;
+ m3 = m0 - (m3 << 1);
+ m1 = pres[1<<4];
+ m2 = pres[2<<4];
+ m1 += m2;
+ m2 = m1 - (m2 << 1);
+ pres[0] = m0 + m1;
+ pres[2<<4] = m0 - m1;
+ pres[1<<4] = m2 + m3;
+ pres[3<<4] = m3 - m2;
+
+ pres++;
+ k--;
+ }
+ }
+
+ /* now sum of absolute value */
+ pres = res;
+ cost = 0;
+ k = 128;
+ while (k > 0)
+ {
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ tmp1 = *pres++;
+ cost += ((tmp1 >= 0) ? tmp1 : -tmp1);
+ k -= 8;
+ if (cost > min_cost) /* early drop out */
+ {
+ return cost;
+ }
+ }
+
+ return cost;
+}
+
+
+
+///////////////////////////////// old code, unused
+/* find the best intra mode based on original (unencoded) frame */
+/* output is
+ currMB->mb_intra, currMB->mbMode,
+ currMB->i16Mode (if currMB->mbMode == AVC_I16)
+ currMB->i4Mode[..] (if currMB->mbMode == AVC_I4) */
+
+#ifdef FIXED_INTRAPRED_MODE
+void MBIntraSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum)
+{
+ (void)(mbNum);
+
+ AVCCommonObj *video = encvid->common;
+ int indx, block_x, block_y;
+
+ video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+
+ if (!video->currPicParams->constrained_intra_pred_flag)
+ {
+ video->intraAvailA = video->mbAvailA;
+ video->intraAvailB = video->mbAvailB;
+ video->intraAvailC = video->mbAvailC;
+ video->intraAvailD = video->mbAvailD;
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+ }
+ if (video->mbAvailB)
+ {
+ video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+ }
+ if (video->mbAvailC)
+ {
+ video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+ }
+ if (video->mbAvailD)
+ {
+ video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+ }
+ }
+
+ currMB->mb_intra = TRUE;
+ currMB->mbMode = FIXED_INTRAPRED_MODE;
+
+ if (currMB->mbMode == AVC_I16)
+ {
+ currMB->i16Mode = FIXED_I16_MODE;
+
+ if (FIXED_I16_MODE == AVC_I16_Vertical && !video->intraAvailB)
+ {
+ currMB->i16Mode = AVC_I16_DC;
+ }
+
+ if (FIXED_I16_MODE == AVC_I16_Horizontal && !video->intraAvailA)
+ {
+ currMB->i16Mode = AVC_I16_DC;
+ }
+
+ if (FIXED_I16_MODE == AVC_I16_Plane && !(video->intraAvailA && video->intraAvailB && video->intraAvailD))
+ {
+ currMB->i16Mode = AVC_I16_DC;
+ }
+ }
+ else //if(currMB->mbMode == AVC_I4)
+ {
+ for (indx = 0; indx < 16; indx++)
+ {
+ block_x = blkIdx2blkX[indx];
+ block_y = blkIdx2blkY[indx];
+
+ currMB->i4Mode[(block_y<<2)+block_x] = FIXED_I4_MODE;
+
+ if (FIXED_I4_MODE == AVC_I4_Vertical && !(block_y > 0 || video->intraAvailB))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Horizontal && !(block_x || video->intraAvailA))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Diagonal_Down_Left &&
+ (block_y == 0 && !video->intraAvailB))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Diagonal_Down_Right &&
+ !((block_y && block_x)
+ || (block_y && video->intraAvailA)
+ || (block_x && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB)))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Vertical_Right &&
+ !((block_y && block_x)
+ || (block_y && video->intraAvailA)
+ || (block_x && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB)))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Horizontal_Down &&
+ !((block_y && block_x)
+ || (block_y && video->intraAvailA)
+ || (block_x && video->intraAvailB)
+ || (video->intraAvailA && video->intraAvailD && video->intraAvailB)))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Vertical_Left &&
+ (block_y == 0 && !video->intraAvailB))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+
+ if (FIXED_I4_MODE == AVC_I4_Horizontal_Up && !(block_x || video->intraAvailA))
+ {
+ currMB->i4Mode[(block_y<<2)+block_x] = AVC_I4_DC;
+ }
+ }
+ }
+
+ currMB->intra_chroma_pred_mode = FIXED_INTRA_CHROMA_MODE;
+
+ if (FIXED_INTRA_CHROMA_MODE == AVC_IC_Horizontal && !(video->intraAvailA))
+ {
+ currMB->intra_chroma_pred_mode = AVC_IC_DC;
+ }
+
+ if (FIXED_INTRA_CHROMA_MODE == AVC_IC_Vertical && !(video->intraAvailB))
+ {
+ currMB->intra_chroma_pred_mode = AVC_IC_DC;
+ }
+
+ if (FIXED_INTRA_CHROMA_MODE == AVC_IC_Plane && !(video->intraAvailA && video->intraAvailB && video->intraAvailD))
+ {
+ currMB->intra_chroma_pred_mode = AVC_IC_DC;
+ }
+
+ /* also reset the motion vectors */
+ /* set MV and Ref_Idx codes of Intra blocks in P-slices */
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ currMB->ref_idx_L0[0] = -1;
+ currMB->ref_idx_L0[1] = -1;
+ currMB->ref_idx_L0[2] = -1;
+ currMB->ref_idx_L0[3] = -1;
+
+ // output from this function, currMB->mbMode should be set to either
+ // AVC_I4, AVC_I16, or else in AVCMBMode enum, mbType, mb_intra, intra_chroma_pred_mode */
+ return ;
+}
+#else // faster combined prediction+SAD calculation
+void MBIntraSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCFrameIO *currInput = encvid->currInput;
+ uint8 *curL, *curCb, *curCr;
+ uint8 *comp, *pred_block;
+ int block_x, block_y, offset;
+ uint sad, sad4, sadI4, sadI16;
+ int component, SubBlock_indx, temp;
+ int pitch = video->currPic->pitch;
+
+ /* calculate the cost of each intra prediction mode and compare to the
+ inter mode */
+ /* full search for all intra prediction */
+ offset = (video->mb_y << 4) * pitch + (video->mb_x << 4);
+ curL = currInput->YCbCr[0] + offset;
+ pred_block = video->pred_block + 84;
+
+ /* Assuming that InitNeighborAvailability has been called prior to this function */
+ video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+
+ if (!video->currPicParams->constrained_intra_pred_flag)
+ {
+ video->intraAvailA = video->mbAvailA;
+ video->intraAvailB = video->mbAvailB;
+ video->intraAvailC = video->mbAvailC;
+ video->intraAvailD = video->mbAvailD;
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+ }
+ if (video->mbAvailB)
+ {
+ video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+ }
+ if (video->mbAvailC)
+ {
+ video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+ }
+ if (video->mbAvailD)
+ {
+ video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+ }
+ }
+
+ /* currently we're doing exhaustive search. Smart search will be used later */
+
+ /* I16 modes */
+ curL = currInput->YCbCr[0] + offset;
+ video->pintra_pred_top = curL - pitch;
+ video->pintra_pred_left = curL - 1;
+ if (video->mb_y)
+ {
+ video->intra_pred_topleft = *(curL - pitch - 1);
+ }
+
+ /* Intra_16x16_Vertical */
+ sadI16 = 65536;
+ /* check availability of top */
+ if (video->intraAvailB)
+ {
+ sad = SAD_I16_Vert(video, curL, sadI16);
+
+ if (sad < sadI16)
+ {
+ sadI16 = sad;
+ currMB->i16Mode = AVC_I16_Vertical;
+ }
+ }
+ /* Intra_16x16_Horizontal */
+ /* check availability of left */
+ if (video->intraAvailA)
+ {
+ sad = SAD_I16_HorzDC(video, curL, AVC_I16_Horizontal, sadI16);
+
+ if (sad < sadI16)
+ {
+ sadI16 = sad;
+ currMB->i16Mode = AVC_I16_Horizontal;
+ }
+ }
+
+ /* Intra_16x16_DC, default mode */
+ sad = SAD_I16_HorzDC(video, curL, AVC_I16_DC, sadI16);
+ if (sad < sadI16)
+ {
+ sadI16 = sad;
+ currMB->i16Mode = AVC_I16_DC;
+ }
+
+ /* Intra_16x16_Plane */
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ sad = SAD_I16_Plane(video, curL, sadI16);
+
+ if (sad < sadI16)
+ {
+ sadI16 = sad;
+ currMB->i16Mode = AVC_I16_Plane;
+ }
+ }
+
+ sadI16 >>= 1; /* before comparison */
+
+ /* selection between intra4, intra16 or inter mode */
+ if (sadI16 < encvid->min_cost)
+ {
+ currMB->mb_intra = TRUE;
+ currMB->mbMode = AVC_I16;
+ encvid->min_cost = sadI16;
+ }
+
+ if (currMB->mb_intra) /* only do the chrominance search when intra is decided */
+ {
+ /* Note that we might be able to guess the type of prediction from
+ the luma prediction type */
+
+ /* now search for the best chroma intra prediction */
+ offset = (offset >> 2) + (video->mb_x << 2);
+ curCb = currInput->YCbCr[1] + offset;
+ curCr = currInput->YCbCr[2] + offset;
+
+ pitch >>= 1;
+ video->pintra_pred_top_cb = curCb - pitch;
+ video->pintra_pred_left_cb = curCb - 1;
+ video->pintra_pred_top_cr = curCr - pitch;
+ video->pintra_pred_left_cr = curCr - 1;
+
+ if (video->mb_y)
+ {
+ video->intra_pred_topleft_cb = *(curCb - pitch - 1);
+ video->intra_pred_topleft_cr = *(curCr - pitch - 1);
+ }
+
+ /* Intra_Chroma_DC */
+ sad4 = SAD_Chroma_DC(video, curCb, curCr, 65536);
+ currMB->intra_chroma_pred_mode = AVC_IC_DC;
+
+ /* Intra_Chroma_Horizontal */
+ if (video->intraAvailA)
+ {
+ /* check availability of left */
+ sad = SAD_Chroma_Horz(video, curCb, curCr, sad4);
+ if (sad < sad4)
+ {
+ sad4 = sad;
+ currMB->intra_chroma_pred_mode = AVC_IC_Horizontal;
+ }
+ }
+
+ /* Intra_Chroma_Vertical */
+ if (video->intraAvailB)
+ {
+ /* check availability of top */
+ sad = SAD_Chroma_Vert(video, curCb, curCr, sad4);
+
+ if (sad < sad4)
+ {
+ sad4 = sad;
+ currMB->intra_chroma_pred_mode = AVC_IC_Vertical;
+ }
+ }
+
+ /* Intra_Chroma_Plane */
+ if (video->intraAvailA && video->intraAvailB && video->intraAvailD)
+ {
+ /* check availability of top and left */
+ Intra_Chroma_Plane(video, pitch);
+
+ sad = SADChroma(pred_block + 452, curCb, curCr, pitch);
+
+ if (sad < sad4)
+ {
+ sad4 = sad;
+ currMB->intra_chroma_pred_mode = AVC_IC_Plane;
+ }
+ }
+
+ /* also reset the motion vectors */
+ /* set MV and Ref_Idx codes of Intra blocks in P-slices */
+ memset(currMB->mvL0, 0, sizeof(int32)*16);
+ memset(currMB->ref_idx_L0, -1, sizeof(int16)*4);
+
+ }
+
+ // output from this function, currMB->mbMode should be set to either
+ // AVC_I4, AVC_I16, or else in AVCMBMode enum, mbType, mb_intra, intra_chroma_pred_mode */
+
+ return ;
+}
+#endif
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/motion_comp.cpp b/media/libstagefright/codecs/avc/enc/src/motion_comp.cpp
new file mode 100644
index 0000000..ac62d78
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/motion_comp.cpp
@@ -0,0 +1,2156 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "avcenc_int.h"
+
+
+#define CLIP_RESULT(x) if((uint)x > 0xFF){ \
+ x = 0xFF & (~(x>>31));}
+
+/* (blkwidth << 2) + (dy << 1) + dx */
+static void (*const eChromaMC_SIMD[8])(uint8 *, int , int , int , uint8 *, int, int , int) =
+{
+ &eChromaFullMC_SIMD,
+ &eChromaHorizontalMC_SIMD,
+ &eChromaVerticalMC_SIMD,
+ &eChromaDiagonalMC_SIMD,
+ &eChromaFullMC_SIMD,
+ &eChromaHorizontalMC2_SIMD,
+ &eChromaVerticalMC2_SIMD,
+ &eChromaDiagonalMC2_SIMD
+};
+/* Perform motion prediction and compensation with residue if exist. */
+void AVCMBMotionComp(AVCEncObject *encvid, AVCCommonObj *video)
+{
+ (void)(encvid);
+
+ AVCMacroblock *currMB = video->currMB;
+ AVCPictureData *currPic = video->currPic;
+ int mbPartIdx, subMbPartIdx;
+ int ref_idx;
+ int offset_MbPart_indx = 0;
+ int16 *mv;
+ uint32 x_pos, y_pos;
+ uint8 *curL, *curCb, *curCr;
+ uint8 *ref_l, *ref_Cb, *ref_Cr;
+ uint8 *predBlock, *predCb, *predCr;
+ int block_x, block_y, offset_x, offset_y, offsetP, offset;
+ int x_position = (video->mb_x << 4);
+ int y_position = (video->mb_y << 4);
+ int MbHeight, MbWidth, mbPartIdx_X, mbPartIdx_Y, offset_indx;
+ int picWidth = currPic->width;
+ int picPitch = currPic->pitch;
+ int picHeight = currPic->height;
+ uint32 tmp_word;
+
+ tmp_word = y_position * picPitch;
+ curL = currPic->Sl + tmp_word + x_position;
+ offset = (tmp_word >> 2) + (x_position >> 1);
+ curCb = currPic->Scb + offset;
+ curCr = currPic->Scr + offset;
+
+ predBlock = curL;
+ predCb = curCb;
+ predCr = curCr;
+
+ GetMotionVectorPredictor(video, 1);
+
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ MbHeight = currMB->SubMbPartHeight[mbPartIdx];
+ MbWidth = currMB->SubMbPartWidth[mbPartIdx];
+ mbPartIdx_X = ((mbPartIdx + offset_MbPart_indx) & 1);
+ mbPartIdx_Y = (mbPartIdx + offset_MbPart_indx) >> 1;
+ ref_idx = currMB->ref_idx_L0[(mbPartIdx_Y << 1) + mbPartIdx_X];
+ offset_indx = 0;
+
+ ref_l = video->RefPicList0[ref_idx]->Sl;
+ ref_Cb = video->RefPicList0[ref_idx]->Scb;
+ ref_Cr = video->RefPicList0[ref_idx]->Scr;
+
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ block_x = (mbPartIdx_X << 1) + ((subMbPartIdx + offset_indx) & 1);
+ block_y = (mbPartIdx_Y << 1) + (((subMbPartIdx + offset_indx) >> 1) & 1);
+ mv = (int16*)(currMB->mvL0 + block_x + (block_y << 2));
+ offset_x = x_position + (block_x << 2);
+ offset_y = y_position + (block_y << 2);
+ x_pos = (offset_x << 2) + *mv++; /*quarter pel */
+ y_pos = (offset_y << 2) + *mv; /*quarter pel */
+
+ //offset = offset_y * currPic->width;
+ //offsetC = (offset >> 2) + (offset_x >> 1);
+ offsetP = (block_y << 2) * picPitch + (block_x << 2);
+ eLumaMotionComp(ref_l, picPitch, picHeight, x_pos, y_pos,
+ /*comp_Sl + offset + offset_x,*/
+ predBlock + offsetP, picPitch, MbWidth, MbHeight);
+
+ offsetP = (block_y * picWidth) + (block_x << 1);
+ eChromaMotionComp(ref_Cb, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+ /*comp_Scb + offsetC,*/
+ predCb + offsetP, picPitch >> 1, MbWidth >> 1, MbHeight >> 1);
+ eChromaMotionComp(ref_Cr, picWidth >> 1, picHeight >> 1, x_pos, y_pos,
+ /*comp_Scr + offsetC,*/
+ predCr + offsetP, picPitch >> 1, MbWidth >> 1, MbHeight >> 1);
+
+ offset_indx = currMB->SubMbPartWidth[mbPartIdx] >> 3;
+ }
+ offset_MbPart_indx = currMB->MbPartWidth >> 4;
+ }
+
+ return ;
+}
+
+
+/* preform the actual motion comp here */
+void eLumaMotionComp(uint8 *ref, int picpitch, int picheight,
+ int x_pos, int y_pos,
+ uint8 *pred, int pred_pitch,
+ int blkwidth, int blkheight)
+{
+ (void)(picheight);
+
+ int dx, dy;
+ int temp2[21][21]; /* for intermediate results */
+ uint8 *ref2;
+
+ dx = x_pos & 3;
+ dy = y_pos & 3;
+ x_pos = x_pos >> 2; /* round it to full-pel resolution */
+ y_pos = y_pos >> 2;
+
+ /* perform actual motion compensation */
+ if (dx == 0 && dy == 0)
+ { /* fullpel position *//* G */
+
+ ref += y_pos * picpitch + x_pos;
+
+ eFullPelMC(ref, picpitch, pred, pred_pitch, blkwidth, blkheight);
+
+ } /* other positions */
+ else if (dy == 0)
+ { /* no vertical interpolation *//* a,b,c*/
+
+ ref += y_pos * picpitch + x_pos;
+
+ eHorzInterp1MC(ref, picpitch, pred, pred_pitch, blkwidth, blkheight, dx);
+ }
+ else if (dx == 0)
+ { /*no horizontal interpolation *//* d,h,n */
+
+ ref += y_pos * picpitch + x_pos;
+
+ eVertInterp1MC(ref, picpitch, pred, pred_pitch, blkwidth, blkheight, dy);
+ }
+ else if (dy == 2)
+ { /* horizontal cross *//* i, j, k */
+
+ ref += y_pos * picpitch + x_pos - 2; /* move to the left 2 pixels */
+
+ eVertInterp2MC(ref, picpitch, &temp2[0][0], 21, blkwidth + 5, blkheight);
+
+ eHorzInterp2MC(&temp2[0][2], 21, pred, pred_pitch, blkwidth, blkheight, dx);
+ }
+ else if (dx == 2)
+ { /* vertical cross */ /* f,q */
+
+ ref += (y_pos - 2) * picpitch + x_pos; /* move to up 2 lines */
+
+ eHorzInterp3MC(ref, picpitch, &temp2[0][0], 21, blkwidth, blkheight + 5);
+ eVertInterp3MC(&temp2[2][0], 21, pred, pred_pitch, blkwidth, blkheight, dy);
+ }
+ else
+ { /* diagonal *//* e,g,p,r */
+
+ ref2 = ref + (y_pos + (dy / 2)) * picpitch + x_pos;
+
+ ref += (y_pos * picpitch) + x_pos + (dx / 2);
+
+ eDiagonalInterpMC(ref2, ref, picpitch, pred, pred_pitch, blkwidth, blkheight);
+ }
+
+ return ;
+}
+
+void eCreateAlign(uint8 *ref, int picpitch, int y_pos,
+ uint8 *out, int blkwidth, int blkheight)
+{
+ int i, j;
+ int offset, out_offset;
+ uint32 prev_pix, result, pix1, pix2, pix4;
+
+ ref += y_pos * picpitch;// + x_pos;
+ out_offset = 24 - blkwidth;
+
+ //switch(x_pos&0x3){
+ switch (((uint32)ref)&0x3)
+ {
+ case 1:
+ offset = picpitch - blkwidth - 3;
+ for (j = 0; j < blkheight; j++)
+ {
+ pix1 = *ref++;
+ pix2 = *((uint16*)ref);
+ ref += 2;
+ result = (pix2 << 8) | pix1;
+
+ for (i = 3; i < blkwidth; i += 4)
+ {
+ pix4 = *((uint32*)ref);
+ ref += 4;
+ prev_pix = (pix4 << 24) & 0xFF000000; /* mask out byte belong to previous word */
+ result |= prev_pix;
+ *((uint32*)out) = result; /* write 4 bytes */
+ out += 4;
+ result = pix4 >> 8; /* for the next loop */
+ }
+ ref += offset;
+ out += out_offset;
+ }
+ break;
+ case 2:
+ offset = picpitch - blkwidth - 2;
+ for (j = 0; j < blkheight; j++)
+ {
+ result = *((uint16*)ref);
+ ref += 2;
+ for (i = 2; i < blkwidth; i += 4)
+ {
+ pix4 = *((uint32*)ref);
+ ref += 4;
+ prev_pix = (pix4 << 16) & 0xFFFF0000; /* mask out byte belong to previous word */
+ result |= prev_pix;
+ *((uint32*)out) = result; /* write 4 bytes */
+ out += 4;
+ result = pix4 >> 16; /* for the next loop */
+ }
+ ref += offset;
+ out += out_offset;
+ }
+ break;
+ case 3:
+ offset = picpitch - blkwidth - 1;
+ for (j = 0; j < blkheight; j++)
+ {
+ result = *ref++;
+ for (i = 1; i < blkwidth; i += 4)
+ {
+ pix4 = *((uint32*)ref);
+ ref += 4;
+ prev_pix = (pix4 << 8) & 0xFFFFFF00; /* mask out byte belong to previous word */
+ result |= prev_pix;
+ *((uint32*)out) = result; /* write 4 bytes */
+ out += 4;
+ result = pix4 >> 24; /* for the next loop */
+ }
+ ref += offset;
+ out += out_offset;
+ }
+ break;
+ }
+}
+
+void eHorzInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx)
+{
+ uint8 *p_ref;
+ uint32 *p_cur;
+ uint32 tmp, pkres;
+ int result, curr_offset, ref_offset;
+ int j;
+ int32 r0, r1, r2, r3, r4, r5;
+ int32 r13, r6;
+
+ p_cur = (uint32*)out; /* assume it's word aligned */
+ curr_offset = (outpitch - blkwidth) >> 2;
+ p_ref = in;
+ ref_offset = inpitch - blkwidth;
+
+ if (dx&1)
+ {
+ dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
+ p_ref -= 2;
+ r13 = 0;
+ for (j = blkheight; j > 0; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ r0 = p_ref[0];
+ r1 = p_ref[2];
+ r0 |= (r1 << 16); /* 0,c,0,a */
+ r1 = p_ref[1];
+ r2 = p_ref[3];
+ r1 |= (r2 << 16); /* 0,d,0,b */
+ while ((uint32)p_ref < tmp)
+ {
+ r2 = *(p_ref += 4); /* move pointer to e */
+ r3 = p_ref[2];
+ r2 |= (r3 << 16); /* 0,g,0,e */
+ r3 = p_ref[1];
+ r4 = p_ref[3];
+ r3 |= (r4 << 16); /* 0,h,0,f */
+
+ r4 = r0 + r3; /* c+h, a+f */
+ r5 = r0 + r1; /* c+d, a+b */
+ r6 = r2 + r3; /* g+h, e+f */
+ r5 >>= 16;
+ r5 |= (r6 << 16); /* e+f, c+d */
+ r4 += r5 * 20; /* c+20*e+20*f+h, a+20*c+20*d+f */
+ r4 += 0x100010; /* +16, +16 */
+ r5 = r1 + r2; /* d+g, b+e */
+ r4 -= r5 * 5; /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+ r4 >>= 5;
+ r13 |= r4; /* check clipping */
+
+ r5 = p_ref[dx+2];
+ r6 = p_ref[dx+4];
+ r5 |= (r6 << 16);
+ r4 += r5;
+ r4 += 0x10001;
+ r4 = (r4 >> 1) & 0xFF00FF;
+
+ r5 = p_ref[4]; /* i */
+ r6 = (r5 << 16);
+ r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+ r5 += r1; /* d+i, b+g */ /* r5 not free */
+ r1 >>= 16;
+ r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+ r1 += r2; /* f+g, d+e */
+ r5 += 20 * r1; /* d+20f+20g+i, b+20d+20e+g */
+ r0 >>= 16;
+ r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+ r0 += r3; /* e+h, c+f */
+ r5 += 0x100010; /* 16,16 */
+ r5 -= r0 * 5; /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+ r5 >>= 5;
+ r13 |= r5; /* check clipping */
+
+ r0 = p_ref[dx+3];
+ r1 = p_ref[dx+5];
+ r0 |= (r1 << 16);
+ r5 += r0;
+ r5 += 0x10001;
+ r5 = (r5 >> 1) & 0xFF00FF;
+
+ r4 |= (r5 << 8); /* pack them together */
+ *p_cur++ = r4;
+ r1 = r3;
+ r0 = r2;
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+
+ if (r13&0xFF000700) /* need clipping */
+ {
+ /* move back to the beginning of the line */
+ p_ref -= (ref_offset + blkwidth); /* input */
+ p_cur -= (outpitch >> 2);
+
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = *p_ref++;
+ r1 = *p_ref++;
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ pkres = (result >> 1) ;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ result = (result >> 1);
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ result = (result >> 1);
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dx] + 1);
+ result = (result >> 1);
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 5; /* offset back to the middle of filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* move to the next line */
+ }
+ }
+ }
+ else
+ {
+ p_ref -= 2;
+ r13 = 0;
+ for (j = blkheight; j > 0; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ r0 = p_ref[0];
+ r1 = p_ref[2];
+ r0 |= (r1 << 16); /* 0,c,0,a */
+ r1 = p_ref[1];
+ r2 = p_ref[3];
+ r1 |= (r2 << 16); /* 0,d,0,b */
+ while ((uint32)p_ref < tmp)
+ {
+ r2 = *(p_ref += 4); /* move pointer to e */
+ r3 = p_ref[2];
+ r2 |= (r3 << 16); /* 0,g,0,e */
+ r3 = p_ref[1];
+ r4 = p_ref[3];
+ r3 |= (r4 << 16); /* 0,h,0,f */
+
+ r4 = r0 + r3; /* c+h, a+f */
+ r5 = r0 + r1; /* c+d, a+b */
+ r6 = r2 + r3; /* g+h, e+f */
+ r5 >>= 16;
+ r5 |= (r6 << 16); /* e+f, c+d */
+ r4 += r5 * 20; /* c+20*e+20*f+h, a+20*c+20*d+f */
+ r4 += 0x100010; /* +16, +16 */
+ r5 = r1 + r2; /* d+g, b+e */
+ r4 -= r5 * 5; /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+ r4 >>= 5;
+ r13 |= r4; /* check clipping */
+ r4 &= 0xFF00FF; /* mask */
+
+ r5 = p_ref[4]; /* i */
+ r6 = (r5 << 16);
+ r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+ r5 += r1; /* d+i, b+g */ /* r5 not free */
+ r1 >>= 16;
+ r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+ r1 += r2; /* f+g, d+e */
+ r5 += 20 * r1; /* d+20f+20g+i, b+20d+20e+g */
+ r0 >>= 16;
+ r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+ r0 += r3; /* e+h, c+f */
+ r5 += 0x100010; /* 16,16 */
+ r5 -= r0 * 5; /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+ r5 >>= 5;
+ r13 |= r5; /* check clipping */
+ r5 &= 0xFF00FF; /* mask */
+
+ r4 |= (r5 << 8); /* pack them together */
+ *p_cur++ = r4;
+ r1 = r3;
+ r0 = r2;
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+
+ if (r13&0xFF000700) /* need clipping */
+ {
+ /* move back to the beginning of the line */
+ p_ref -= (ref_offset + blkwidth); /* input */
+ p_cur -= (outpitch >> 2);
+
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = *p_ref++;
+ r1 = *p_ref++;
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 5;
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset;
+ }
+ }
+ }
+
+ return ;
+}
+
+void eHorzInterp2MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dx)
+{
+ int *p_ref;
+ uint32 *p_cur;
+ uint32 tmp, pkres;
+ int result, result2, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = (uint32*)out; /* assume it's word aligned */
+ curr_offset = (outpitch - blkwidth) >> 2;
+ p_ref = in;
+ ref_offset = inpitch - blkwidth;
+
+ if (dx&1)
+ {
+ dx = ((dx >> 1) ? -3 : -4); /* use in 3/4 pel */
+
+ for (j = blkheight; j > 0 ; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = p_ref[-2];
+ r1 = p_ref[-1];
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ pkres = (result >> 1);
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dx] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 3; /* offset back to the middle of filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* move to the next line */
+ }
+ }
+ else
+ {
+ for (j = blkheight; j > 0 ; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = p_ref[-2];
+ r1 = p_ref[-1];
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ pkres |= (result << 24);
+ *p_cur++ = pkres; /* write 4 pixels */
+ p_ref -= 3; /* offset back to the middle of filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset; /* move to the next line */
+ }
+ }
+
+ return ;
+}
+
+void eHorzInterp3MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ uint8 *p_ref;
+ int *p_cur;
+ uint32 tmp;
+ int result, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = out;
+ curr_offset = (outpitch - blkwidth);
+ p_ref = in;
+ ref_offset = inpitch - blkwidth;
+
+ for (j = blkheight; j > 0 ; j--)
+ {
+ tmp = (uint32)(p_ref + blkwidth);
+ for (; (uint32)p_ref < tmp;)
+ {
+
+ r0 = p_ref[-2];
+ r1 = p_ref[-1];
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ *p_cur++ = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ *p_cur++ = result;
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ *p_cur++ = result;
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ *p_cur++ = result;
+ p_ref -= 3; /* move back to the middle of the filter */
+ }
+ p_cur += curr_offset; /* move to the next line */
+ p_ref += ref_offset;
+ }
+
+ return ;
+}
+void eVertInterp1MC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy)
+{
+ uint8 *p_cur, *p_ref;
+ uint32 tmp;
+ int result, curr_offset, ref_offset;
+ int j, i;
+ int32 r0, r1, r2, r3, r4, r5, r6, r7, r8, r13;
+ uint8 tmp_in[24][24];
+
+ /* not word-aligned */
+ if (((uint32)in)&0x3)
+ {
+ eCreateAlign(in, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
+ in = &tmp_in[2][0];
+ inpitch = 24;
+ }
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+ ref_offset = blkheight * inpitch; /* for limit */
+
+ curr_offset += 3;
+
+ if (dy&1)
+ {
+ dy = (dy >> 1) ? 0 : -inpitch;
+
+ for (j = 0; j < blkwidth; j += 4, in += 4)
+ {
+ r13 = 0;
+ p_ref = in;
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+ p_ref += inpitch;
+ r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+ r0 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + (inpitch << 1))); /* r1, r7, ref[3] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+
+ r0 += r1;
+ r6 += r7;
+
+ r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 += 20 * r1;
+ r6 += 20 * r7;
+ r0 += 0x100010;
+ r6 += 0x100010;
+
+ r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 -= 5 * r1;
+ r6 -= 5 * r7;
+
+ r0 >>= 5;
+ r6 >>= 5;
+ /* clip */
+ r13 |= r6;
+ r13 |= r0;
+ //CLIPPACK(r6,result)
+
+ r1 = *((uint32*)(p_ref + dy));
+ r2 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r0 += r1;
+ r6 += r2;
+ r0 += 0x10001;
+ r6 += 0x10001;
+ r0 = (r0 >> 1) & 0xFF00FF;
+ r6 = (r6 >> 1) & 0xFF00FF;
+
+ r0 |= (r6 << 8); /* pack it back */
+ *((uint32*)(p_cur += outpitch)) = r0;
+ }
+ p_cur += curr_offset; /* offset to the next pixel */
+ if (r13 & 0xFF000700) /* this column need clipping */
+ {
+ p_cur -= 4;
+ for (i = 0; i < 4; i++)
+ {
+ p_ref = in + i;
+ p_cur -= outpitch; /* compensate for the first offset */
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ /* 3/4 pel, no need to clip */
+ result = (result + p_ref[dy-(inpitch<<1)] + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += (curr_offset - 3);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (j = 0; j < blkwidth; j += 4, in += 4)
+ {
+ r13 = 0;
+ p_ref = in;
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+ p_ref += inpitch;
+ r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+ r0 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + (inpitch << 1))); /* r1, r7, ref[3] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+
+ r0 += r1;
+ r6 += r7;
+
+ r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 += 20 * r1;
+ r6 += 20 * r7;
+ r0 += 0x100010;
+ r6 += 0x100010;
+
+ r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 -= 5 * r1;
+ r6 -= 5 * r7;
+
+ r0 >>= 5;
+ r6 >>= 5;
+ /* clip */
+ r13 |= r6;
+ r13 |= r0;
+ //CLIPPACK(r6,result)
+ r0 &= 0xFF00FF;
+ r6 &= 0xFF00FF;
+ r0 |= (r6 << 8); /* pack it back */
+ *((uint32*)(p_cur += outpitch)) = r0;
+ }
+ p_cur += curr_offset; /* offset to the next pixel */
+ if (r13 & 0xFF000700) /* this column need clipping */
+ {
+ p_cur -= 4;
+ for (i = 0; i < 4; i++)
+ {
+ p_ref = in + i;
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += (curr_offset - 3);
+ }
+ }
+ }
+ }
+
+ return ;
+}
+
+void eVertInterp2MC(uint8 *in, int inpitch, int *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ int *p_cur;
+ uint8 *p_ref;
+ uint32 tmp;
+ int result, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+ ref_offset = blkheight * inpitch; /* for limit */
+
+ for (j = 0; j < blkwidth; j++)
+ {
+ p_cur -= outpitch; /* compensate for the first offset */
+ p_ref = in++;
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += curr_offset;
+ }
+
+ return ;
+}
+
+void eVertInterp3MC(int *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight, int dy)
+{
+ uint8 *p_cur;
+ int *p_ref;
+ uint32 tmp;
+ int result, result2, curr_offset, ref_offset;
+ int j, r0, r1, r2, r3, r4, r5;
+
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically back up and one pixel to right */
+ ref_offset = blkheight * inpitch; /* for limit */
+
+ if (dy&1)
+ {
+ dy = (dy >> 1) ? -(inpitch << 1) : -(inpitch << 1) - inpitch;
+
+ for (j = 0; j < blkwidth; j++)
+ {
+ p_cur -= outpitch; /* compensate for the first offset */
+ p_ref = in++;
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ result2 = ((p_ref[dy] + 16) >> 5);
+ CLIP_RESULT(result2)
+ /* 3/4 pel, no need to clip */
+ result = (result + result2 + 1);
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += curr_offset;
+ }
+ }
+ else
+ {
+ for (j = 0; j < blkwidth; j++)
+ {
+ p_cur -= outpitch; /* compensate for the first offset */
+ p_ref = in++;
+
+ tmp = (uint32)(p_ref + ref_offset); /* limit */
+ while ((uint32)p_ref < tmp)
+ { /* loop un-rolled */
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 512) >> 10;
+ CLIP_RESULT(result)
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += curr_offset;
+ }
+ }
+
+ return ;
+}
+
+void eDiagonalInterpMC(uint8 *in1, uint8 *in2, int inpitch,
+ uint8 *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ int j, i;
+ int result;
+ uint8 *p_cur, *p_ref, *p_tmp8;
+ int curr_offset, ref_offset;
+ uint8 tmp_res[24][24], tmp_in[24][24];
+ uint32 *p_tmp;
+ uint32 tmp, pkres, tmp_result;
+ int32 r0, r1, r2, r3, r4, r5;
+ int32 r6, r7, r8, r9, r10, r13;
+
+ ref_offset = inpitch - blkwidth;
+ p_ref = in1 - 2;
+ /* perform horizontal interpolation */
+ /* not word-aligned */
+ /* It is faster to read 1 byte at time to avoid calling CreateAlign */
+ /* if(((uint32)p_ref)&0x3)
+ {
+ CreateAlign(p_ref,inpitch,0,&tmp_in[0][0],blkwidth+8,blkheight);
+ p_ref = &tmp_in[0][0];
+ ref_offset = 24-blkwidth;
+ }*/
+
+ p_tmp = (uint32*) & (tmp_res[0][0]);
+ for (j = blkheight; j > 0; j--)
+ {
+ r13 = 0;
+ tmp = (uint32)(p_ref + blkwidth);
+
+ //r0 = *((uint32*)p_ref); /* d,c,b,a */
+ //r1 = (r0>>8)&0xFF00FF; /* 0,d,0,b */
+ //r0 &= 0xFF00FF; /* 0,c,0,a */
+ /* It is faster to read 1 byte at a time */
+ r0 = p_ref[0];
+ r1 = p_ref[2];
+ r0 |= (r1 << 16); /* 0,c,0,a */
+ r1 = p_ref[1];
+ r2 = p_ref[3];
+ r1 |= (r2 << 16); /* 0,d,0,b */
+
+ while ((uint32)p_ref < tmp)
+ {
+ //r2 = *((uint32*)(p_ref+=4));/* h,g,f,e */
+ //r3 = (r2>>8)&0xFF00FF; /* 0,h,0,f */
+ //r2 &= 0xFF00FF; /* 0,g,0,e */
+ /* It is faster to read 1 byte at a time */
+ r2 = *(p_ref += 4);
+ r3 = p_ref[2];
+ r2 |= (r3 << 16); /* 0,g,0,e */
+ r3 = p_ref[1];
+ r4 = p_ref[3];
+ r3 |= (r4 << 16); /* 0,h,0,f */
+
+ r4 = r0 + r3; /* c+h, a+f */
+ r5 = r0 + r1; /* c+d, a+b */
+ r6 = r2 + r3; /* g+h, e+f */
+ r5 >>= 16;
+ r5 |= (r6 << 16); /* e+f, c+d */
+ r4 += r5 * 20; /* c+20*e+20*f+h, a+20*c+20*d+f */
+ r4 += 0x100010; /* +16, +16 */
+ r5 = r1 + r2; /* d+g, b+e */
+ r4 -= r5 * 5; /* c-5*d+20*e+20*f-5*g+h, a-5*b+20*c+20*d-5*e+f */
+ r4 >>= 5;
+ r13 |= r4; /* check clipping */
+ r4 &= 0xFF00FF; /* mask */
+
+ r5 = p_ref[4]; /* i */
+ r6 = (r5 << 16);
+ r5 = r6 | (r2 >> 16);/* 0,i,0,g */
+ r5 += r1; /* d+i, b+g */ /* r5 not free */
+ r1 >>= 16;
+ r1 |= (r3 << 16); /* 0,f,0,d */ /* r1 has changed */
+ r1 += r2; /* f+g, d+e */
+ r5 += 20 * r1; /* d+20f+20g+i, b+20d+20e+g */
+ r0 >>= 16;
+ r0 |= (r2 << 16); /* 0,e,0,c */ /* r0 has changed */
+ r0 += r3; /* e+h, c+f */
+ r5 += 0x100010; /* 16,16 */
+ r5 -= r0 * 5; /* d-5e+20f+20g-5h+i, b-5c+20d+20e-5f+g */
+ r5 >>= 5;
+ r13 |= r5; /* check clipping */
+ r5 &= 0xFF00FF; /* mask */
+
+ r4 |= (r5 << 8); /* pack them together */
+ *p_tmp++ = r4;
+ r1 = r3;
+ r0 = r2;
+ }
+ p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+
+ if (r13&0xFF000700) /* need clipping */
+ {
+ /* move back to the beginning of the line */
+ p_ref -= (ref_offset + blkwidth); /* input */
+ p_tmp -= 6; /* intermediate output */
+ tmp = (uint32)(p_ref + blkwidth);
+ while ((uint32)p_ref < tmp)
+ {
+ r0 = *p_ref++;
+ r1 = *p_ref++;
+ r2 = *p_ref++;
+ r3 = *p_ref++;
+ r4 = *p_ref++;
+ /* first pixel */
+ r5 = *p_ref++;
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres = result;
+ /* second pixel */
+ r0 = *p_ref++;
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 8);
+ /* third pixel */
+ r1 = *p_ref++;
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 16);
+ /* fourth pixel */
+ r2 = *p_ref++;
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ pkres |= (result << 24);
+
+ *p_tmp++ = pkres; /* write 4 pixel */
+ p_ref -= 5;
+ }
+ p_tmp += ((24 - blkwidth) >> 2); /* move to the next line */
+ p_ref += ref_offset; /* ref_offset = inpitch-blkwidth; */
+ }
+ }
+
+ /* perform vertical interpolation */
+ /* not word-aligned */
+ if (((uint32)in2)&0x3)
+ {
+ eCreateAlign(in2, inpitch, -2, &tmp_in[0][0], blkwidth, blkheight + 5);
+ in2 = &tmp_in[2][0];
+ inpitch = 24;
+ }
+
+ p_cur = out;
+ curr_offset = 1 - outpitch * (blkheight - 1); /* offset vertically up and one pixel right */
+ pkres = blkheight * inpitch; /* reuse it for limit */
+
+ curr_offset += 3;
+
+ for (j = 0; j < blkwidth; j += 4, in2 += 4)
+ {
+ r13 = 0;
+ p_ref = in2;
+ p_tmp8 = &(tmp_res[0][j]); /* intermediate result */
+ p_tmp8 -= 24; /* compensate for the first offset */
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + pkres); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ /* Read 1 byte at a time is too slow, too many read and pack ops, need to call CreateAlign */
+ /*p_ref8 = p_ref-(inpitch<<1); r0 = p_ref8[0]; r1 = p_ref8[2];
+ r0 |= (r1<<16); r6 = p_ref8[1]; r1 = p_ref8[3];
+ r6 |= (r1<<16); p_ref+=inpitch; */
+ r0 = *((uint32*)(p_ref - (inpitch << 1))); /* load 4 bytes */
+ p_ref += inpitch;
+ r6 = (r0 >> 8) & 0xFF00FF; /* second and fourth byte */
+ r0 &= 0xFF00FF;
+
+ /*p_ref8 = p_ref+(inpitch<<1);
+ r1 = p_ref8[0]; r7 = p_ref8[2]; r1 |= (r7<<16);
+ r7 = p_ref8[1]; r2 = p_ref8[3]; r7 |= (r2<<16);*/
+ r1 = *((uint32*)(p_ref + (inpitch << 1))); /* r1, r7, ref[3] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+
+ r0 += r1;
+ r6 += r7;
+
+ /*r2 = p_ref[0]; r8 = p_ref[2]; r2 |= (r8<<16);
+ r8 = p_ref[1]; r1 = p_ref[3]; r8 |= (r1<<16);*/
+ r2 = *((uint32*)p_ref); /* r2, r8, ref[1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ /*p_ref8 = p_ref-inpitch; r1 = p_ref8[0]; r7 = p_ref8[2];
+ r1 |= (r7<<16); r1 += r2; r7 = p_ref8[1];
+ r2 = p_ref8[3]; r7 |= (r2<<16);*/
+ r1 = *((uint32*)(p_ref - inpitch)); /* r1, r7, ref[0] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 += 20 * r1;
+ r6 += 20 * r7;
+ r0 += 0x100010;
+ r6 += 0x100010;
+
+ /*p_ref8 = p_ref-(inpitch<<1); r2 = p_ref8[0]; r8 = p_ref8[2];
+ r2 |= (r8<<16); r8 = p_ref8[1]; r1 = p_ref8[3]; r8 |= (r1<<16);*/
+ r2 = *((uint32*)(p_ref - (inpitch << 1))); /* r2, r8, ref[-1] */
+ r8 = (r2 >> 8) & 0xFF00FF;
+ r2 &= 0xFF00FF;
+
+ /*p_ref8 = p_ref+inpitch; r1 = p_ref8[0]; r7 = p_ref8[2];
+ r1 |= (r7<<16); r1 += r2; r7 = p_ref8[1];
+ r2 = p_ref8[3]; r7 |= (r2<<16);*/
+ r1 = *((uint32*)(p_ref + inpitch)); /* r1, r7, ref[2] */
+ r7 = (r1 >> 8) & 0xFF00FF;
+ r1 &= 0xFF00FF;
+ r1 += r2;
+
+ r7 += r8;
+
+ r0 -= 5 * r1;
+ r6 -= 5 * r7;
+
+ r0 >>= 5;
+ r6 >>= 5;
+ /* clip */
+ r13 |= r6;
+ r13 |= r0;
+ //CLIPPACK(r6,result)
+ /* add with horizontal results */
+ r10 = *((uint32*)(p_tmp8 += 24));
+ r9 = (r10 >> 8) & 0xFF00FF;
+ r10 &= 0xFF00FF;
+
+ r0 += r10;
+ r0 += 0x10001;
+ r0 = (r0 >> 1) & 0xFF00FF; /* mask to 8 bytes */
+
+ r6 += r9;
+ r6 += 0x10001;
+ r6 = (r6 >> 1) & 0xFF00FF; /* mask to 8 bytes */
+
+ r0 |= (r6 << 8); /* pack it back */
+ *((uint32*)(p_cur += outpitch)) = r0;
+ }
+ p_cur += curr_offset; /* offset to the next pixel */
+ if (r13 & 0xFF000700) /* this column need clipping */
+ {
+ p_cur -= 4;
+ for (i = 0; i < 4; i++)
+ {
+ p_ref = in2 + i;
+ p_tmp8 = &(tmp_res[0][j+i]); /* intermediate result */
+ p_tmp8 -= 24; /* compensate for the first offset */
+ p_cur -= outpitch; /* compensate for the first offset */
+ tmp = (uint32)(p_ref + pkres); /* limit */
+ while ((uint32)p_ref < tmp) /* the loop un-rolled */
+ {
+ r0 = *(p_ref - (inpitch << 1));
+ r1 = *(p_ref - inpitch);
+ r2 = *p_ref;
+ r3 = *(p_ref += inpitch); /* modify pointer before loading */
+ r4 = *(p_ref += inpitch);
+ /* first pixel */
+ r5 = *(p_ref += inpitch);
+ result = (r0 + r5);
+ r0 = (r1 + r4);
+ result -= (r0 * 5);//result -= r0; result -= (r0<<2);
+ r0 = (r2 + r3);
+ result += (r0 * 20);//result += (r0<<4); result += (r0<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* modify pointer before loading */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* second pixel */
+ r0 = *(p_ref += inpitch);
+ result = (r1 + r0);
+ r1 = (r2 + r5);
+ result -= (r1 * 5);//result -= r1; result -= (r1<<2);
+ r1 = (r3 + r4);
+ result += (r1 * 20);//result += (r1<<4); result += (r1<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* intermediate result */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* third pixel */
+ r1 = *(p_ref += inpitch);
+ result = (r2 + r1);
+ r2 = (r3 + r0);
+ result -= (r2 * 5);//result -= r2; result -= (r2<<2);
+ r2 = (r4 + r5);
+ result += (r2 * 20);//result += (r2<<4); result += (r2<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* intermediate result */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ /* fourth pixel */
+ r2 = *(p_ref += inpitch);
+ result = (r3 + r2);
+ r3 = (r4 + r1);
+ result -= (r3 * 5);//result -= r3; result -= (r3<<2);
+ r3 = (r5 + r0);
+ result += (r3 * 20);//result += (r3<<4); result += (r3<<2);
+ result = (result + 16) >> 5;
+ CLIP_RESULT(result)
+ tmp_result = *(p_tmp8 += 24); /* intermediate result */
+ result = (result + tmp_result + 1); /* no clip */
+ result = (result >> 1);
+ *(p_cur += outpitch) = result;
+ p_ref -= (inpitch << 1); /* move back to center of the filter of the next one */
+ }
+ p_cur += (curr_offset - 3);
+ }
+ }
+ }
+
+ return ;
+}
+
+/* position G */
+void eFullPelMC(uint8 *in, int inpitch, uint8 *out, int outpitch,
+ int blkwidth, int blkheight)
+{
+ int i, j;
+ int offset_in = inpitch - blkwidth;
+ int offset_out = outpitch - blkwidth;
+ uint32 temp;
+ uint8 byte;
+
+ if (((uint32)in)&3)
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 4)
+ {
+ temp = *in++;
+ byte = *in++;
+ temp |= (byte << 8);
+ byte = *in++;
+ temp |= (byte << 16);
+ byte = *in++;
+ temp |= (byte << 24);
+
+ *((uint32*)out) = temp; /* write 4 bytes */
+ out += 4;
+ }
+ out += offset_out;
+ in += offset_in;
+ }
+ }
+ else
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 4)
+ {
+ temp = *((uint32*)in);
+ *((uint32*)out) = temp;
+ in += 4;
+ out += 4;
+ }
+ out += offset_out;
+ in += offset_in;
+ }
+ }
+ return ;
+}
+
+void ePadChroma(uint8 *ref, int picwidth, int picheight, int picpitch, int x_pos, int y_pos)
+{
+ int pad_height;
+ int pad_width;
+ uint8 *start;
+ uint32 word1, word2, word3;
+ int offset, j;
+
+
+ pad_height = 8 + ((y_pos & 7) ? 1 : 0);
+ pad_width = 8 + ((x_pos & 7) ? 1 : 0);
+
+ y_pos >>= 3;
+ x_pos >>= 3;
+ // pad vertical first
+ if (y_pos < 0) // need to pad up
+ {
+ if (x_pos < -8) start = ref - 8;
+ else if (x_pos + pad_width > picwidth + 7) start = ref + picwidth + 7 - pad_width;
+ else start = ref + x_pos;
+
+ /* word-align start */
+ offset = (uint32)start & 0x3;
+ if (offset) start -= offset;
+
+ word1 = *((uint32*)start);
+ word2 = *((uint32*)(start + 4));
+ word3 = *((uint32*)(start + 8));
+
+ /* pad up N rows */
+ j = -y_pos;
+ if (j > 8) j = 8;
+ while (j--)
+ {
+ *((uint32*)(start -= picpitch)) = word1;
+ *((uint32*)(start + 4)) = word2;
+ *((uint32*)(start + 8)) = word3;
+ }
+
+ }
+ else if (y_pos + pad_height >= picheight) /* pad down */
+ {
+ if (x_pos < -8) start = ref + picpitch * (picheight - 1) - 8;
+ else if (x_pos + pad_width > picwidth + 7) start = ref + picpitch * (picheight - 1) +
+ picwidth + 7 - pad_width;
+ else start = ref + picpitch * (picheight - 1) + x_pos;
+
+ /* word-align start */
+ offset = (uint32)start & 0x3;
+ if (offset) start -= offset;
+
+ word1 = *((uint32*)start);
+ word2 = *((uint32*)(start + 4));
+ word3 = *((uint32*)(start + 8));
+
+ /* pad down N rows */
+ j = y_pos + pad_height - picheight;
+ if (j > 8) j = 8;
+ while (j--)
+ {
+ *((uint32*)(start += picpitch)) = word1;
+ *((uint32*)(start + 4)) = word2;
+ *((uint32*)(start + 8)) = word3;
+ }
+ }
+
+ /* now pad horizontal */
+ if (x_pos < 0) // pad left
+ {
+ if (y_pos < -8) start = ref - (picpitch << 3);
+ else if (y_pos + pad_height > picheight + 7) start = ref + (picheight + 7 - pad_height) * picpitch;
+ else start = ref + y_pos * picpitch;
+
+ // now pad left 8 pixels for pad_height rows */
+ j = pad_height;
+ start -= picpitch;
+ while (j--)
+ {
+ word1 = *(start += picpitch);
+ word1 |= (word1 << 8);
+ word1 |= (word1 << 16);
+ *((uint32*)(start - 8)) = word1;
+ *((uint32*)(start - 4)) = word1;
+ }
+ }
+ else if (x_pos + pad_width >= picwidth) /* pad right */
+ {
+ if (y_pos < -8) start = ref - (picpitch << 3) + picwidth - 1;
+ else if (y_pos + pad_height > picheight + 7) start = ref + (picheight + 7 - pad_height) * picpitch + picwidth - 1;
+ else start = ref + y_pos * picpitch + picwidth - 1;
+
+ // now pad right 8 pixels for pad_height rows */
+ j = pad_height;
+ start -= picpitch;
+ while (j--)
+ {
+ word1 = *(start += picpitch);
+ word1 |= (word1 << 8);
+ word1 |= (word1 << 16);
+ *((uint32*)(start + 1)) = word1;
+ *((uint32*)(start + 5)) = word1;
+ }
+ }
+
+ return ;
+}
+
+
+void eChromaMotionComp(uint8 *ref, int picwidth, int picheight,
+ int x_pos, int y_pos,
+ uint8 *pred, int picpitch,
+ int blkwidth, int blkheight)
+{
+ int dx, dy;
+ int offset_dx, offset_dy;
+ int index;
+
+ ePadChroma(ref, picwidth, picheight, picpitch, x_pos, y_pos);
+
+ dx = x_pos & 7;
+ dy = y_pos & 7;
+ offset_dx = (dx + 7) >> 3;
+ offset_dy = (dy + 7) >> 3;
+ x_pos = x_pos >> 3; /* round it to full-pel resolution */
+ y_pos = y_pos >> 3;
+
+ ref += y_pos * picpitch + x_pos;
+
+ index = offset_dx + (offset_dy << 1) + ((blkwidth << 1) & 0x7);
+
+ (*(eChromaMC_SIMD[index]))(ref, picpitch , dx, dy, pred, picpitch, blkwidth, blkheight);
+ return ;
+}
+
+
+/* SIMD routines, unroll the loops in vertical direction, decreasing loops (things to be done) */
+void eChromaDiagonalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ int32 r0, r1, r2, r3, result0, result1;
+ uint8 temp[288];
+ uint8 *ref, *out;
+ int i, j;
+ int dx_8 = 8 - dx;
+ int dy_8 = 8 - dy;
+
+ /* horizontal first */
+ out = temp;
+ for (i = 0; i < blkheight + 1; i++)
+ {
+ ref = pRef;
+ r0 = ref[0];
+ for (j = 0; j < blkwidth; j += 4)
+ {
+ r0 |= (ref[2] << 16);
+ result0 = dx_8 * r0;
+
+ r1 = ref[1] | (ref[3] << 16);
+ result0 += dx * r1;
+ *(int32 *)out = result0;
+
+ result0 = dx_8 * r1;
+
+ r2 = ref[4];
+ r0 = r0 >> 16;
+ r1 = r0 | (r2 << 16);
+ result0 += dx * r1;
+ *(int32 *)(out + 16) = result0;
+
+ ref += 4;
+ out += 4;
+ r0 = r2;
+ }
+ pRef += srcPitch;
+ out += (32 - blkwidth);
+ }
+
+// pRef -= srcPitch*(blkheight+1);
+ ref = temp;
+
+ for (j = 0; j < blkwidth; j += 4)
+ {
+ r0 = *(int32 *)ref;
+ r1 = *(int32 *)(ref + 16);
+ ref += 32;
+ out = pOut;
+ for (i = 0; i < (blkheight >> 1); i++)
+ {
+ result0 = dy_8 * r0 + 0x00200020;
+ r2 = *(int32 *)ref;
+ result0 += dy * r2;
+ result0 >>= 6;
+ result0 &= 0x00FF00FF;
+ r0 = r2;
+
+ result1 = dy_8 * r1 + 0x00200020;
+ r3 = *(int32 *)(ref + 16);
+ result1 += dy * r3;
+ result1 >>= 6;
+ result1 &= 0x00FF00FF;
+ r1 = r3;
+ *(int32 *)out = result0 | (result1 << 8);
+ out += predPitch;
+ ref += 32;
+
+ result0 = dy_8 * r0 + 0x00200020;
+ r2 = *(int32 *)ref;
+ result0 += dy * r2;
+ result0 >>= 6;
+ result0 &= 0x00FF00FF;
+ r0 = r2;
+
+ result1 = dy_8 * r1 + 0x00200020;
+ r3 = *(int32 *)(ref + 16);
+ result1 += dy * r3;
+ result1 >>= 6;
+ result1 &= 0x00FF00FF;
+ r1 = r3;
+ *(int32 *)out = result0 | (result1 << 8);
+ out += predPitch;
+ ref += 32;
+ }
+ pOut += 4;
+ ref = temp + 4; /* since it can only iterate twice max */
+ }
+ return;
+}
+
+void eChromaHorizontalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ (void)(dy);
+
+ int32 r0, r1, r2, result0, result1;
+ uint8 *ref, *out;
+ int i, j;
+ int dx_8 = 8 - dx;
+
+ /* horizontal first */
+ for (i = 0; i < blkheight; i++)
+ {
+ ref = pRef;
+ out = pOut;
+
+ r0 = ref[0];
+ for (j = 0; j < blkwidth; j += 4)
+ {
+ r0 |= (ref[2] << 16);
+ result0 = dx_8 * r0 + 0x00040004;
+
+ r1 = ref[1] | (ref[3] << 16);
+ result0 += dx * r1;
+ result0 >>= 3;
+ result0 &= 0x00FF00FF;
+
+ result1 = dx_8 * r1 + 0x00040004;
+
+ r2 = ref[4];
+ r0 = r0 >> 16;
+ r1 = r0 | (r2 << 16);
+ result1 += dx * r1;
+ result1 >>= 3;
+ result1 &= 0x00FF00FF;
+
+ *(int32 *)out = result0 | (result1 << 8);
+
+ ref += 4;
+ out += 4;
+ r0 = r2;
+ }
+
+ pRef += srcPitch;
+ pOut += predPitch;
+ }
+ return;
+}
+
+void eChromaVerticalMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ (void)(dx);
+
+ int32 r0, r1, r2, r3, result0, result1;
+ int i, j;
+ uint8 *ref, *out;
+ int dy_8 = 8 - dy;
+ /* vertical first */
+ for (i = 0; i < blkwidth; i += 4)
+ {
+ ref = pRef;
+ out = pOut;
+
+ r0 = ref[0] | (ref[2] << 16);
+ r1 = ref[1] | (ref[3] << 16);
+ ref += srcPitch;
+ for (j = 0; j < blkheight; j++)
+ {
+ result0 = dy_8 * r0 + 0x00040004;
+ r2 = ref[0] | (ref[2] << 16);
+ result0 += dy * r2;
+ result0 >>= 3;
+ result0 &= 0x00FF00FF;
+ r0 = r2;
+
+ result1 = dy_8 * r1 + 0x00040004;
+ r3 = ref[1] | (ref[3] << 16);
+ result1 += dy * r3;
+ result1 >>= 3;
+ result1 &= 0x00FF00FF;
+ r1 = r3;
+ *(int32 *)out = result0 | (result1 << 8);
+ ref += srcPitch;
+ out += predPitch;
+ }
+ pOut += 4;
+ pRef += 4;
+ }
+ return;
+}
+
+void eChromaDiagonalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ (void)(blkwidth);
+
+ int32 r0, r1, temp0, temp1, result;
+ int32 temp[9];
+ int32 *out;
+ int i, r_temp;
+ int dy_8 = 8 - dy;
+
+ /* horizontal first */
+ out = temp;
+ for (i = 0; i < blkheight + 1; i++)
+ {
+ r_temp = pRef[1];
+ temp0 = (pRef[0] << 3) + dx * (r_temp - pRef[0]);
+ temp1 = (r_temp << 3) + dx * (pRef[2] - r_temp);
+ r0 = temp0 | (temp1 << 16);
+ *out++ = r0;
+ pRef += srcPitch;
+ }
+
+ pRef -= srcPitch * (blkheight + 1);
+
+ out = temp;
+
+ r0 = *out++;
+
+ for (i = 0; i < blkheight; i++)
+ {
+ result = dy_8 * r0 + 0x00200020;
+ r1 = *out++;
+ result += dy * r1;
+ result >>= 6;
+ result &= 0x00FF00FF;
+ *(int16 *)pOut = (result >> 8) | (result & 0xFF);
+ r0 = r1;
+ pOut += predPitch;
+ }
+ return;
+}
+
+void eChromaHorizontalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ (void)(dy);
+ (void)(blkwidth);
+
+ int i, temp, temp0, temp1;
+
+ /* horizontal first */
+ for (i = 0; i < blkheight; i++)
+ {
+ temp = pRef[1];
+ temp0 = ((pRef[0] << 3) + dx * (temp - pRef[0]) + 4) >> 3;
+ temp1 = ((temp << 3) + dx * (pRef[2] - temp) + 4) >> 3;
+
+ *(int16 *)pOut = temp0 | (temp1 << 8);
+ pRef += srcPitch;
+ pOut += predPitch;
+
+ }
+ return;
+}
+void eChromaVerticalMC2_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ (void)(dx);
+ (void)(blkwidth);
+
+ int32 r0, r1, result;
+ int i;
+ int dy_8 = 8 - dy;
+ r0 = pRef[0] | (pRef[1] << 16);
+ pRef += srcPitch;
+ for (i = 0; i < blkheight; i++)
+ {
+ result = dy_8 * r0 + 0x00040004;
+ r1 = pRef[0] | (pRef[1] << 16);
+ result += dy * r1;
+ result >>= 3;
+ result &= 0x00FF00FF;
+ *(int16 *)pOut = (result >> 8) | (result & 0xFF);
+ r0 = r1;
+ pRef += srcPitch;
+ pOut += predPitch;
+ }
+ return;
+}
+
+void eChromaFullMC_SIMD(uint8 *pRef, int srcPitch, int dx, int dy,
+ uint8 *pOut, int predPitch, int blkwidth, int blkheight)
+{
+ (void)(dx);
+ (void)(dy);
+
+ int i, j;
+ int offset_in = srcPitch - blkwidth;
+ int offset_out = predPitch - blkwidth;
+ uint16 temp;
+ uint8 byte;
+
+ if (((uint32)pRef)&1)
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 2)
+ {
+ temp = *pRef++;
+ byte = *pRef++;
+ temp |= (byte << 8);
+ *((uint16*)pOut) = temp; /* write 2 bytes */
+ pOut += 2;
+ }
+ pOut += offset_out;
+ pRef += offset_in;
+ }
+ }
+ else
+ {
+ for (j = blkheight; j > 0; j--)
+ {
+ for (i = blkwidth; i > 0; i -= 2)
+ {
+ temp = *((uint16*)pRef);
+ *((uint16*)pOut) = temp;
+ pRef += 2;
+ pOut += 2;
+ }
+ pOut += offset_out;
+ pRef += offset_in;
+ }
+ }
+ return ;
+}
diff --git a/media/libstagefright/codecs/avc/enc/src/motion_est.cpp b/media/libstagefright/codecs/avc/enc/src/motion_est.cpp
new file mode 100644
index 0000000..f650ef9
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/motion_est.cpp
@@ -0,0 +1,1774 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+#define MIN_GOP 1 /* minimum size of GOP, 1/23/01, need to be tested */
+
+#define DEFAULT_REF_IDX 0 /* always from the first frame in the reflist */
+
+#define ALL_CAND_EQUAL 10 /* any number greater than 5 will work */
+
+
+/* from TMN 3.2 */
+#define PREF_NULL_VEC 129 /* zero vector bias */
+#define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/
+#define PREF_INTRA 3024//512 /* bias for INTRA coding */
+
+const static int tab_exclude[9][9] = // [last_loc][curr_loc]
+{
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 1, 1, 1, 0, 0},
+ {0, 0, 0, 0, 1, 1, 1, 1, 1},
+ {0, 0, 0, 0, 0, 0, 1, 1, 1},
+ {0, 1, 1, 0, 0, 0, 1, 1, 1},
+ {0, 1, 1, 0, 0, 0, 0, 0, 1},
+ {0, 1, 1, 1, 1, 0, 0, 0, 1},
+ {0, 0, 1, 1, 1, 0, 0, 0, 0},
+ {0, 0, 1, 1, 1, 1, 1, 0, 0}
+}; //to decide whether to continue or compute
+
+const static int refine_next[8][2] = /* [curr_k][increment] */
+{
+ {0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}
+};
+
+#ifdef _SAD_STAT
+uint32 num_MB = 0;
+uint32 num_cand = 0;
+#endif
+
+/************************************************************************/
+#define TH_INTER_2 100 /* temporary for now */
+
+//#define FIXED_INTERPRED_MODE AVC_P16
+#define FIXED_REF_IDX 0
+#define FIXED_MVX 0
+#define FIXED_MVY 0
+
+// only use when AVC_P8 or AVC_P8ref0
+#define FIXED_SUBMB_MODE AVC_4x4
+/*************************************************************************/
+
+/* Initialize arrays necessary for motion search */
+AVCEnc_Status InitMotionSearchModule(AVCHandle *avcHandle)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ int search_range = rateCtrl->mvRange;
+ int number_of_subpel_positions = 4 * (2 * search_range + 3);
+ int max_mv_bits, max_mvd;
+ int temp_bits = 0;
+ uint8 *mvbits;
+ int bits, imax, imin, i;
+ uint8* subpel_pred = (uint8*) encvid->subpel_pred; // all 16 sub-pel positions
+
+
+ while (number_of_subpel_positions > 0)
+ {
+ temp_bits++;
+ number_of_subpel_positions >>= 1;
+ }
+
+ max_mv_bits = 3 + 2 * temp_bits;
+ max_mvd = (1 << (max_mv_bits >> 1)) - 1;
+
+ encvid->mvbits_array = (uint8*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+ sizeof(uint8) * (2 * max_mvd + 1), DEFAULT_ATTR);
+
+ if (encvid->mvbits_array == NULL)
+ {
+ return AVCENC_MEMORY_FAIL;
+ }
+
+ mvbits = encvid->mvbits = encvid->mvbits_array + max_mvd;
+
+ mvbits[0] = 1;
+ for (bits = 3; bits <= max_mv_bits; bits += 2)
+ {
+ imax = 1 << (bits >> 1);
+ imin = imax >> 1;
+
+ for (i = imin; i < imax; i++) mvbits[-i] = mvbits[i] = bits;
+ }
+
+ /* initialize half-pel search */
+ encvid->hpel_cand[0] = subpel_pred + REF_CENTER;
+ encvid->hpel_cand[1] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1 ;
+ encvid->hpel_cand[2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+ encvid->hpel_cand[3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+ encvid->hpel_cand[4] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+ encvid->hpel_cand[5] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
+ encvid->hpel_cand[6] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->hpel_cand[7] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->hpel_cand[8] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+
+ /* For quarter-pel interpolation around best half-pel result */
+
+ encvid->bilin_base[0][0] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[0][1] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+ encvid->bilin_base[0][2] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->bilin_base[0][3] = subpel_pred + REF_CENTER;
+
+
+ encvid->bilin_base[1][0] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[1][1] = subpel_pred + REF_CENTER - 24;
+ encvid->bilin_base[1][2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[1][3] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+
+ encvid->bilin_base[2][0] = subpel_pred + REF_CENTER - 24;
+ encvid->bilin_base[2][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+ encvid->bilin_base[2][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+ encvid->bilin_base[2][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+
+ encvid->bilin_base[3][0] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 1;
+ encvid->bilin_base[3][1] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 1;
+ encvid->bilin_base[3][2] = subpel_pred + REF_CENTER;
+ encvid->bilin_base[3][3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+
+ encvid->bilin_base[4][0] = subpel_pred + REF_CENTER;
+ encvid->bilin_base[4][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+ encvid->bilin_base[4][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
+ encvid->bilin_base[4][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 25;
+
+ encvid->bilin_base[5][0] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->bilin_base[5][1] = subpel_pred + REF_CENTER;
+ encvid->bilin_base[5][2] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->bilin_base[5][3] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 25;
+
+ encvid->bilin_base[6][0] = subpel_pred + REF_CENTER - 1;
+ encvid->bilin_base[6][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->bilin_base[6][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE + 24;
+ encvid->bilin_base[6][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+
+ encvid->bilin_base[7][0] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[7][1] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[7][2] = subpel_pred + REF_CENTER - 1;
+ encvid->bilin_base[7][3] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE + 24;
+
+ encvid->bilin_base[8][0] = subpel_pred + REF_CENTER - 25;
+ encvid->bilin_base[8][1] = subpel_pred + V0Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[8][2] = subpel_pred + V2Q_H0Q * SUBPEL_PRED_BLK_SIZE;
+ encvid->bilin_base[8][3] = subpel_pred + V2Q_H2Q * SUBPEL_PRED_BLK_SIZE;
+
+
+ return AVCENC_SUCCESS;
+}
+
+/* Clean-up memory */
+void CleanMotionSearchModule(AVCHandle *avcHandle)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+
+ if (encvid->mvbits_array)
+ {
+ avcHandle->CBAVC_Free(avcHandle->userData, (int)(encvid->mvbits_array));
+ encvid->mvbits = NULL;
+ }
+
+ return ;
+}
+
+
+bool IntraDecisionABE(int *min_cost, uint8 *cur, int pitch, bool ave)
+{
+ int j;
+ uint8 *out;
+ int temp, SBE;
+ OsclFloat ABE;
+ bool intra = true;
+
+ SBE = 0;
+ /* top neighbor */
+ out = cur - pitch;
+ for (j = 0; j < 16; j++)
+ {
+ temp = out[j] - cur[j];
+ SBE += ((temp >= 0) ? temp : -temp);
+ }
+
+ /* left neighbor */
+ out = cur - 1;
+ out -= pitch;
+ cur -= pitch;
+ for (j = 0; j < 16; j++)
+ {
+ temp = *(out += pitch) - *(cur += pitch);
+ SBE += ((temp >= 0) ? temp : -temp);
+ }
+
+ /* compare mincost/384 and SBE/64 */
+ ABE = SBE / 32.0; //ABE = SBE/64.0; //
+ if (ABE >= *min_cost / 256.0) //if( ABE*0.8 >= min_cost/384.0) //
+ {
+ intra = false; // no possibility of intra, just use inter
+ }
+ else
+ {
+ if (ave == true)
+ {
+ *min_cost = (*min_cost + (int)(SBE * 8)) >> 1; // possibility of intra, averaging the cost
+ }
+ else
+ {
+ *min_cost = (int)(SBE * 8);
+ }
+ }
+
+ return intra;
+}
+
+/******* main function for macroblock prediction for the entire frame ***/
+/* if turns out to be IDR frame, set video->nal_unit_type to AVC_NALTYPE_IDR */
+void AVCMotionEstimation(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ int slice_type = video->slice_type;
+ AVCFrameIO *currInput = encvid->currInput;
+ AVCPictureData *refPic = video->RefPicList0[0];
+ int i, j, k;
+ int mbwidth = video->PicWidthInMbs;
+ int mbheight = video->PicHeightInMbs;
+ int totalMB = video->PicSizeInMbs;
+ int pitch = currInput->pitch;
+ AVCMacroblock *currMB, *mblock = video->mblock;
+ AVCMV *mot_mb_16x16, *mot16x16 = encvid->mot16x16;
+ // AVCMV *mot_mb_16x8, *mot_mb_8x16, *mot_mb_8x8, etc;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ uint8 *intraSearch = encvid->intraSearch;
+ uint FS_en = encvid->fullsearch_enable;
+
+ int NumIntraSearch, start_i, numLoop, incr_i;
+ int mbnum, offset;
+ uint8 *cur, *best_cand[5];
+ int totalSAD = 0; /* average SAD for rate control */
+ int type_pred;
+ int abe_cost;
+
+#ifdef HTFM
+ /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
+ int collect = 0;
+ HTFM_Stat htfm_stat;
+ double newvar[16];
+ double exp_lamda[15];
+ /*********************************/
+#endif
+ int hp_guess = 0;
+ uint32 mv_uint32;
+
+ offset = 0;
+
+ if (slice_type == AVC_I_SLICE)
+ {
+ /* cannot do I16 prediction here because it needs full decoding. */
+ for (i = 0; i < totalMB; i++)
+ {
+ encvid->min_cost[i] = 0x7FFFFFFF; /* max value for int */
+ }
+
+ memset(intraSearch, 1, sizeof(uint8)*totalMB);
+
+ encvid->firstIntraRefreshMBIndx = 0; /* reset this */
+
+ return ;
+ }
+ else // P_SLICE
+ {
+ for (i = 0; i < totalMB; i++)
+ {
+ mblock[i].mb_intra = 0;
+ }
+ memset(intraSearch, 1, sizeof(uint8)*totalMB);
+ }
+
+ if (refPic->padded == 0)
+ {
+ AVCPaddingEdge(refPic);
+ refPic->padded = 1;
+ }
+ /* Random INTRA update */
+ if (rateCtrl->intraMBRate)
+ {
+ AVCRasterIntraUpdate(encvid, mblock, totalMB, rateCtrl->intraMBRate);
+ }
+
+ encvid->sad_extra_info = NULL;
+#ifdef HTFM
+ /***** HYPOTHESIS TESTING ********/
+ InitHTFM(video, &htfm_stat, newvar, &collect);
+ /*********************************/
+#endif
+
+ if ((rateCtrl->scdEnable == 1)
+ && ((rateCtrl->frame_rate < 5.0) || (video->sliceHdr->frame_num > MIN_GOP)))
+ /* do not try to detect a new scene if low frame rate and too close to previous I-frame */
+ {
+ incr_i = 2;
+ numLoop = 2;
+ start_i = 1;
+ type_pred = 0; /* for initial candidate selection */
+ }
+ else
+ {
+ incr_i = 1;
+ numLoop = 1;
+ start_i = 0;
+ type_pred = 2;
+ }
+
+ /* First pass, loop thru half the macroblock */
+ /* determine scene change */
+ /* Second pass, for the rest of macroblocks */
+ NumIntraSearch = 0; // to be intra searched in the encoding loop.
+ while (numLoop--)
+ {
+ for (j = 0; j < mbheight; j++)
+ {
+ if (incr_i > 1)
+ start_i = (start_i == 0 ? 1 : 0) ; /* toggle 0 and 1 */
+
+ offset = pitch * (j << 4) + (start_i << 4);
+
+ mbnum = j * mbwidth + start_i;
+
+ for (i = start_i; i < mbwidth; i += incr_i)
+ {
+ video->mbNum = mbnum;
+ video->currMB = currMB = mblock + mbnum;
+ mot_mb_16x16 = mot16x16 + mbnum;
+
+ cur = currInput->YCbCr[0] + offset;
+
+ if (currMB->mb_intra == 0) /* for INTER mode */
+ {
+#if defined(HTFM)
+ HTFMPrepareCurMB_AVC(encvid, &htfm_stat, cur, pitch);
+#else
+ AVCPrepareCurMB(encvid, cur, pitch);
+#endif
+ /************************************************************/
+ /******** full-pel 1MV search **********************/
+
+ AVCMBMotionSearch(encvid, cur, best_cand, i << 4, j << 4, type_pred,
+ FS_en, &hp_guess);
+
+ abe_cost = encvid->min_cost[mbnum] = mot_mb_16x16->sad;
+
+ /* set mbMode and MVs */
+ currMB->mbMode = AVC_P16;
+ currMB->MBPartPredMode[0][0] = AVC_Pred_L0;
+ mv_uint32 = ((mot_mb_16x16->y) << 16) | ((mot_mb_16x16->x) & 0xffff);
+ for (k = 0; k < 32; k += 2)
+ {
+ currMB->mvL0[k>>1] = mv_uint32;
+ }
+
+ /* make a decision whether it should be tested for intra or not */
+ if (i != mbwidth - 1 && j != mbheight - 1 && i != 0 && j != 0)
+ {
+ if (false == IntraDecisionABE(&abe_cost, cur, pitch, true))
+ {
+ intraSearch[mbnum] = 0;
+ }
+ else
+ {
+ NumIntraSearch++;
+ rateCtrl->MADofMB[mbnum] = abe_cost;
+ }
+ }
+ else // boundary MBs, always do intra search
+ {
+ NumIntraSearch++;
+ }
+
+ totalSAD += (int) rateCtrl->MADofMB[mbnum];//mot_mb_16x16->sad;
+ }
+ else /* INTRA update, use for prediction */
+ {
+ mot_mb_16x16[0].x = mot_mb_16x16[0].y = 0;
+
+ /* reset all other MVs to zero */
+ /* mot_mb_16x8, mot_mb_8x16, mot_mb_8x8, etc. */
+ abe_cost = encvid->min_cost[mbnum] = 0x7FFFFFFF; /* max value for int */
+
+ if (i != mbwidth - 1 && j != mbheight - 1 && i != 0 && j != 0)
+ {
+ IntraDecisionABE(&abe_cost, cur, pitch, false);
+
+ rateCtrl->MADofMB[mbnum] = abe_cost;
+ totalSAD += abe_cost;
+ }
+
+ NumIntraSearch++ ;
+ /* cannot do I16 prediction here because it needs full decoding. */
+ // intraSearch[mbnum] = 1;
+
+ }
+
+ mbnum += incr_i;
+ offset += (incr_i << 4);
+
+ } /* for i */
+ } /* for j */
+
+ /* since we cannot do intra/inter decision here, the SCD has to be
+ based on other criteria such as motion vectors coherency or the SAD */
+ if (incr_i > 1 && numLoop) /* scene change on and first loop */
+ {
+ //if(NumIntraSearch > ((totalMB>>3)<<1) + (totalMB>>3)) /* 75% of 50%MBs */
+ if (NumIntraSearch*99 > (48*totalMB)) /* 20% of 50%MBs */
+ /* need to do more investigation about this threshold since the NumIntraSearch
+ only show potential intra MBs, not the actual one */
+ {
+ /* we can choose to just encode I_SLICE without IDR */
+ //video->nal_unit_type = AVC_NALTYPE_IDR;
+ video->nal_unit_type = AVC_NALTYPE_SLICE;
+ video->sliceHdr->slice_type = AVC_I_ALL_SLICE;
+ video->slice_type = AVC_I_SLICE;
+ memset(intraSearch, 1, sizeof(uint8)*totalMB);
+ i = totalMB;
+ while (i--)
+ {
+ mblock[i].mb_intra = 1;
+ encvid->min_cost[i] = 0x7FFFFFFF; /* max value for int */
+ }
+
+ rateCtrl->totalSAD = totalSAD * 2; /* SAD */
+
+ return ;
+ }
+ }
+ /******** no scene change, continue motion search **********************/
+ start_i = 0;
+ type_pred++; /* second pass */
+ }
+
+ rateCtrl->totalSAD = totalSAD; /* SAD */
+
+#ifdef HTFM
+ /***** HYPOTHESIS TESTING ********/
+ if (collect)
+ {
+ collect = 0;
+ UpdateHTFM(encvid, newvar, exp_lamda, &htfm_stat);
+ }
+ /*********************************/
+#endif
+
+ return ;
+}
+
+/*=====================================================================
+ Function: PaddingEdge
+ Date: 09/16/2000
+ Purpose: Pad edge of a Vop
+=====================================================================*/
+
+void AVCPaddingEdge(AVCPictureData *refPic)
+{
+ uint8 *src, *dst;
+ int i;
+ int pitch, width, height;
+ uint32 temp1, temp2;
+
+ width = refPic->width;
+ height = refPic->height;
+ pitch = refPic->pitch;
+
+ /* pad top */
+ src = refPic->Sl;
+
+ temp1 = *src; /* top-left corner */
+ temp2 = src[width-1]; /* top-right corner */
+ temp1 |= (temp1 << 8);
+ temp1 |= (temp1 << 16);
+ temp2 |= (temp2 << 8);
+ temp2 |= (temp2 << 16);
+
+ dst = src - (pitch << 4);
+
+ *((uint32*)(dst - 16)) = temp1;
+ *((uint32*)(dst - 12)) = temp1;
+ *((uint32*)(dst - 8)) = temp1;
+ *((uint32*)(dst - 4)) = temp1;
+
+ memcpy(dst, src, width);
+
+ *((uint32*)(dst += width)) = temp2;
+ *((uint32*)(dst + 4)) = temp2;
+ *((uint32*)(dst + 8)) = temp2;
+ *((uint32*)(dst + 12)) = temp2;
+
+ dst = dst - width - 16;
+
+ i = 15;
+ while (i--)
+ {
+ memcpy(dst + pitch, dst, pitch);
+ dst += pitch;
+ }
+
+ /* pad sides */
+ dst += (pitch + 16);
+ src = dst;
+ i = height;
+ while (i--)
+ {
+ temp1 = *src;
+ temp2 = src[width-1];
+ temp1 |= (temp1 << 8);
+ temp1 |= (temp1 << 16);
+ temp2 |= (temp2 << 8);
+ temp2 |= (temp2 << 16);
+
+ *((uint32*)(dst - 16)) = temp1;
+ *((uint32*)(dst - 12)) = temp1;
+ *((uint32*)(dst - 8)) = temp1;
+ *((uint32*)(dst - 4)) = temp1;
+
+ *((uint32*)(dst += width)) = temp2;
+ *((uint32*)(dst + 4)) = temp2;
+ *((uint32*)(dst + 8)) = temp2;
+ *((uint32*)(dst + 12)) = temp2;
+
+ src += pitch;
+ dst = src;
+ }
+
+ /* pad bottom */
+ dst -= 16;
+ i = 16;
+ while (i--)
+ {
+ memcpy(dst, dst - pitch, pitch);
+ dst += pitch;
+ }
+
+
+ return ;
+}
+
+/*===========================================================================
+ Function: AVCRasterIntraUpdate
+ Date: 2/26/01
+ Purpose: To raster-scan assign INTRA-update .
+ N macroblocks are updated (also was programmable).
+===========================================================================*/
+void AVCRasterIntraUpdate(AVCEncObject *encvid, AVCMacroblock *mblock, int totalMB, int numRefresh)
+{
+ int indx, i;
+
+ indx = encvid->firstIntraRefreshMBIndx;
+ for (i = 0; i < numRefresh && indx < totalMB; i++)
+ {
+ (mblock + indx)->mb_intra = 1;
+ encvid->intraSearch[indx++] = 1;
+ }
+
+ /* if read the end of frame, reset and loop around */
+ if (indx >= totalMB - 1)
+ {
+ indx = 0;
+ while (i < numRefresh && indx < totalMB)
+ {
+ (mblock + indx)->mb_intra = 1;
+ encvid->intraSearch[indx++] = 1;
+ i++;
+ }
+ }
+
+ encvid->firstIntraRefreshMBIndx = indx; /* update with a new value */
+
+ return ;
+}
+
+
+#ifdef HTFM
+void InitHTFM(VideoEncData *encvid, HTFM_Stat *htfm_stat, double *newvar, int *collect)
+{
+ AVCCommonObj *video = encvid->common;
+ int i;
+ int lx = video->currPic->width; // padding
+ int lx2 = lx << 1;
+ int lx3 = lx2 + lx;
+ int rx = video->currPic->pitch;
+ int rx2 = rx << 1;
+ int rx3 = rx2 + rx;
+
+ int *offset, *offset2;
+
+ /* 4/11/01, collect data every 30 frames, doesn't have to be base layer */
+ if (((int)video->sliceHdr->frame_num) % 30 == 1)
+ {
+
+ *collect = 1;
+
+ htfm_stat->countbreak = 0;
+ htfm_stat->abs_dif_mad_avg = 0;
+
+ for (i = 0; i < 16; i++)
+ {
+ newvar[i] = 0.0;
+ }
+// encvid->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM_Collect;
+ encvid->functionPointer->SAD_Macroblock = &SAD_MB_HTFM_Collect;
+ encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
+ encvid->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFM_Collectxh;
+ encvid->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFM_Collectyh;
+ encvid->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFM_Collectxhyh;
+ encvid->sad_extra_info = (void*)(htfm_stat);
+ offset = htfm_stat->offsetArray;
+ offset2 = htfm_stat->offsetRef;
+ }
+ else
+ {
+// encvid->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM;
+ encvid->functionPointer->SAD_Macroblock = &SAD_MB_HTFM;
+ encvid->functionPointer->SAD_MB_HalfPel[0] = NULL;
+ encvid->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFMxh;
+ encvid->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFMyh;
+ encvid->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFMxhyh;
+ encvid->sad_extra_info = (void*)(encvid->nrmlz_th);
+ offset = encvid->nrmlz_th + 16;
+ offset2 = encvid->nrmlz_th + 32;
+ }
+
+ offset[0] = 0;
+ offset[1] = lx2 + 2;
+ offset[2] = 2;
+ offset[3] = lx2;
+ offset[4] = lx + 1;
+ offset[5] = lx3 + 3;
+ offset[6] = lx + 3;
+ offset[7] = lx3 + 1;
+ offset[8] = lx;
+ offset[9] = lx3 + 2;
+ offset[10] = lx3 ;
+ offset[11] = lx + 2 ;
+ offset[12] = 1;
+ offset[13] = lx2 + 3;
+ offset[14] = lx2 + 1;
+ offset[15] = 3;
+
+ offset2[0] = 0;
+ offset2[1] = rx2 + 2;
+ offset2[2] = 2;
+ offset2[3] = rx2;
+ offset2[4] = rx + 1;
+ offset2[5] = rx3 + 3;
+ offset2[6] = rx + 3;
+ offset2[7] = rx3 + 1;
+ offset2[8] = rx;
+ offset2[9] = rx3 + 2;
+ offset2[10] = rx3 ;
+ offset2[11] = rx + 2 ;
+ offset2[12] = 1;
+ offset2[13] = rx2 + 3;
+ offset2[14] = rx2 + 1;
+ offset2[15] = 3;
+
+ return ;
+}
+
+void UpdateHTFM(AVCEncObject *encvid, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat)
+{
+ if (htfm_stat->countbreak == 0)
+ htfm_stat->countbreak = 1;
+
+ newvar[0] = (double)(htfm_stat->abs_dif_mad_avg) / (htfm_stat->countbreak * 16.);
+
+ if (newvar[0] < 0.001)
+ {
+ newvar[0] = 0.001; /* to prevent floating overflow */
+ }
+ exp_lamda[0] = 1 / (newvar[0] * 1.4142136);
+ exp_lamda[1] = exp_lamda[0] * 1.5825;
+ exp_lamda[2] = exp_lamda[0] * 2.1750;
+ exp_lamda[3] = exp_lamda[0] * 3.5065;
+ exp_lamda[4] = exp_lamda[0] * 3.1436;
+ exp_lamda[5] = exp_lamda[0] * 3.5315;
+ exp_lamda[6] = exp_lamda[0] * 3.7449;
+ exp_lamda[7] = exp_lamda[0] * 4.5854;
+ exp_lamda[8] = exp_lamda[0] * 4.6191;
+ exp_lamda[9] = exp_lamda[0] * 5.4041;
+ exp_lamda[10] = exp_lamda[0] * 6.5974;
+ exp_lamda[11] = exp_lamda[0] * 10.5341;
+ exp_lamda[12] = exp_lamda[0] * 10.0719;
+ exp_lamda[13] = exp_lamda[0] * 12.0516;
+ exp_lamda[14] = exp_lamda[0] * 15.4552;
+
+ CalcThreshold(HTFM_Pf, exp_lamda, encvid->nrmlz_th);
+ return ;
+}
+
+
+void CalcThreshold(double pf, double exp_lamda[], int nrmlz_th[])
+{
+ int i;
+ double temp[15];
+ // printf("\nLamda: ");
+
+ /* parametric PREMODELling */
+ for (i = 0; i < 15; i++)
+ {
+ // printf("%g ",exp_lamda[i]);
+ if (pf < 0.5)
+ temp[i] = 1 / exp_lamda[i] * M4VENC_LOG(2 * pf);
+ else
+ temp[i] = -1 / exp_lamda[i] * M4VENC_LOG(2 * (1 - pf));
+ }
+
+ nrmlz_th[15] = 0;
+ for (i = 0; i < 15; i++) /* scale upto no.pixels */
+ nrmlz_th[i] = (int)(temp[i] * ((i + 1) << 4) + 0.5);
+
+ return ;
+}
+
+void HTFMPrepareCurMB_AVC(AVCEncObject *encvid, HTFM_Stat *htfm_stat, uint8 *cur, int pitch)
+{
+ AVCCommonObj *video = encvid->common;
+ uint32 *htfmMB = (uint32*)(encvid->currYMB);
+ uint8 *ptr, byte;
+ int *offset;
+ int i;
+ uint32 word;
+
+ if (((int)video->sliceHdr->frame_num) % 30 == 1)
+ {
+ offset = htfm_stat->offsetArray;
+ }
+ else
+ {
+ offset = encvid->nrmlz_th + 16;
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ ptr = cur + offset[i];
+ word = ptr[0];
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+
+ word = *(ptr += (pitch << 2));
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+
+ word = *(ptr += (pitch << 2));
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+
+ word = *(ptr += (pitch << 2));
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+ }
+
+ return ;
+}
+
+
+#endif // HTFM
+
+void AVCPrepareCurMB(AVCEncObject *encvid, uint8 *cur, int pitch)
+{
+ void* tmp = (void*)(encvid->currYMB);
+ uint32 *currYMB = (uint32*) tmp;
+ int i;
+
+ cur -= pitch;
+
+ for (i = 0; i < 16; i++)
+ {
+ *currYMB++ = *((uint32*)(cur += pitch));
+ *currYMB++ = *((uint32*)(cur + 4));
+ *currYMB++ = *((uint32*)(cur + 8));
+ *currYMB++ = *((uint32*)(cur + 12));
+ }
+
+ return ;
+}
+
+#ifdef FIXED_INTERPRED_MODE
+
+/* due to the complexity of the predicted motion vector, we may not decide to skip
+a macroblock here just yet. */
+/* We will find the best motion vector and the best intra prediction mode for each block. */
+/* output are
+ currMB->NumMbPart, currMB->MbPartWidth, currMB->MbPartHeight,
+ currMB->NumSubMbPart[], currMB->SubMbPartWidth[], currMB->SubMbPartHeight,
+ currMB->MBPartPredMode[][] (L0 or L1 or BiPred)
+ currMB->RefIdx[], currMB->ref_idx_L0[],
+ currMB->mvL0[], currMB->mvL1[]
+ */
+
+AVCEnc_Status AVCMBMotionSearch(AVCEncObject *encvid, AVCMacroblock *currMB, int mbNum,
+ int num_pass)
+{
+ AVCCommonObj *video = encvid->common;
+ int mbPartIdx, subMbPartIdx;
+ int16 *mv;
+ int i;
+ int SubMbPartHeight, SubMbPartWidth, NumSubMbPart;
+
+ /* assign value to currMB->MBPartPredMode[][x],subMbMode[],NumSubMbPart[],SubMbPartWidth[],SubMbPartHeight[] */
+
+ currMB->mbMode = FIXED_INTERPRED_MODE;
+ currMB->mb_intra = 0;
+
+ if (currMB->mbMode == AVC_P16)
+ {
+ currMB->NumMbPart = 1;
+ currMB->MbPartWidth = 16;
+ currMB->MbPartHeight = 16;
+ currMB->SubMbPartHeight[0] = 16;
+ currMB->SubMbPartWidth[0] = 16;
+ currMB->NumSubMbPart[0] = 1;
+ }
+ else if (currMB->mbMode == AVC_P16x8)
+ {
+ currMB->NumMbPart = 2;
+ currMB->MbPartWidth = 16;
+ currMB->MbPartHeight = 8;
+ for (i = 0; i < 2; i++)
+ {
+ currMB->SubMbPartWidth[i] = 16;
+ currMB->SubMbPartHeight[i] = 8;
+ currMB->NumSubMbPart[i] = 1;
+ }
+ }
+ else if (currMB->mbMode == AVC_P8x16)
+ {
+ currMB->NumMbPart = 2;
+ currMB->MbPartWidth = 8;
+ currMB->MbPartHeight = 16;
+ for (i = 0; i < 2; i++)
+ {
+ currMB->SubMbPartWidth[i] = 8;
+ currMB->SubMbPartHeight[i] = 16;
+ currMB->NumSubMbPart[i] = 1;
+ }
+ }
+ else if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
+ {
+ currMB->NumMbPart = 4;
+ currMB->MbPartWidth = 8;
+ currMB->MbPartHeight = 8;
+ if (FIXED_SUBMB_MODE == AVC_8x8)
+ {
+ SubMbPartHeight = 8;
+ SubMbPartWidth = 8;
+ NumSubMbPart = 1;
+ }
+ else if (FIXED_SUBMB_MODE == AVC_8x4)
+ {
+ SubMbPartHeight = 4;
+ SubMbPartWidth = 8;
+ NumSubMbPart = 2;
+ }
+ else if (FIXED_SUBMB_MODE == AVC_4x8)
+ {
+ SubMbPartHeight = 8;
+ SubMbPartWidth = 4;
+ NumSubMbPart = 2;
+ }
+ else if (FIXED_SUBMB_MODE == AVC_4x4)
+ {
+ SubMbPartHeight = 4;
+ SubMbPartWidth = 4;
+ NumSubMbPart = 4;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ currMB->subMbMode[i] = FIXED_SUBMB_MODE;
+ currMB->SubMbPartHeight[i] = SubMbPartHeight;
+ currMB->SubMbPartWidth[i] = SubMbPartWidth;
+ currMB->NumSubMbPart[i] = NumSubMbPart;
+ }
+ }
+ else /* it's probably intra mode */
+ {
+ return AVCENC_SUCCESS;
+ }
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ currMB->MBPartPredMode[mbPartIdx][0] = AVC_Pred_L0;
+ currMB->ref_idx_L0[mbPartIdx] = FIXED_REF_IDX;
+ currMB->RefIdx[mbPartIdx] = video->RefPicList0[FIXED_REF_IDX]->RefIdx;
+
+ for (subMbPartIdx = 0; subMbPartIdx < 4; subMbPartIdx++)
+ {
+ mv = (int16*)(currMB->mvL0 + (mbPartIdx << 2) + subMbPartIdx);
+
+ *mv++ = FIXED_MVX;
+ *mv = FIXED_MVY;
+ }
+ }
+
+ encvid->min_cost = 0;
+
+ return AVCENC_SUCCESS;
+}
+
+#else /* perform the search */
+
+/* This option #1 search is very similar to PV's MPEG4 motion search algorithm.
+ The search is done in hierarchical manner from 16x16 MB down to smaller and smaller
+ partition. At each level, a decision can be made to stop the search if the expected
+ prediction gain is not worth the computation. The decision can also be made at the finest
+ level for more fullsearch-like behavior with the price of heavier computation. */
+void AVCMBMotionSearch(AVCEncObject *encvid, uint8 *cur, uint8 *best_cand[],
+ int i0, int j0, int type_pred, int FS_en, int *hp_guess)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCPictureData *currPic = video->currPic;
+ AVCSeqParamSet *currSPS = video->currSeqParams;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ AVCMacroblock *currMB = video->currMB;
+ uint8 *ref, *cand, *ncand;
+ void *extra_info = encvid->sad_extra_info;
+ int mbnum = video->mbNum;
+ int width = currPic->width; /* 6/12/01, must be multiple of 16 */
+ int height = currPic->height;
+ AVCMV *mot16x16 = encvid->mot16x16;
+ int (*SAD_Macroblock)(uint8*, uint8*, int, void*) = encvid->functionPointer->SAD_Macroblock;
+
+ int range = rateCtrl->mvRange;
+
+ int lx = currPic->pitch; /* padding */
+ int i, j, imin, jmin, ilow, ihigh, jlow, jhigh;
+ int d, dmin, dn[9];
+ int k;
+ int mvx[5], mvy[5];
+ int num_can, center_again;
+ int last_loc, new_loc = 0;
+ int step, max_step = range >> 1;
+ int next;
+
+ int cmvx, cmvy; /* estimated predicted MV */
+ int lev_idx;
+ int lambda_motion = encvid->lambda_motion;
+ uint8 *mvbits = encvid->mvbits;
+ int mvshift = 2;
+ int mvcost;
+
+ int min_sad = 65535;
+
+ ref = video->RefPicList0[DEFAULT_REF_IDX]->Sl; /* origin of actual frame */
+
+ /* have to initialize these params, necessary for interprediction part */
+ currMB->NumMbPart = 1;
+ currMB->SubMbPartHeight[0] = 16;
+ currMB->SubMbPartWidth[0] = 16;
+ currMB->NumSubMbPart[0] = 1;
+ currMB->ref_idx_L0[0] = currMB->ref_idx_L0[1] =
+ currMB->ref_idx_L0[2] = currMB->ref_idx_L0[3] = DEFAULT_REF_IDX;
+ currMB->ref_idx_L1[0] = currMB->ref_idx_L1[1] =
+ currMB->ref_idx_L1[2] = currMB->ref_idx_L1[3] = DEFAULT_REF_IDX;
+ currMB->RefIdx[0] = currMB->RefIdx[1] =
+ currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[DEFAULT_REF_IDX]->RefIdx;
+
+ cur = encvid->currYMB; /* use smaller memory space for current MB */
+
+ /* find limit of the search (adjusting search range)*/
+ lev_idx = mapLev2Idx[currSPS->level_idc];
+
+ /* we can make this part dynamic based on previous statistics */
+ ilow = i0 - range;
+ if (i0 - ilow > 2047) /* clip to conform with the standard */
+ {
+ ilow = i0 - 2047;
+ }
+ if (ilow < -13) // change it from -15 to -13 because of 6-tap filter needs extra 2 lines.
+ {
+ ilow = -13;
+ }
+
+ ihigh = i0 + range - 1;
+ if (ihigh - i0 > 2047) /* clip to conform with the standard */
+ {
+ ihigh = i0 + 2047;
+ }
+ if (ihigh > width - 3)
+ {
+ ihigh = width - 3; // change from width-1 to width-3 for the same reason as above
+ }
+
+ jlow = j0 - range;
+ if (j0 - jlow > MaxVmvR[lev_idx] - 1) /* clip to conform with the standard */
+ {
+ jlow = j0 - MaxVmvR[lev_idx] + 1;
+ }
+ if (jlow < -13) // same reason as above
+ {
+ jlow = -13;
+ }
+
+ jhigh = j0 + range - 1;
+ if (jhigh - j0 > MaxVmvR[lev_idx] - 1) /* clip to conform with the standard */
+ {
+ jhigh = j0 + MaxVmvR[lev_idx] - 1;
+ }
+ if (jhigh > height - 3) // same reason as above
+ {
+ jhigh = height - 3;
+ }
+
+ /* find initial motion vector & predicted MV*/
+ AVCCandidateSelection(mvx, mvy, &num_can, i0 >> 4, j0 >> 4, encvid, type_pred, &cmvx, &cmvy);
+
+ imin = i0;
+ jmin = j0; /* needed for fullsearch */
+ ncand = ref + i0 + j0 * lx;
+
+ /* for first row of MB, fullsearch can be used */
+ if (FS_en)
+ {
+ *hp_guess = 0; /* no guess for fast half-pel */
+
+ dmin = AVCFullSearch(encvid, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh, cmvx, cmvy);
+
+ ncand = ref + imin + jmin * lx;
+ }
+ else
+ { /* fullsearch the top row to only upto (0,3) MB */
+ /* upto 30% complexity saving with the same complexity */
+ if (video->PrevRefFrameNum == 0 && j0 == 0 && i0 <= 64 && type_pred != 1)
+ {
+ *hp_guess = 0; /* no guess for fast half-pel */
+ dmin = AVCFullSearch(encvid, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh, cmvx, cmvy);
+ ncand = ref + imin + jmin * lx;
+ }
+ else
+ {
+ /************** initialize candidate **************************/
+
+ dmin = 65535;
+
+ /* check if all are equal */
+ if (num_can == ALL_CAND_EQUAL)
+ {
+ i = i0 + mvx[0];
+ j = j0 + mvy[0];
+
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ cand = ref + i + j * lx;
+
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+ mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+ d += mvcost;
+
+ if (d < dmin)
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ ncand = cand;
+ min_sad = d - mvcost; // for rate control
+ }
+ }
+ }
+ else
+ {
+ /************** evaluate unique candidates **********************/
+ for (k = 0; k < num_can; k++)
+ {
+ i = i0 + mvx[k];
+ j = j0 + mvy[k];
+
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ cand = ref + i + j * lx;
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+ mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+ d += mvcost;
+
+ if (d < dmin)
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ ncand = cand;
+ min_sad = d - mvcost; // for rate control
+ }
+ }
+ }
+ }
+
+ /******************* local refinement ***************************/
+ center_again = 0;
+ last_loc = new_loc = 0;
+ // ncand = ref + jmin*lx + imin; /* center of the search */
+ step = 0;
+ dn[0] = dmin;
+ while (!center_again && step <= max_step)
+ {
+
+ AVCMoveNeighborSAD(dn, last_loc);
+
+ center_again = 1;
+ i = imin;
+ j = jmin - 1;
+ cand = ref + i + j * lx;
+
+ /* starting from [0,-1] */
+ /* spiral check one step at a time*/
+ for (k = 2; k <= 8; k += 2)
+ {
+ if (!tab_exclude[last_loc][k]) /* exclude last step computation */
+ { /* not already computed */
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+ mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+ d += mvcost;
+
+ dn[k] = d; /* keep it for half pel use */
+
+ if (d < dmin)
+ {
+ ncand = cand;
+ dmin = d;
+ imin = i;
+ jmin = j;
+ center_again = 0;
+ new_loc = k;
+ min_sad = d - mvcost; // for rate control
+ }
+ }
+ }
+ if (k == 8) /* end side search*/
+ {
+ if (!center_again)
+ {
+ k = -1; /* start diagonal search */
+ cand -= lx;
+ j--;
+ }
+ }
+ else
+ {
+ next = refine_next[k][0];
+ i += next;
+ cand += next;
+ next = refine_next[k][1];
+ j += next;
+ cand += lx * next;
+ }
+ }
+ last_loc = new_loc;
+ step ++;
+ }
+ if (!center_again)
+ AVCMoveNeighborSAD(dn, last_loc);
+
+ *hp_guess = AVCFindMin(dn);
+
+ encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
+ }
+ }
+
+ mot16x16[mbnum].sad = dmin;
+ mot16x16[mbnum].x = (imin - i0) << 2;
+ mot16x16[mbnum].y = (jmin - j0) << 2;
+ best_cand[0] = ncand;
+
+ if (rateCtrl->subPelEnable) // always enable half-pel search
+ {
+ /* find half-pel resolution motion vector */
+ min_sad = AVCFindHalfPelMB(encvid, cur, mot16x16 + mbnum, best_cand[0], i0, j0, *hp_guess, cmvx, cmvy);
+
+ encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
+
+
+ if (encvid->best_qpel_pos == -1)
+ {
+ ncand = encvid->hpel_cand[encvid->best_hpel_pos];
+ }
+ else
+ {
+ ncand = encvid->qpel_cand[encvid->best_qpel_pos];
+ }
+ }
+ else
+ {
+ encvid->rateCtrl->MADofMB[mbnum] = min_sad / 256.0;
+ }
+
+ /** do motion comp here for now */
+ ref = currPic->Sl + i0 + j0 * lx;
+ /* copy from the best result to current Picture */
+ for (j = 0; j < 16; j++)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ *ref++ = *ncand++;
+ }
+ ref += (lx - 16);
+ ncand += 8;
+ }
+
+ return ;
+}
+
+#endif
+
+/*===============================================================================
+ Function: AVCFullSearch
+ Date: 09/16/2000
+ Purpose: Perform full-search motion estimation over the range of search
+ region in a spiral-outward manner.
+ Input/Output: VideoEncData, current Vol, previou Vop, pointer to the left corner of
+ current VOP, current coord (also output), boundaries.
+===============================================================================*/
+int AVCFullSearch(AVCEncObject *encvid, uint8 *prev, uint8 *cur,
+ int *imin, int *jmin, int ilow, int ihigh, int jlow, int jhigh,
+ int cmvx, int cmvy)
+{
+ int range = encvid->rateCtrl->mvRange;
+ AVCPictureData *currPic = encvid->common->currPic;
+ uint8 *cand;
+ int i, j, k, l;
+ int d, dmin;
+ int i0 = *imin; /* current position */
+ int j0 = *jmin;
+ int (*SAD_Macroblock)(uint8*, uint8*, int, void*) = encvid->functionPointer->SAD_Macroblock;
+ void *extra_info = encvid->sad_extra_info;
+ int lx = currPic->pitch; /* with padding */
+
+ int offset = i0 + j0 * lx;
+
+ int lambda_motion = encvid->lambda_motion;
+ uint8 *mvbits = encvid->mvbits;
+ int mvshift = 2;
+ int mvcost;
+ int min_sad;
+
+ cand = prev + offset;
+
+ dmin = (*SAD_Macroblock)(cand, cur, (65535 << 16) | lx, (void*)extra_info);
+ mvcost = MV_COST(lambda_motion, mvshift, 0, 0, cmvx, cmvy);
+ min_sad = dmin;
+ dmin += mvcost;
+
+ /* perform spiral search */
+ for (k = 1; k <= range; k++)
+ {
+
+ i = i0 - k;
+ j = j0 - k;
+
+ cand = prev + i + j * lx;
+
+ for (l = 0; l < 8*k; l++)
+ {
+ /* no need for boundary checking again */
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, (void*)extra_info);
+ mvcost = MV_COST(lambda_motion, mvshift, i - i0, j - j0, cmvx, cmvy);
+ d += mvcost;
+
+ if (d < dmin)
+ {
+ dmin = d;
+ *imin = i;
+ *jmin = j;
+ min_sad = d - mvcost;
+ }
+ }
+
+ if (l < (k << 1))
+ {
+ i++;
+ cand++;
+ }
+ else if (l < (k << 2))
+ {
+ j++;
+ cand += lx;
+ }
+ else if (l < ((k << 2) + (k << 1)))
+ {
+ i--;
+ cand--;
+ }
+ else
+ {
+ j--;
+ cand -= lx;
+ }
+ }
+ }
+
+ encvid->rateCtrl->MADofMB[encvid->common->mbNum] = (min_sad / 256.0); // for rate control
+
+ return dmin;
+}
+
+/*===============================================================================
+ Function: AVCCandidateSelection
+ Date: 09/16/2000
+ Purpose: Fill up the list of candidate using spatio-temporal correlation
+ among neighboring blocks.
+ Input/Output: type_pred = 0: first pass, 1: second pass, or no SCD
+ Modified: , 09/23/01, get rid of redundant candidates before passing back.
+ , 09/11/07, added return for modified predicted MV, this will be
+ needed for both fast search and fullsearch.
+===============================================================================*/
+
+void AVCCandidateSelection(int *mvx, int *mvy, int *num_can, int imb, int jmb,
+ AVCEncObject *encvid, int type_pred, int *cmvx, int *cmvy)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCMV *mot16x16 = encvid->mot16x16;
+ AVCMV *pmot;
+ int mbnum = video->mbNum;
+ int mbwidth = video->PicWidthInMbs;
+ int mbheight = video->PicHeightInMbs;
+ int i, j, same, num1;
+
+ /* this part is for predicted MV */
+ int pmvA_x = 0, pmvA_y = 0, pmvB_x = 0, pmvB_y = 0, pmvC_x = 0, pmvC_y = 0;
+ int availA = 0, availB = 0, availC = 0;
+
+ *num_can = 0;
+
+ if (video->PrevRefFrameNum != 0) // previous frame is an IDR frame
+ {
+ /* Spatio-Temporal Candidate (five candidates) */
+ if (type_pred == 0) /* first pass */
+ {
+ pmot = &mot16x16[mbnum]; /* same coordinate previous frame */
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ if (imb >= (mbwidth >> 1) && imb > 0) /*left neighbor previous frame */
+ {
+ pmot = &mot16x16[mbnum-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ else if (imb + 1 < mbwidth) /*right neighbor previous frame */
+ {
+ pmot = &mot16x16[mbnum+1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+
+ if (jmb < mbheight - 1) /*bottom neighbor previous frame */
+ {
+ pmot = &mot16x16[mbnum+mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ else if (jmb > 0) /*upper neighbor previous frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+
+ if (imb > 0 && jmb > 0) /* upper-left neighbor current frame*/
+ {
+ pmot = &mot16x16[mbnum-mbwidth-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (jmb > 0 && imb < mbheight - 1) /* upper right neighbor current frame*/
+ {
+ pmot = &mot16x16[mbnum-mbwidth+1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ }
+ else /* second pass */
+ /* original ST1 algorithm */
+ {
+ pmot = &mot16x16[mbnum]; /* same coordinate previous frame */
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+
+ if (imb > 0) /*left neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (jmb > 0) /*upper neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (imb < mbwidth - 1) /*right neighbor previous frame */
+ {
+ pmot = &mot16x16[mbnum+1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (jmb < mbheight - 1) /*bottom neighbor previous frame */
+ {
+ pmot = &mot16x16[mbnum+mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ }
+
+ /* get predicted MV */
+ if (imb > 0) /* get MV from left (A) neighbor either on current or previous frame */
+ {
+ availA = 1;
+ pmot = &mot16x16[mbnum-1];
+ pmvA_x = pmot->x;
+ pmvA_y = pmot->y;
+ }
+
+ if (jmb > 0) /* get MV from top (B) neighbor either on current or previous frame */
+ {
+ availB = 1;
+ pmot = &mot16x16[mbnum-mbwidth];
+ pmvB_x = pmot->x;
+ pmvB_y = pmot->y;
+
+ availC = 1;
+
+ if (imb < mbwidth - 1) /* get MV from top-right (C) neighbor of current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth+1];
+ }
+ else /* get MV from top-left (D) neighbor of current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth-1];
+ }
+ pmvC_x = pmot->x;
+ pmvC_y = pmot->y;
+ }
+
+ }
+ else /* only Spatial Candidate (four candidates)*/
+ {
+ if (type_pred == 0) /*first pass*/
+ {
+ if (imb > 1) /* neighbor two blocks away to the left */
+ {
+ pmot = &mot16x16[mbnum-2];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (imb > 0 && jmb > 0) /* upper-left neighbor */
+ {
+ pmot = &mot16x16[mbnum-mbwidth-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (jmb > 0 && imb < mbheight - 1) /* upper right neighbor */
+ {
+ pmot = &mot16x16[mbnum-mbwidth+1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+
+ /* get predicted MV */
+ if (imb > 1) /* get MV from 2nd left (A) neighbor either of current frame */
+ {
+ availA = 1;
+ pmot = &mot16x16[mbnum-2];
+ pmvA_x = pmot->x;
+ pmvA_y = pmot->y;
+ }
+
+ if (jmb > 0 && imb > 0) /* get MV from top-left (B) neighbor of current frame */
+ {
+ availB = 1;
+ pmot = &mot16x16[mbnum-mbwidth-1];
+ pmvB_x = pmot->x;
+ pmvB_y = pmot->y;
+ }
+
+ if (jmb > 0 && imb < mbwidth - 1)
+ {
+ availC = 1;
+ pmot = &mot16x16[mbnum-mbwidth+1];
+ pmvC_x = pmot->x;
+ pmvC_y = pmot->y;
+ }
+ }
+//#ifdef SCENE_CHANGE_DETECTION
+ /* second pass (ST2 algorithm)*/
+ else
+ {
+ if (type_pred == 1) /* 4/7/01 */
+ {
+ if (imb > 0) /*left neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (jmb > 0) /*upper neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (imb < mbwidth - 1) /*right neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum+1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ if (jmb < mbheight - 1) /*bottom neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum+mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ }
+ //#else
+ else /* original ST1 algorithm */
+ {
+ if (imb > 0) /*left neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+
+ if (jmb > 0) /*upper-left neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth-1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+
+ }
+ if (jmb > 0) /*upper neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+
+ if (imb < mbheight - 1) /*upper-right neighbor current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth+1];
+ mvx[(*num_can)] = (pmot->x) >> 2;
+ mvy[(*num_can)++] = (pmot->y) >> 2;
+ }
+ }
+ }
+
+ /* get predicted MV */
+ if (imb > 0) /* get MV from left (A) neighbor either on current or previous frame */
+ {
+ availA = 1;
+ pmot = &mot16x16[mbnum-1];
+ pmvA_x = pmot->x;
+ pmvA_y = pmot->y;
+ }
+
+ if (jmb > 0) /* get MV from top (B) neighbor either on current or previous frame */
+ {
+ availB = 1;
+ pmot = &mot16x16[mbnum-mbwidth];
+ pmvB_x = pmot->x;
+ pmvB_y = pmot->y;
+
+ availC = 1;
+
+ if (imb < mbwidth - 1) /* get MV from top-right (C) neighbor of current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth+1];
+ }
+ else /* get MV from top-left (D) neighbor of current frame */
+ {
+ pmot = &mot16x16[mbnum-mbwidth-1];
+ }
+ pmvC_x = pmot->x;
+ pmvC_y = pmot->y;
+ }
+ }
+//#endif
+ }
+
+ /* 3/23/01, remove redundant candidate (possible k-mean) */
+ num1 = *num_can;
+ *num_can = 1;
+ for (i = 1; i < num1; i++)
+ {
+ same = 0;
+ j = 0;
+ while (!same && j < *num_can)
+ {
+#if (CANDIDATE_DISTANCE==0)
+ if (mvx[i] == mvx[j] && mvy[i] == mvy[j])
+#else
+ // modified k-mean, 3/24/01, shouldn't be greater than 3
+ if (AVC_ABS(mvx[i] - mvx[j]) + AVC_ABS(mvy[i] - mvy[j]) < CANDIDATE_DISTANCE)
+#endif
+ same = 1;
+ j++;
+ }
+ if (!same)
+ {
+ mvx[*num_can] = mvx[i];
+ mvy[*num_can] = mvy[i];
+ (*num_can)++;
+ }
+ }
+
+ if (num1 == 5 && *num_can == 1)
+ *num_can = ALL_CAND_EQUAL; /* all are equal */
+
+ /* calculate predicted MV */
+
+ if (availA && !(availB || availC))
+ {
+ *cmvx = pmvA_x;
+ *cmvy = pmvA_y;
+ }
+ else
+ {
+ *cmvx = AVC_MEDIAN(pmvA_x, pmvB_x, pmvC_x);
+ *cmvy = AVC_MEDIAN(pmvA_y, pmvB_y, pmvC_y);
+ }
+
+ return ;
+}
+
+
+/*************************************************************
+ Function: AVCMoveNeighborSAD
+ Date: 3/27/01
+ Purpose: Move neighboring SAD around when center has shifted
+*************************************************************/
+
+void AVCMoveNeighborSAD(int dn[], int new_loc)
+{
+ int tmp[9];
+ tmp[0] = dn[0];
+ tmp[1] = dn[1];
+ tmp[2] = dn[2];
+ tmp[3] = dn[3];
+ tmp[4] = dn[4];
+ tmp[5] = dn[5];
+ tmp[6] = dn[6];
+ tmp[7] = dn[7];
+ tmp[8] = dn[8];
+ dn[0] = dn[1] = dn[2] = dn[3] = dn[4] = dn[5] = dn[6] = dn[7] = dn[8] = 65536;
+
+ switch (new_loc)
+ {
+ case 0:
+ break;
+ case 1:
+ dn[4] = tmp[2];
+ dn[5] = tmp[0];
+ dn[6] = tmp[8];
+ break;
+ case 2:
+ dn[4] = tmp[3];
+ dn[5] = tmp[4];
+ dn[6] = tmp[0];
+ dn[7] = tmp[8];
+ dn[8] = tmp[1];
+ break;
+ case 3:
+ dn[6] = tmp[4];
+ dn[7] = tmp[0];
+ dn[8] = tmp[2];
+ break;
+ case 4:
+ dn[1] = tmp[2];
+ dn[2] = tmp[3];
+ dn[6] = tmp[5];
+ dn[7] = tmp[6];
+ dn[8] = tmp[0];
+ break;
+ case 5:
+ dn[1] = tmp[0];
+ dn[2] = tmp[4];
+ dn[8] = tmp[6];
+ break;
+ case 6:
+ dn[1] = tmp[8];
+ dn[2] = tmp[0];
+ dn[3] = tmp[4];
+ dn[4] = tmp[5];
+ dn[8] = tmp[7];
+ break;
+ case 7:
+ dn[2] = tmp[8];
+ dn[3] = tmp[0];
+ dn[4] = tmp[6];
+ break;
+ case 8:
+ dn[2] = tmp[1];
+ dn[3] = tmp[2];
+ dn[4] = tmp[0];
+ dn[5] = tmp[6];
+ dn[6] = tmp[7];
+ break;
+ }
+ dn[0] = tmp[new_loc];
+
+ return ;
+}
+
+/* 3/28/01, find minimal of dn[9] */
+
+int AVCFindMin(int dn[])
+{
+ int min, i;
+ int dmin;
+
+ dmin = dn[1];
+ min = 1;
+ for (i = 2; i < 9; i++)
+ {
+ if (dn[i] < dmin)
+ {
+ dmin = dn[i];
+ min = i;
+ }
+ }
+
+ return min;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/rate_control.cpp b/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
new file mode 100644
index 0000000..15b55fb
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/rate_control.cpp
@@ -0,0 +1,981 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include <math.h>
+
+/* rate control variables */
+#define RC_MAX_QUANT 51
+#define RC_MIN_QUANT 0 //cap to 10 to prevent rate fluctuation
+
+#define MAD_MIN 1 /* handle the case of devision by zero in RC */
+
+
+/* local functions */
+double QP2Qstep(int QP);
+int Qstep2QP(double Qstep);
+
+double ComputeFrameMAD(AVCCommonObj *video, AVCRateControl *rateCtrl);
+
+void targetBitCalculation(AVCEncObject *encvid, AVCCommonObj *video, AVCRateControl *rateCtrl, MultiPass *pMP);
+
+void calculateQuantizer_Multipass(AVCEncObject *encvid, AVCCommonObj *video,
+ AVCRateControl *rateCtrl, MultiPass *pMP);
+
+void updateRC_PostProc(AVCRateControl *rateCtrl, MultiPass *pMP);
+
+void AVCSaveRDSamples(MultiPass *pMP, int counter_samples);
+
+void updateRateControl(AVCRateControl *rateControl, int nal_type);
+
+int GetAvgFrameQP(AVCRateControl *rateCtrl)
+{
+ return rateCtrl->Qc;
+}
+
+AVCEnc_Status RCDetermineFrameNum(AVCEncObject *encvid, AVCRateControl *rateCtrl, uint32 modTime, uint *frameNum)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ uint32 modTimeRef = encvid->modTimeRef;
+ int32 currFrameNum ;
+ int frameInc;
+
+
+ /* check with the buffer fullness to make sure that we have enough bits to encode this frame */
+ /* we can use a threshold to guarantee minimum picture quality */
+ /**********************************/
+
+ /* for now, the default is to encode every frame, To Be Changed */
+ if (rateCtrl->first_frame)
+ {
+ encvid->modTimeRef = modTime;
+ encvid->wrapModTime = 0;
+ encvid->prevFrameNum = 0;
+ encvid->prevProcFrameNum = 0;
+
+ *frameNum = 0;
+
+ /* set frame type to IDR-frame */
+ video->nal_unit_type = AVC_NALTYPE_IDR;
+ sliceHdr->slice_type = AVC_I_ALL_SLICE;
+ video->slice_type = AVC_I_SLICE;
+
+ return AVCENC_SUCCESS;
+ }
+ else
+ {
+ if (modTime < modTimeRef) /* modTime wrapped around */
+ {
+ encvid->wrapModTime += ((uint32)0xFFFFFFFF - modTimeRef) + 1;
+ encvid->modTimeRef = modTimeRef = 0;
+ }
+ modTime += encvid->wrapModTime; /* wrapModTime is non zero after wrap-around */
+
+ currFrameNum = (int32)(((modTime - modTimeRef) * rateCtrl->frame_rate + 200) / 1000); /* add small roundings */
+
+ if (currFrameNum <= (int32)encvid->prevProcFrameNum)
+ {
+ return AVCENC_FAIL; /* this is a late frame do not encode it */
+ }
+
+ frameInc = currFrameNum - encvid->prevProcFrameNum;
+
+ if (frameInc < rateCtrl->skip_next_frame + 1)
+ {
+ return AVCENC_FAIL; /* frame skip required to maintain the target bit rate. */
+ }
+
+ RCUpdateBuffer(video, rateCtrl, frameInc - rateCtrl->skip_next_frame); /* in case more frames dropped */
+
+ *frameNum = currFrameNum;
+
+ /* This part would be similar to DetermineVopType of m4venc */
+ if ((*frameNum >= (uint)rateCtrl->idrPeriod && rateCtrl->idrPeriod > 0) || (*frameNum > video->MaxFrameNum)) /* first frame or IDR*/
+ {
+ /* set frame type to IDR-frame */
+ if (rateCtrl->idrPeriod)
+ {
+ encvid->modTimeRef += (uint32)(rateCtrl->idrPeriod * 1000 / rateCtrl->frame_rate);
+ *frameNum -= rateCtrl->idrPeriod;
+ }
+ else
+ {
+ encvid->modTimeRef += (uint32)(video->MaxFrameNum * 1000 / rateCtrl->frame_rate);
+ *frameNum -= video->MaxFrameNum;
+ }
+
+ video->nal_unit_type = AVC_NALTYPE_IDR;
+ sliceHdr->slice_type = AVC_I_ALL_SLICE;
+ video->slice_type = AVC_I_SLICE;
+ encvid->prevProcFrameNum = *frameNum;
+ }
+ else
+ {
+ video->nal_unit_type = AVC_NALTYPE_SLICE;
+ sliceHdr->slice_type = AVC_P_ALL_SLICE;
+ video->slice_type = AVC_P_SLICE;
+ encvid->prevProcFrameNum = currFrameNum;
+ }
+
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+void RCUpdateBuffer(AVCCommonObj *video, AVCRateControl *rateCtrl, int frameInc)
+{
+ int tmp;
+ MultiPass *pMP = rateCtrl->pMP;
+
+ OSCL_UNUSED_ARG(video);
+
+ if (rateCtrl->rcEnable == TRUE)
+ {
+ if (frameInc > 1)
+ {
+ tmp = rateCtrl->bitsPerFrame * (frameInc - 1);
+ rateCtrl->VBV_fullness -= tmp;
+ pMP->counter_BTsrc += 10 * (frameInc - 1);
+
+ /* Check buffer underflow */
+ if (rateCtrl->VBV_fullness < rateCtrl->low_bound)
+ {
+ rateCtrl->VBV_fullness = rateCtrl->low_bound; // -rateCtrl->Bs/2;
+ rateCtrl->TMN_W = rateCtrl->VBV_fullness - rateCtrl->low_bound;
+ pMP->counter_BTsrc = pMP->counter_BTdst + (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+ }
+ }
+ }
+}
+
+
+AVCEnc_Status InitRateControlModule(AVCHandle *avcHandle)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+ AVCCommonObj *video = encvid->common;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ double L1, L2, L3, bpp;
+ int qp;
+ int i, j;
+
+ rateCtrl->basicUnit = video->PicSizeInMbs;
+
+ rateCtrl->MADofMB = (double*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData,
+ video->PicSizeInMbs * sizeof(double), DEFAULT_ATTR);
+
+ if (!rateCtrl->MADofMB)
+ {
+ goto CLEANUP_RC;
+ }
+
+ if (rateCtrl->rcEnable == TRUE)
+ {
+ rateCtrl->pMP = (MultiPass*) avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, sizeof(MultiPass), DEFAULT_ATTR);
+ if (!rateCtrl->pMP)
+ {
+ goto CLEANUP_RC;
+ }
+ memset(rateCtrl->pMP, 0, sizeof(MultiPass));
+ rateCtrl->pMP->encoded_frames = -1; /* forget about the very first I frame */
+
+ /* RDInfo **pRDSamples */
+ rateCtrl->pMP->pRDSamples = (RDInfo **)avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, (30 * sizeof(RDInfo *)), DEFAULT_ATTR);
+ if (!rateCtrl->pMP->pRDSamples)
+ {
+ goto CLEANUP_RC;
+ }
+
+ for (i = 0; i < 30; i++)
+ {
+ rateCtrl->pMP->pRDSamples[i] = (RDInfo *)avcHandle->CBAVC_Malloc(encvid->avcHandle->userData, (32 * sizeof(RDInfo)), DEFAULT_ATTR);
+ if (!rateCtrl->pMP->pRDSamples[i])
+ {
+ goto CLEANUP_RC;
+ }
+ for (j = 0; j < 32; j++) memset(&(rateCtrl->pMP->pRDSamples[i][j]), 0, sizeof(RDInfo));
+ }
+ rateCtrl->pMP->frameRange = (int)(rateCtrl->frame_rate * 1.0); /* 1.0s time frame*/
+ rateCtrl->pMP->frameRange = AVC_MAX(rateCtrl->pMP->frameRange, 5);
+ rateCtrl->pMP->frameRange = AVC_MIN(rateCtrl->pMP->frameRange, 30);
+
+ rateCtrl->pMP->framePos = -1;
+
+
+ rateCtrl->bitsPerFrame = (int32)(rateCtrl->bitRate / rateCtrl->frame_rate);
+
+ /* BX rate control */
+ rateCtrl->skip_next_frame = 0; /* must be initialized */
+
+ rateCtrl->Bs = rateCtrl->cpbSize;
+ rateCtrl->TMN_W = 0;
+ rateCtrl->VBV_fullness = (int)(rateCtrl->Bs * 0.5); /* rateCtrl->Bs */
+ rateCtrl->encoded_frames = 0;
+
+ rateCtrl->TMN_TH = rateCtrl->bitsPerFrame;
+
+ rateCtrl->max_BitVariance_num = (int)((OsclFloat)(rateCtrl->Bs - rateCtrl->VBV_fullness) / (rateCtrl->bitsPerFrame / 10.0)) - 5;
+ if (rateCtrl->max_BitVariance_num < 0) rateCtrl->max_BitVariance_num += 5;
+
+ // Set the initial buffer fullness
+ /* According to the spec, the initial buffer fullness needs to be set to 1/3 */
+ rateCtrl->VBV_fullness = (int)(rateCtrl->Bs / 3.0 - rateCtrl->Bs / 2.0); /* the buffer range is [-Bs/2, Bs/2] */
+ rateCtrl->pMP->counter_BTsrc = (int)((rateCtrl->Bs / 2.0 - rateCtrl->Bs / 3.0) / (rateCtrl->bitsPerFrame / 10.0));
+ rateCtrl->TMN_W = (int)(rateCtrl->VBV_fullness + rateCtrl->pMP->counter_BTsrc * (rateCtrl->bitsPerFrame / 10.0));
+
+ rateCtrl->low_bound = -rateCtrl->Bs / 2;
+ rateCtrl->VBV_fullness_offset = 0;
+
+ /* Setting the bitrate and framerate */
+ rateCtrl->pMP->bitrate = rateCtrl->bitRate;
+ rateCtrl->pMP->framerate = rateCtrl->frame_rate;
+ rateCtrl->pMP->target_bits_per_frame = rateCtrl->pMP->bitrate / rateCtrl->pMP->framerate;
+
+ /*compute the initial QP*/
+ bpp = 1.0 * rateCtrl->bitRate / (rateCtrl->frame_rate * (video->PicSizeInMbs << 8));
+ if (video->PicWidthInSamplesL == 176)
+ {
+ L1 = 0.1;
+ L2 = 0.3;
+ L3 = 0.6;
+ }
+ else if (video->PicWidthInSamplesL == 352)
+ {
+ L1 = 0.2;
+ L2 = 0.6;
+ L3 = 1.2;
+ }
+ else
+ {
+ L1 = 0.6;
+ L2 = 1.4;
+ L3 = 2.4;
+ }
+
+ if (rateCtrl->initQP == 0)
+ {
+ if (bpp <= L1)
+ qp = 35;
+ else if (bpp <= L2)
+ qp = 25;
+ else if (bpp <= L3)
+ qp = 20;
+ else
+ qp = 15;
+ rateCtrl->initQP = qp;
+ }
+
+ rateCtrl->Qc = rateCtrl->initQP;
+ }
+
+ return AVCENC_SUCCESS;
+
+CLEANUP_RC:
+
+ CleanupRateControlModule(avcHandle);
+ return AVCENC_MEMORY_FAIL;
+
+}
+
+
+void CleanupRateControlModule(AVCHandle *avcHandle)
+{
+ AVCEncObject *encvid = (AVCEncObject*) avcHandle->AVCObject;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ int i;
+
+ if (rateCtrl->MADofMB)
+ {
+ avcHandle->CBAVC_Free(avcHandle->userData, (int)(rateCtrl->MADofMB));
+ }
+
+ if (rateCtrl->pMP)
+ {
+ if (rateCtrl->pMP->pRDSamples)
+ {
+ for (i = 0; i < 30; i++)
+ {
+ if (rateCtrl->pMP->pRDSamples[i])
+ {
+ avcHandle->CBAVC_Free(avcHandle->userData, (int)rateCtrl->pMP->pRDSamples[i]);
+ }
+ }
+ avcHandle->CBAVC_Free(avcHandle->userData, (int)rateCtrl->pMP->pRDSamples);
+ }
+ avcHandle->CBAVC_Free(avcHandle->userData, (int)(rateCtrl->pMP));
+ }
+
+ return ;
+}
+
+void RCInitGOP(AVCEncObject *encvid)
+{
+ /* in BX RC, there's no GOP-level RC */
+
+ OSCL_UNUSED_ARG(encvid);
+
+ return ;
+}
+
+
+void RCInitFrameQP(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ AVCPicParamSet *picParam = video->currPicParams;
+ MultiPass *pMP = rateCtrl->pMP;
+
+ if (rateCtrl->rcEnable == TRUE)
+ {
+ /* frame layer rate control */
+ if (rateCtrl->encoded_frames == 0)
+ {
+ video->QPy = rateCtrl->Qc = rateCtrl->initQP;
+ }
+ else
+ {
+ calculateQuantizer_Multipass(encvid, video, rateCtrl, pMP);
+ video->QPy = rateCtrl->Qc;
+ }
+
+ rateCtrl->NumberofHeaderBits = 0;
+ rateCtrl->NumberofTextureBits = 0;
+ rateCtrl->numFrameBits = 0; // reset
+
+ /* update pMP->framePos */
+ if (++pMP->framePos == pMP->frameRange) pMP->framePos = 0;
+
+ if (rateCtrl->T == 0)
+ {
+ pMP->counter_BTdst = (int)(rateCtrl->frame_rate * 7.5 + 0.5); /* 0.75s time frame */
+ pMP->counter_BTdst = AVC_MIN(pMP->counter_BTdst, (int)(rateCtrl->max_BitVariance_num / 2 * 0.40)); /* 0.75s time frame may go beyond VBV buffer if we set the buffer size smaller than 0.75s */
+ pMP->counter_BTdst = AVC_MAX(pMP->counter_BTdst, (int)((rateCtrl->Bs / 2 - rateCtrl->VBV_fullness) * 0.30 / (rateCtrl->TMN_TH / 10.0) + 0.5)); /* At least 30% of VBV buffer size/2 */
+ pMP->counter_BTdst = AVC_MIN(pMP->counter_BTdst, 20); /* Limit the target to be smaller than 3C */
+
+ pMP->target_bits = rateCtrl->T = rateCtrl->TMN_TH = (int)(rateCtrl->TMN_TH * (1.0 + pMP->counter_BTdst * 0.1));
+ pMP->diff_counter = pMP->counter_BTdst;
+ }
+
+ /* collect the necessary data: target bits, actual bits, mad and QP */
+ pMP->target_bits = rateCtrl->T;
+ pMP->QP = video->QPy;
+
+ pMP->mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs; //ComputeFrameMAD(video, rateCtrl);
+ if (pMP->mad < MAD_MIN) pMP->mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+
+ pMP->bitrate = rateCtrl->bitRate; /* calculated in RCVopQPSetting */
+ pMP->framerate = rateCtrl->frame_rate;
+
+ /* first pass encoding */
+ pMP->nRe_Quantized = 0;
+
+ } // rcEnable
+ else
+ {
+ video->QPy = rateCtrl->initQP;
+ }
+
+// printf(" %d ",video->QPy);
+
+ if (video->CurrPicNum == 0 && encvid->outOfBandParamSet == FALSE)
+ {
+ picParam->pic_init_qs_minus26 = 0;
+ picParam->pic_init_qp_minus26 = video->QPy - 26;
+ }
+
+ // need this for motion estimation
+ encvid->lambda_mode = QP2QUANT[AVC_MAX(0, video->QPy-SHIFT_QP)];
+ encvid->lambda_motion = LAMBDA_FACTOR(encvid->lambda_mode);
+ return ;
+}
+
+/* Mad based variable bit allocation + QP calculation with a new quadratic method */
+void calculateQuantizer_Multipass(AVCEncObject *encvid, AVCCommonObj *video,
+ AVCRateControl *rateCtrl, MultiPass *pMP)
+{
+ int prev_actual_bits = 0, curr_target, /*pos=0,*/i, j;
+ OsclFloat Qstep, prev_QP = 0.625;
+
+ OsclFloat curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
+
+ /* Mad based variable bit allocation */
+ targetBitCalculation(encvid, video, rateCtrl, pMP);
+
+ if (rateCtrl->T <= 0 || rateCtrl->totalSAD == 0)
+ {
+ if (rateCtrl->T < 0) rateCtrl->Qc = RC_MAX_QUANT;
+ return;
+ }
+
+ /* ---------------------------------------------------------------------------------------------------*/
+ /* current frame QP estimation */
+ curr_target = rateCtrl->T;
+ curr_mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs;
+ if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+ curr_RD = (OsclFloat)curr_target / curr_mad;
+
+ if (rateCtrl->skip_next_frame == -1) // previous was skipped
+ {
+ i = pMP->framePos;
+ prev_mad = pMP->pRDSamples[i][0].mad;
+ prev_QP = pMP->pRDSamples[i][0].QP;
+ prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
+ }
+ else
+ {
+ /* Another version of search the optimal point */
+ prev_mad = 0.0;
+ i = 0;
+ while (i < pMP->frameRange && prev_mad < 0.001) /* find first one with nonzero prev_mad */
+ {
+ prev_mad = pMP->pRDSamples[i][0].mad;
+ i++;
+ }
+
+ if (i < pMP->frameRange)
+ {
+ prev_actual_bits = pMP->pRDSamples[i-1][0].actual_bits;
+
+ for (j = 0; i < pMP->frameRange; i++)
+ {
+ if (pMP->pRDSamples[i][0].mad != 0 &&
+ AVC_ABS(prev_mad - curr_mad) > AVC_ABS(pMP->pRDSamples[i][0].mad - curr_mad))
+ {
+ prev_mad = pMP->pRDSamples[i][0].mad;
+ prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
+ j = i;
+ }
+ }
+ prev_QP = QP2Qstep(pMP->pRDSamples[j][0].QP);
+
+ for (i = 1; i < pMP->samplesPerFrame[j]; i++)
+ {
+ if (AVC_ABS(prev_actual_bits - curr_target) > AVC_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target))
+ {
+ prev_actual_bits = pMP->pRDSamples[j][i].actual_bits;
+ prev_QP = QP2Qstep(pMP->pRDSamples[j][i].QP);
+ }
+ }
+ }
+ }
+
+ // quadratic approximation
+ if (prev_mad > 0.001) // only when prev_mad is greater than 0, otherwise keep using the same QP
+ {
+ prev_RD = (OsclFloat)prev_actual_bits / prev_mad;
+ //rateCtrl->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4);
+ if (prev_QP == 0.625) // added this to allow getting out of QP = 0 easily
+ {
+ Qstep = (int)(prev_RD / curr_RD + 0.5);
+ }
+ else
+ {
+ // rateCtrl->Qc =(Int)(prev_QP * M4VENC_SQRT(prev_RD/curr_RD) + 0.9);
+
+ if (prev_RD / curr_RD > 0.5 && prev_RD / curr_RD < 2.0)
+ Qstep = (int)(prev_QP * (sqrt(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */
+ else
+ Qstep = (int)(prev_QP * (sqrt(prev_RD / curr_RD) + pow(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9);
+ }
+ // lower bound on Qc should be a function of curr_mad
+ // When mad is already low, lower bound on Qc doesn't have to be small.
+ // Note, this doesn't work well for low complexity clip encoded at high bit rate
+ // it doesn't hit the target bit rate due to this QP lower bound.
+ /// if((curr_mad < 8) && (rateCtrl->Qc < 12)) rateCtrl->Qc = 12;
+ // else if((curr_mad < 128) && (rateCtrl->Qc < 3)) rateCtrl->Qc = 3;
+
+ rateCtrl->Qc = Qstep2QP(Qstep);
+
+ if (rateCtrl->Qc < RC_MIN_QUANT) rateCtrl->Qc = RC_MIN_QUANT;
+ if (rateCtrl->Qc > RC_MAX_QUANT) rateCtrl->Qc = RC_MAX_QUANT;
+ }
+
+ /* active bit resource protection */
+ aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (OsclFloat)pMP->encoded_frames);
+ average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (OsclFloat)pMP->encoded_frames); /* this function is called from the scond encoded frame*/
+ if (pMP->diff_counter == 0 &&
+ ((OsclFloat)rateCtrl->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) &&
+ pMP->counter_BTsrc <= (pMP->counter_BTdst + (int)(pMP->framerate*1.0 + 0.5)))
+ {
+ rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame / 10.0);
+ rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W;
+ pMP->counter_BTsrc++;
+ pMP->diff_counter--;
+ }
+
+}
+
+void targetBitCalculation(AVCEncObject *encvid, AVCCommonObj *video, AVCRateControl *rateCtrl, MultiPass *pMP)
+{
+ OSCL_UNUSED_ARG(encvid);
+ OsclFloat curr_mad;//, average_mad;
+ int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
+ /* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
+
+ /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
+ updateRC_PostProc(rateCtrl, pMP);
+
+ /* update pMP->counter_BTsrc and pMP->counter_BTdst to avoid interger overflow */
+ if (pMP->counter_BTsrc > 1000 && pMP->counter_BTdst > 1000)
+ {
+ pMP->counter_BTsrc -= 1000;
+ pMP->counter_BTdst -= 1000;
+ }
+
+ /* ---------------------------------------------------------------------------------------------------*/
+ /* target calculation */
+ curr_mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs;
+ if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+ diff_counter_BTsrc = diff_counter_BTdst = 0;
+ pMP->diff_counter = 0;
+
+
+ /*1.calculate average mad */
+ pMP->sum_mad += curr_mad;
+ //average_mad = (pMP->encoded_frames < 1 ? curr_mad : pMP->sum_mad/(OsclFloat)(pMP->encoded_frames+1)); /* this function is called from the scond encoded frame*/
+ //pMP->aver_mad = average_mad;
+ if (pMP->encoded_frames >= 0) /* pMP->encoded_frames is set to -1 initially, so forget about the very first I frame */
+ pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames + curr_mad) / (pMP->encoded_frames + 1);
+
+ if (pMP->overlapped_win_size > 0 && pMP->encoded_frames_prev >= 0)
+ pMP->aver_mad_prev = (pMP->aver_mad_prev * pMP->encoded_frames_prev + curr_mad) / (pMP->encoded_frames_prev + 1);
+
+ /*2.average_mad, mad ==> diff_counter_BTsrc, diff_counter_BTdst */
+ if (pMP->overlapped_win_size == 0)
+ {
+ /* original verison */
+ if (curr_mad > pMP->aver_mad*1.1)
+ {
+ if (curr_mad / (pMP->aver_mad + 0.0001) > 2)
+ diff_counter_BTdst = (int)(sqrt(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.4) - 10;
+ //diff_counter_BTdst = (int)((sqrt(curr_mad/pMP->aver_mad)*2+curr_mad/pMP->aver_mad)/(3*0.1) + 0.4) - 10;
+ else
+ diff_counter_BTdst = (int)(curr_mad / (pMP->aver_mad + 0.0001) * 10 + 0.4) - 10;
+ }
+ else /* curr_mad <= average_mad*1.1 */
+ //diff_counter_BTsrc = 10 - (int)((sqrt(curr_mad/pMP->aver_mad) + pow(curr_mad/pMP->aver_mad, 1.0/3.0))/(2.0*0.1) + 0.4);
+ diff_counter_BTsrc = 10 - (int)(sqrt(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.5);
+
+ /* actively fill in the possible gap */
+ if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+ curr_mad <= pMP->aver_mad*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+ diff_counter_BTsrc = 1;
+
+ }
+ else if (pMP->overlapped_win_size > 0)
+ {
+ /* transition time: use previous average mad "pMP->aver_mad_prev" instead of the current average mad "pMP->aver_mad" */
+ if (curr_mad > pMP->aver_mad_prev*1.1)
+ {
+ if (curr_mad / pMP->aver_mad_prev > 2)
+ diff_counter_BTdst = (int)(sqrt(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.4) - 10;
+ //diff_counter_BTdst = (int)((M4VENC_SQRT(curr_mad/pMP->aver_mad_prev)*2+curr_mad/pMP->aver_mad_prev)/(3*0.1) + 0.4) - 10;
+ else
+ diff_counter_BTdst = (int)(curr_mad / (pMP->aver_mad_prev + 0.0001) * 10 + 0.4) - 10;
+ }
+ else /* curr_mad <= average_mad*1.1 */
+ //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad_prev) + pow(curr_mad/pMP->aver_mad_prev, 1.0/3.0))/(2.0*0.1) + 0.4);
+ diff_counter_BTsrc = 10 - (int)(sqrt(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.5);
+
+ /* actively fill in the possible gap */
+ if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+ curr_mad <= pMP->aver_mad_prev*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+ diff_counter_BTsrc = 1;
+
+ if (--pMP->overlapped_win_size <= 0) pMP->overlapped_win_size = 0;
+ }
+
+
+ /* if difference is too much, do clipping */
+ /* First, set the upper bound for current bit allocation variance: 80% of available buffer */
+ bound = (int)((rateCtrl->Bs / 2 - rateCtrl->VBV_fullness) * 0.6 / (pMP->target_bits_per_frame / 10)); /* rateCtrl->Bs */
+ diff_counter_BTsrc = AVC_MIN(diff_counter_BTsrc, bound);
+ diff_counter_BTdst = AVC_MIN(diff_counter_BTdst, bound);
+
+ /* Second, set another upper bound for current bit allocation: 4-5*bitrate/framerate */
+ bound = 50;
+// if(video->encParams->RC_Type == CBR_LOWDELAY)
+// not necessary bound = 10; -- For Low delay */
+
+ diff_counter_BTsrc = AVC_MIN(diff_counter_BTsrc, bound);
+ diff_counter_BTdst = AVC_MIN(diff_counter_BTdst, bound);
+
+
+ /* Third, check the buffer */
+ prev_counter_diff = pMP->counter_BTdst - pMP->counter_BTsrc;
+ curr_counter_diff = prev_counter_diff + (diff_counter_BTdst - diff_counter_BTsrc);
+
+ if (AVC_ABS(prev_counter_diff) >= rateCtrl->max_BitVariance_num || AVC_ABS(curr_counter_diff) >= rateCtrl->max_BitVariance_num)
+ { //diff_counter_BTsrc = diff_counter_BTdst = 0;
+
+ if (curr_counter_diff > rateCtrl->max_BitVariance_num && diff_counter_BTdst)
+ {
+ diff_counter_BTdst = (rateCtrl->max_BitVariance_num - prev_counter_diff) + diff_counter_BTsrc;
+ if (diff_counter_BTdst < 0) diff_counter_BTdst = 0;
+ }
+
+ else if (curr_counter_diff < -rateCtrl->max_BitVariance_num && diff_counter_BTsrc)
+ {
+ diff_counter_BTsrc = diff_counter_BTdst - (-rateCtrl->max_BitVariance_num - prev_counter_diff);
+ if (diff_counter_BTsrc < 0) diff_counter_BTsrc = 0;
+ }
+ }
+
+
+ /*3.diff_counter_BTsrc, diff_counter_BTdst ==> TMN_TH */
+ rateCtrl->TMN_TH = (int)(pMP->target_bits_per_frame);
+ pMP->diff_counter = 0;
+
+ if (diff_counter_BTsrc)
+ {
+ rateCtrl->TMN_TH -= (int)(pMP->target_bits_per_frame * diff_counter_BTsrc * 0.1);
+ pMP->diff_counter = -diff_counter_BTsrc;
+ }
+ else if (diff_counter_BTdst)
+ {
+ rateCtrl->TMN_TH += (int)(pMP->target_bits_per_frame * diff_counter_BTdst * 0.1);
+ pMP->diff_counter = diff_counter_BTdst;
+ }
+
+
+ /*4.update pMP->counter_BTsrc, pMP->counter_BTdst */
+ pMP->counter_BTsrc += diff_counter_BTsrc;
+ pMP->counter_BTdst += diff_counter_BTdst;
+
+
+ /*5.target bit calculation */
+ rateCtrl->T = rateCtrl->TMN_TH - rateCtrl->TMN_W;
+
+ return ;
+}
+
+void updateRC_PostProc(AVCRateControl *rateCtrl, MultiPass *pMP)
+{
+ if (rateCtrl->skip_next_frame > 0) /* skip next frame */
+ {
+ pMP->counter_BTsrc += 10 * rateCtrl->skip_next_frame;
+
+ }
+ else if (rateCtrl->skip_next_frame == -1) /* skip current frame */
+ {
+ pMP->counter_BTdst -= pMP->diff_counter;
+ pMP->counter_BTsrc += 10;
+
+ pMP->sum_mad -= pMP->mad;
+ pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames - pMP->mad) / (pMP->encoded_frames - 1 + 0.0001);
+ pMP->sum_QP -= pMP->QP;
+ pMP->encoded_frames --;
+ }
+ /* some stuff in update VBV_fullness remains here */
+ //if(rateCtrl->VBV_fullness < -rateCtrl->Bs/2) /* rateCtrl->Bs */
+ if (rateCtrl->VBV_fullness < rateCtrl->low_bound)
+ {
+ rateCtrl->VBV_fullness = rateCtrl->low_bound; // -rateCtrl->Bs/2;
+ rateCtrl->TMN_W = rateCtrl->VBV_fullness - rateCtrl->low_bound;
+ pMP->counter_BTsrc = pMP->counter_BTdst + (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+ }
+}
+
+
+void RCInitChromaQP(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCMacroblock *currMB = video->currMB;
+ int q_bits;
+
+ /* we have to do the same thing for AVC_CLIP3(0,51,video->QSy) */
+
+ video->QPy_div_6 = (currMB->QPy * 43) >> 8;
+ video->QPy_mod_6 = currMB->QPy - 6 * video->QPy_div_6;
+ currMB->QPc = video->QPc = mapQPi2QPc[AVC_CLIP3(0, 51, currMB->QPy + video->currPicParams->chroma_qp_index_offset)];
+ video->QPc_div_6 = (video->QPc * 43) >> 8;
+ video->QPc_mod_6 = video->QPc - 6 * video->QPc_div_6;
+
+ /* pre-calculate this to save computation */
+ q_bits = 4 + video->QPy_div_6;
+ if (video->slice_type == AVC_I_SLICE)
+ {
+ encvid->qp_const = 682 << q_bits; // intra
+ }
+ else
+ {
+ encvid->qp_const = 342 << q_bits; // inter
+ }
+
+ q_bits = 4 + video->QPc_div_6;
+ if (video->slice_type == AVC_I_SLICE)
+ {
+ encvid->qp_const_c = 682 << q_bits; // intra
+ }
+ else
+ {
+ encvid->qp_const_c = 342 << q_bits; // inter
+ }
+
+ encvid->lambda_mode = QP2QUANT[AVC_MAX(0, currMB->QPy-SHIFT_QP)];
+ encvid->lambda_motion = LAMBDA_FACTOR(encvid->lambda_mode);
+
+ return ;
+}
+
+
+void RCInitMBQP(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCMacroblock *currMB = video->currMB;
+
+ currMB->QPy = video->QPy; /* set to previous value or picture level */
+
+ RCInitChromaQP(encvid);
+
+}
+
+void RCPostMB(AVCCommonObj *video, AVCRateControl *rateCtrl, int num_header_bits, int num_texture_bits)
+{
+ OSCL_UNUSED_ARG(video);
+ rateCtrl->numMBHeaderBits = num_header_bits;
+ rateCtrl->numMBTextureBits = num_texture_bits;
+ rateCtrl->NumberofHeaderBits += rateCtrl->numMBHeaderBits;
+ rateCtrl->NumberofTextureBits += rateCtrl->numMBTextureBits;
+}
+
+void RCRestoreQP(AVCMacroblock *currMB, AVCCommonObj *video, AVCEncObject *encvid)
+{
+ currMB->QPy = video->QPy; /* use previous QP */
+ RCInitChromaQP(encvid);
+
+ return ;
+}
+
+
+void RCCalculateMAD(AVCEncObject *encvid, AVCMacroblock *currMB, uint8 *orgL, int orgPitch)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ uint32 dmin_lx;
+
+ if (rateCtrl->rcEnable == TRUE)
+ {
+ if (currMB->mb_intra)
+ {
+ if (currMB->mbMode == AVC_I16)
+ {
+ dmin_lx = (0xFFFF << 16) | orgPitch;
+ rateCtrl->MADofMB[video->mbNum] = AVCSAD_Macroblock_C(orgL,
+ encvid->pred_i16[currMB->i16Mode], dmin_lx, NULL);
+ }
+ else /* i4 */
+ {
+ rateCtrl->MADofMB[video->mbNum] = encvid->i4_sad / 256.;
+ }
+ }
+ /* for INTER, we have already saved it with the MV search */
+ }
+
+ return ;
+}
+
+
+
+AVCEnc_Status RCUpdateFrame(AVCEncObject *encvid)
+{
+ AVCCommonObj *video = encvid->common;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ MultiPass *pMP = rateCtrl->pMP;
+ int diff_BTCounter;
+ int nal_type = video->nal_unit_type;
+
+ /* update the complexity weight of I, P, B frame */
+
+ if (rateCtrl->rcEnable == TRUE)
+ {
+ pMP->actual_bits = rateCtrl->numFrameBits;
+ pMP->mad = (OsclFloat)rateCtrl->totalSAD / video->PicSizeInMbs; //ComputeFrameMAD(video, rateCtrl);
+
+ AVCSaveRDSamples(pMP, 0);
+
+ pMP->encoded_frames++;
+
+ /* for pMP->samplesPerFrame */
+ pMP->samplesPerFrame[pMP->framePos] = 0;
+
+ pMP->sum_QP += pMP->QP;
+
+ /* update pMP->counter_BTsrc, pMP->counter_BTdst */
+ /* re-allocate the target bit again and then stop encoding */
+ diff_BTCounter = (int)((OsclFloat)(rateCtrl->TMN_TH - rateCtrl->TMN_W - pMP->actual_bits) /
+ (pMP->bitrate / (pMP->framerate + 0.0001) + 0.0001) / 0.1);
+ if (diff_BTCounter >= 0)
+ pMP->counter_BTsrc += diff_BTCounter; /* pMP->actual_bits is smaller */
+ else
+ pMP->counter_BTdst -= diff_BTCounter; /* pMP->actual_bits is bigger */
+
+ rateCtrl->TMN_TH -= (int)((OsclFloat)pMP->bitrate / (pMP->framerate + 0.0001) * (diff_BTCounter * 0.1));
+ rateCtrl->T = pMP->target_bits = rateCtrl->TMN_TH - rateCtrl->TMN_W;
+ pMP->diff_counter -= diff_BTCounter;
+
+ rateCtrl->Rc = rateCtrl->numFrameBits; /* Total Bits for current frame */
+ rateCtrl->Hc = rateCtrl->NumberofHeaderBits; /* Total Bits in Header and Motion Vector */
+
+ /* BX_RC */
+ updateRateControl(rateCtrl, nal_type);
+ if (rateCtrl->skip_next_frame == -1) // skip current frame
+ {
+ status = AVCENC_SKIPPED_PICTURE;
+ }
+ }
+
+ rateCtrl->first_frame = 0; // reset here after we encode the first frame.
+
+ return status;
+}
+
+void AVCSaveRDSamples(MultiPass *pMP, int counter_samples)
+{
+ /* for pMP->pRDSamples */
+ pMP->pRDSamples[pMP->framePos][counter_samples].QP = pMP->QP;
+ pMP->pRDSamples[pMP->framePos][counter_samples].actual_bits = pMP->actual_bits;
+ pMP->pRDSamples[pMP->framePos][counter_samples].mad = pMP->mad;
+ pMP->pRDSamples[pMP->framePos][counter_samples].R_D = (OsclFloat)pMP->actual_bits / (pMP->mad + 0.0001);
+
+ return ;
+}
+
+void updateRateControl(AVCRateControl *rateCtrl, int nal_type)
+{
+ int frame_bits;
+ MultiPass *pMP = rateCtrl->pMP;
+
+ /* BX rate contro\l */
+ frame_bits = (int)(rateCtrl->bitRate / rateCtrl->frame_rate);
+ rateCtrl->TMN_W += (rateCtrl->Rc - rateCtrl->TMN_TH);
+ rateCtrl->VBV_fullness += (rateCtrl->Rc - frame_bits); //rateCtrl->Rp);
+ //if(rateCtrl->VBV_fullness < 0) rateCtrl->VBV_fullness = -1;
+
+ rateCtrl->encoded_frames++;
+
+ /* frame dropping */
+ rateCtrl->skip_next_frame = 0;
+
+ if ((rateCtrl->VBV_fullness > rateCtrl->Bs / 2) && nal_type != AVC_NALTYPE_IDR) /* skip the current frame */ /* rateCtrl->Bs */
+ {
+ rateCtrl->TMN_W -= (rateCtrl->Rc - rateCtrl->TMN_TH);
+ rateCtrl->VBV_fullness -= rateCtrl->Rc;
+ rateCtrl->skip_next_frame = -1;
+ }
+ else if ((OsclFloat)(rateCtrl->VBV_fullness - rateCtrl->VBV_fullness_offset) > (rateCtrl->Bs / 2 - rateCtrl->VBV_fullness_offset)*0.95) /* skip next frame */
+ {
+ rateCtrl->VBV_fullness -= frame_bits; //rateCtrl->Rp;
+ rateCtrl->skip_next_frame = 1;
+ pMP->counter_BTsrc -= (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+ /* BX_1, skip more than 1 frames */
+ //while(rateCtrl->VBV_fullness > rateCtrl->Bs*0.475)
+ while ((rateCtrl->VBV_fullness - rateCtrl->VBV_fullness_offset) > (rateCtrl->Bs / 2 - rateCtrl->VBV_fullness_offset)*0.95)
+ {
+ rateCtrl->VBV_fullness -= frame_bits; //rateCtrl->Rp;
+ rateCtrl->skip_next_frame++;
+ pMP->counter_BTsrc -= (int)((OsclFloat)(rateCtrl->Bs / 2 - rateCtrl->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+ }
+
+ /* END BX_1 */
+ }
+}
+
+
+double ComputeFrameMAD(AVCCommonObj *video, AVCRateControl *rateCtrl)
+{
+ double TotalMAD;
+ int i;
+ TotalMAD = 0.0;
+ for (i = 0; i < (int)video->PicSizeInMbs; i++)
+ TotalMAD += rateCtrl->MADofMB[i];
+ TotalMAD /= video->PicSizeInMbs;
+ return TotalMAD;
+}
+
+
+
+
+
+/* convert from QP to Qstep */
+double QP2Qstep(int QP)
+{
+ int i;
+ double Qstep;
+ static const double QP2QSTEP[6] = { 0.625, 0.6875, 0.8125, 0.875, 1.0, 1.125 };
+
+ Qstep = QP2QSTEP[QP % 6];
+ for (i = 0; i < (QP / 6); i++)
+ Qstep *= 2;
+
+ return Qstep;
+}
+
+/* convert from step size to QP */
+int Qstep2QP(double Qstep)
+{
+ int q_per = 0, q_rem = 0;
+
+ // assert( Qstep >= QP2Qstep(0) && Qstep <= QP2Qstep(51) );
+ if (Qstep < QP2Qstep(0))
+ return 0;
+ else if (Qstep > QP2Qstep(51))
+ return 51;
+
+ while (Qstep > QP2Qstep(5))
+ {
+ Qstep /= 2;
+ q_per += 1;
+ }
+
+ if (Qstep <= (0.625 + 0.6875) / 2)
+ {
+ Qstep = 0.625;
+ q_rem = 0;
+ }
+ else if (Qstep <= (0.6875 + 0.8125) / 2)
+ {
+ Qstep = 0.6875;
+ q_rem = 1;
+ }
+ else if (Qstep <= (0.8125 + 0.875) / 2)
+ {
+ Qstep = 0.8125;
+ q_rem = 2;
+ }
+ else if (Qstep <= (0.875 + 1.0) / 2)
+ {
+ Qstep = 0.875;
+ q_rem = 3;
+ }
+ else if (Qstep <= (1.0 + 1.125) / 2)
+ {
+ Qstep = 1.0;
+ q_rem = 4;
+ }
+ else
+ {
+ Qstep = 1.125;
+ q_rem = 5;
+ }
+
+ return (q_per * 6 + q_rem);
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/residual.cpp b/media/libstagefright/codecs/avc/enc/src/residual.cpp
new file mode 100644
index 0000000..42eb910
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/residual.cpp
@@ -0,0 +1,389 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+AVCEnc_Status EncodeIntraPCM(AVCEncObject *encvid)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ AVCCommonObj *video = encvid->common;
+ AVCFrameIO *currInput = encvid->currInput;
+ AVCEncBitstream *stream = encvid->bitstream;
+ int x_position = (video->mb_x << 4);
+ int y_position = (video->mb_y << 4);
+ int orgPitch = currInput->pitch;
+ int offset1 = y_position * orgPitch + x_position;
+ int i, j;
+ int offset;
+ uint8 *pDst, *pSrc;
+ uint code;
+
+ ue_v(stream, 25);
+
+ i = stream->bit_left & 0x7;
+ if (i) /* not byte-aligned */
+ {
+ BitstreamWriteBits(stream, 0, i);
+ }
+
+ pSrc = currInput->YCbCr[0] + offset1;
+ pDst = video->currPic->Sl + offset1;
+ offset = video->PicWidthInSamplesL - 16;
+
+ /* at this point bitstream is byte-aligned */
+ j = 16;
+ while (j > 0)
+ {
+#if (WORD_SIZE==32)
+ for (i = 0; i < 4; i++)
+ {
+ code = *((uint*)pSrc);
+ pSrc += 4;
+ *((uint*)pDst) = code;
+ pDst += 4;
+ status = BitstreamWriteBits(stream, 32, code);
+ }
+#else
+ for (i = 0; i < 8; i++)
+ {
+ code = *((uint*)pSrc);
+ pSrc += 2;
+ *((uint*)pDst) = code;
+ pDst += 2;
+ status = BitstreamWriteBits(stream, 16, code);
+ }
+#endif
+ pDst += offset;
+ pSrc += offset;
+ j--;
+ }
+ if (status != AVCENC_SUCCESS) /* check only once per line */
+ return status;
+
+ pDst = video->currPic->Scb + ((offset1 + x_position) >> 2);
+ pSrc = currInput->YCbCr[1] + ((offset1 + x_position) >> 2);
+ offset >>= 1;
+
+ j = 8;
+ while (j > 0)
+ {
+#if (WORD_SIZE==32)
+ for (i = 0; i < 2; i++)
+ {
+ code = *((uint*)pSrc);
+ pSrc += 4;
+ *((uint*)pDst) = code;
+ pDst += 4;
+ status = BitstreamWriteBits(stream, 32, code);
+ }
+#else
+ for (i = 0; i < 4; i++)
+ {
+ code = *((uint*)pSrc);
+ pSrc += 2;
+ *((uint*)pDst) = code;
+ pDst += 2;
+ status = BitstreamWriteBits(stream, 16, code);
+ }
+#endif
+ pDst += offset;
+ pSrc += offset;
+ j--;
+ }
+
+ if (status != AVCENC_SUCCESS) /* check only once per line */
+ return status;
+
+ pDst = video->currPic->Scr + ((offset1 + x_position) >> 2);
+ pSrc = currInput->YCbCr[2] + ((offset1 + x_position) >> 2);
+
+ j = 8;
+ while (j > 0)
+ {
+#if (WORD_SIZE==32)
+ for (i = 0; i < 2; i++)
+ {
+ code = *((uint*)pSrc);
+ pSrc += 4;
+ *((uint*)pDst) = code;
+ pDst += 4;
+ status = BitstreamWriteBits(stream, 32, code);
+ }
+#else
+ for (i = 0; i < 4; i++)
+ {
+ code = *((uint*)pSrc);
+ pSrc += 2;
+ *((uint*)pDst) = code;
+ pDst += 2;
+ status = BitstreamWriteBits(stream, 16, code);
+ }
+#endif
+ pDst += offset;
+ pSrc += offset;
+ j--;
+ }
+
+ return status;
+}
+
+
+AVCEnc_Status enc_residual_block(AVCEncObject *encvid, AVCResidualType type, int cindx, AVCMacroblock *currMB)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ AVCCommonObj *video = encvid->common;
+ int i, maxNumCoeff, nC;
+ int cdc = 0, cac = 0;
+ int TrailingOnes;
+ AVCEncBitstream *stream = encvid->bitstream;
+ uint trailing_ones_sign_flag;
+ int zerosLeft;
+ int *level, *run;
+ int TotalCoeff;
+ const static int incVlc[] = {0, 3, 6, 12, 24, 48, 32768}; // maximum vlc = 6
+ int escape, numPrefix, sufmask, suffix, shift, sign, value, absvalue, vlcnum, level_two_or_higher;
+ int bindx = blkIdx2blkXY[cindx>>2][cindx&3] ; // raster scan index
+
+ switch (type)
+ {
+ case AVC_Luma:
+ maxNumCoeff = 16;
+ level = encvid->level[cindx];
+ run = encvid->run[cindx];
+ TotalCoeff = currMB->nz_coeff[bindx];
+ break;
+ case AVC_Intra16DC:
+ maxNumCoeff = 16;
+ level = encvid->leveldc;
+ run = encvid->rundc;
+ TotalCoeff = cindx; /* special case */
+ bindx = 0;
+ cindx = 0;
+ break;
+ case AVC_Intra16AC:
+ maxNumCoeff = 15;
+ level = encvid->level[cindx];
+ run = encvid->run[cindx];
+ TotalCoeff = currMB->nz_coeff[bindx];
+ break;
+ case AVC_ChromaDC: /* how to differentiate Cb from Cr */
+ maxNumCoeff = 4;
+ cdc = 1;
+ if (cindx >= 8)
+ {
+ level = encvid->levelcdc + 4;
+ run = encvid->runcdc + 4;
+ TotalCoeff = cindx - 8; /* special case */
+ }
+ else
+ {
+ level = encvid->levelcdc;
+ run = encvid->runcdc;
+ TotalCoeff = cindx; /* special case */
+ }
+ break;
+ case AVC_ChromaAC:
+ maxNumCoeff = 15;
+ cac = 1;
+ level = encvid->level[cindx];
+ run = encvid->run[cindx];
+ cindx -= 16;
+ bindx = 16 + blkIdx2blkXY[cindx>>2][cindx&3];
+ cindx += 16;
+ TotalCoeff = currMB->nz_coeff[bindx];
+ break;
+ default:
+ return AVCENC_FAIL;
+ }
+
+
+ /* find TrailingOnes */
+ TrailingOnes = 0;
+ zerosLeft = 0;
+ i = TotalCoeff - 1;
+ nC = 1;
+ while (i >= 0)
+ {
+ zerosLeft += run[i];
+ if (nC && (level[i] == 1 || level[i] == -1))
+ {
+ TrailingOnes++;
+ }
+ else
+ {
+ nC = 0;
+ }
+ i--;
+ }
+ if (TrailingOnes > 3)
+ {
+ TrailingOnes = 3; /* clip it */
+ }
+
+ if (!cdc)
+ {
+ if (!cac) /* not chroma */
+ {
+ nC = predict_nnz(video, bindx & 3, bindx >> 2);
+ }
+ else /* chroma ac but not chroma dc */
+ {
+ nC = predict_nnz_chroma(video, bindx & 3, bindx >> 2);
+ }
+
+ status = ce_TotalCoeffTrailingOnes(stream, TrailingOnes, TotalCoeff, nC);
+ }
+ else
+ {
+ nC = -1; /* Chroma DC level */
+ status = ce_TotalCoeffTrailingOnesChromaDC(stream, TrailingOnes, TotalCoeff);
+ }
+
+ /* This part is done quite differently in ReadCoef4x4_CAVLC() */
+ if (TotalCoeff > 0)
+ {
+
+ i = TotalCoeff - 1;
+
+ if (TrailingOnes) /* keep reading the sign of those trailing ones */
+ {
+ nC = TrailingOnes;
+ trailing_ones_sign_flag = 0;
+ while (nC)
+ {
+ trailing_ones_sign_flag <<= 1;
+ trailing_ones_sign_flag |= ((uint32)level[i--] >> 31); /* 0 or positive, 1 for negative */
+ nC--;
+ }
+
+ /* instead of writing one bit at a time, read the whole thing at once */
+ status = BitstreamWriteBits(stream, TrailingOnes, trailing_ones_sign_flag);
+ }
+
+ level_two_or_higher = 1;
+ if (TotalCoeff > 3 && TrailingOnes == 3)
+ {
+ level_two_or_higher = 0;
+ }
+
+ if (TotalCoeff > 10 && TrailingOnes < 3)
+ {
+ vlcnum = 1;
+ }
+ else
+ {
+ vlcnum = 0;
+ }
+
+ /* then do this TotalCoeff-TrailingOnes times */
+ for (i = TotalCoeff - TrailingOnes - 1; i >= 0; i--)
+ {
+ value = level[i];
+ absvalue = (value >= 0) ? value : -value;
+
+ if (level_two_or_higher)
+ {
+ if (value > 0) value--;
+ else value++;
+ level_two_or_higher = 0;
+ }
+
+ if (value >= 0)
+ {
+ sign = 0;
+ }
+ else
+ {
+ sign = 1;
+ value = -value;
+ }
+
+ if (vlcnum == 0) // VLC1
+ {
+ if (value < 8)
+ {
+ status = BitstreamWriteBits(stream, value * 2 + sign - 1, 1);
+ }
+ else if (value < 8 + 8)
+ {
+ status = BitstreamWriteBits(stream, 14 + 1 + 4, (1 << 4) | ((value - 8) << 1) | sign);
+ }
+ else
+ {
+ status = BitstreamWriteBits(stream, 14 + 2 + 12, (1 << 12) | ((value - 16) << 1) | sign) ;
+ }
+ }
+ else // VLCN
+ {
+ shift = vlcnum - 1;
+ escape = (15 << shift) + 1;
+ numPrefix = (value - 1) >> shift;
+ sufmask = ~((0xffffffff) << shift);
+ suffix = (value - 1) & sufmask;
+ if (value < escape)
+ {
+ status = BitstreamWriteBits(stream, numPrefix + vlcnum + 1, (1 << (shift + 1)) | (suffix << 1) | sign);
+ }
+ else
+ {
+ status = BitstreamWriteBits(stream, 28, (1 << 12) | ((value - escape) << 1) | sign);
+ }
+
+ }
+
+ if (absvalue > incVlc[vlcnum])
+ vlcnum++;
+
+ if (i == TotalCoeff - TrailingOnes - 1 && absvalue > 3)
+ vlcnum = 2;
+ }
+
+ if (status != AVCENC_SUCCESS) /* occasionally check the bitstream */
+ {
+ return status;
+ }
+ if (TotalCoeff < maxNumCoeff)
+ {
+ if (!cdc)
+ {
+ ce_TotalZeros(stream, zerosLeft, TotalCoeff);
+ }
+ else
+ {
+ ce_TotalZerosChromaDC(stream, zerosLeft, TotalCoeff);
+ }
+ }
+ else
+ {
+ zerosLeft = 0;
+ }
+
+ i = TotalCoeff - 1;
+ while (i > 0) /* don't do the last one */
+ {
+ if (zerosLeft > 0)
+ {
+ ce_RunBefore(stream, run[i], zerosLeft);
+ }
+
+ zerosLeft = zerosLeft - run[i];
+ i--;
+ }
+ }
+
+ return status;
+}
diff --git a/media/libstagefright/codecs/avc/enc/src/sad.cpp b/media/libstagefright/codecs/avc/enc/src/sad.cpp
new file mode 100644
index 0000000..ae7acd2
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad.cpp
@@ -0,0 +1,290 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+#include "sad_inline.h"
+
+#define Cached_lx 176
+
+#ifdef _SAD_STAT
+uint32 num_sad_MB = 0;
+uint32 num_sad_Blk = 0;
+uint32 num_sad_MB_call = 0;
+uint32 num_sad_Blk_call = 0;
+
+#define NUM_SAD_MB_CALL() num_sad_MB_call++
+#define NUM_SAD_MB() num_sad_MB++
+#define NUM_SAD_BLK_CALL() num_sad_Blk_call++
+#define NUM_SAD_BLK() num_sad_Blk++
+
+#else
+
+#define NUM_SAD_MB_CALL()
+#define NUM_SAD_MB()
+#define NUM_SAD_BLK_CALL()
+#define NUM_SAD_BLK()
+
+#endif
+
+
+/* consist of
+int AVCSAD_Macroblock_C(uint8 *ref,uint8 *blk,int dmin,int lx,void *extra_info)
+int AVCSAD_MB_HTFM_Collect(uint8 *ref,uint8 *blk,int dmin,int lx,void *extra_info)
+int AVCSAD_MB_HTFM(uint8 *ref,uint8 *blk,int dmin,int lx,void *extra_info)
+*/
+
+
+/*==================================================================
+ Function: SAD_Macroblock
+ Date: 09/07/2000
+ Purpose: Compute SAD 16x16 between blk and ref.
+ To do: Uniform subsampling will be inserted later!
+ Hypothesis Testing Fast Matching to be used later!
+ Changes:
+ 11/7/00: implemented MMX
+ 1/24/01: implemented SSE
+==================================================================*/
+/********** C ************/
+int AVCSAD_Macroblock_C(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info)
+{
+ (void)(extra_info);
+
+ int32 x10;
+ int dmin = (uint32)dmin_lx >> 16;
+ int lx = dmin_lx & 0xFFFF;
+
+ NUM_SAD_MB_CALL();
+
+ x10 = simd_sad_mb(ref, blk, dmin, lx);
+
+ return x10;
+}
+
+#ifdef HTFM /* HTFM with uniform subsampling implementation 2/28/01 */
+/*===============================================================
+ Function: AVCAVCSAD_MB_HTFM_Collect and AVCSAD_MB_HTFM
+ Date: 3/2/1
+ Purpose: Compute the SAD on a 16x16 block using
+ uniform subsampling and hypothesis testing fast matching
+ for early dropout. SAD_MB_HP_HTFM_Collect is to collect
+ the statistics to compute the thresholds to be used in
+ SAD_MB_HP_HTFM.
+ Input/Output:
+ Changes:
+ ===============================================================*/
+
+int AVCAVCSAD_MB_HTFM_Collect(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info)
+{
+ int i;
+ int sad = 0;
+ uint8 *p1;
+ int lx4 = (dmin_lx << 2) & 0x3FFFC;
+ uint32 cur_word;
+ int saddata[16], tmp, tmp2; /* used when collecting flag (global) is on */
+ int difmad;
+ int madstar;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ uint *countbreak = &(htfm_stat->countbreak);
+ int *offsetRef = htfm_stat->offsetRef;
+
+ madstar = (uint32)dmin_lx >> 20;
+
+ NUM_SAD_MB_CALL();
+
+ blk -= 4;
+ for (i = 0; i < 16; i++)
+ {
+ p1 = ref + offsetRef[i];
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ NUM_SAD_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if ((uint32)sad > ((uint32)dmin_lx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+}
+
+int AVCSAD_MB_HTFM(uint8 *ref, uint8 *blk, int dmin_lx, void *extra_info)
+{
+ int sad = 0;
+ uint8 *p1;
+
+ int i;
+ int tmp, tmp2;
+ int lx4 = (dmin_lx << 2) & 0x3FFFC;
+ int sadstar = 0, madstar;
+ int *nrmlz_th = (int*) extra_info;
+ int *offsetRef = (int*) extra_info + 32;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_lx >> 20;
+
+ NUM_SAD_MB_CALL();
+
+ blk -= 4;
+ for (i = 0; i < 16; i++)
+ {
+ p1 = ref + offsetRef[i];
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ NUM_SAD_MB();
+
+ sadstar += madstar;
+ if (((uint32)sad <= ((uint32)dmin_lx >> 16)) && (sad <= (sadstar - *nrmlz_th++)))
+ ;
+ else
+ return 65536;
+ }
+
+ return sad;
+}
+#endif /* HTFM */
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp b/media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp
new file mode 100644
index 0000000..faf2198
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_halfpel.cpp
@@ -0,0 +1,629 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/* contains
+int AVCHalfPel1_SAD_MB(uint8 *ref,uint8 *blk,int dmin,int width,int ih,int jh)
+int AVCHalfPel2_SAD_MB(uint8 *ref,uint8 *blk,int dmin,int width)
+int AVCHalfPel1_SAD_Blk(uint8 *ref,uint8 *blk,int dmin,int width,int ih,int jh)
+int AVCHalfPel2_SAD_Blk(uint8 *ref,uint8 *blk,int dmin,int width)
+
+int AVCSAD_MB_HalfPel_C(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+int AVCSAD_MB_HP_HTFM_Collect(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+int AVCSAD_MB_HP_HTFM(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+int AVCSAD_Blk_HalfPel_C(uint8 *ref,uint8 *blk,int dmin,int width,int rx,int xh,int yh,void *extra_info)
+*/
+
+#include "avcenc_lib.h"
+#include "sad_halfpel_inline.h"
+
+#ifdef _SAD_STAT
+uint32 num_sad_HP_MB = 0;
+uint32 num_sad_HP_Blk = 0;
+uint32 num_sad_HP_MB_call = 0;
+uint32 num_sad_HP_Blk_call = 0;
+#define NUM_SAD_HP_MB_CALL() num_sad_HP_MB_call++
+#define NUM_SAD_HP_MB() num_sad_HP_MB++
+#define NUM_SAD_HP_BLK_CALL() num_sad_HP_Blk_call++
+#define NUM_SAD_HP_BLK() num_sad_HP_Blk++
+#else
+#define NUM_SAD_HP_MB_CALL()
+#define NUM_SAD_HP_MB()
+#define NUM_SAD_HP_BLK_CALL()
+#define NUM_SAD_HP_BLK()
+#endif
+
+
+
+/*===============================================================
+ Function: SAD_MB_HalfPel
+ Date: 09/17/2000
+ Purpose: Compute the SAD on the half-pel resolution
+ Input/Output: hmem is assumed to be a pointer to the starting
+ point of the search in the 33x33 matrix search region
+ Changes:
+ 11/7/00: implemented MMX
+ ===============================================================*/
+/*==================================================================
+ Function: AVCSAD_MB_HalfPel_C
+ Date: 04/30/2001
+ Purpose: Compute SAD 16x16 between blk and ref in halfpel
+ resolution,
+ Changes:
+ ==================================================================*/
+/* One component is half-pel */
+int AVCSAD_MB_HalfPel_Cxhyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ (void)(extra_info);
+
+ int i, j;
+ int sad = 0;
+ uint8 *kk, *p1, *p2, *p3, *p4;
+// int sumref=0;
+ int temp;
+ int rx = dmin_rx & 0xFFFF;
+
+ NUM_SAD_HP_MB_CALL();
+
+ p1 = ref;
+ p2 = ref + 1;
+ p3 = ref + rx;
+ p4 = ref + rx + 1;
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+ sad += AVC_ABS(temp);
+ }
+
+ NUM_SAD_HP_MB();
+
+ if (sad > (int)((uint32)dmin_rx >> 16))
+ return sad;
+
+ p1 += rx;
+ p3 += rx;
+ p2 += rx;
+ p4 += rx;
+ }
+ return sad;
+}
+
+int AVCSAD_MB_HalfPel_Cyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ (void)(extra_info);
+
+ int i, j;
+ int sad = 0;
+ uint8 *kk, *p1, *p2;
+// int sumref=0;
+ int temp;
+ int rx = dmin_rx & 0xFFFF;
+
+ NUM_SAD_HP_MB_CALL();
+
+ p1 = ref;
+ p2 = ref + rx; /* either left/right or top/bottom pixel */
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+ sad += AVC_ABS(temp);
+ }
+
+ NUM_SAD_HP_MB();
+
+ if (sad > (int)((uint32)dmin_rx >> 16))
+ return sad;
+ p1 += rx;
+ p2 += rx;
+ }
+ return sad;
+}
+
+int AVCSAD_MB_HalfPel_Cxh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ (void)(extra_info);
+
+ int i, j;
+ int sad = 0;
+ uint8 *kk, *p1;
+ int temp;
+ int rx = dmin_rx & 0xFFFF;
+
+ NUM_SAD_HP_MB_CALL();
+
+ p1 = ref;
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p1[j+1] + 1) >> 1) - *kk++;
+ sad += AVC_ABS(temp);
+ }
+
+ NUM_SAD_HP_MB();
+
+ if (sad > (int)((uint32)dmin_rx >> 16))
+ return sad;
+ p1 += rx;
+ }
+ return sad;
+}
+
+#ifdef HTFM /* HTFM with uniform subsampling implementation, 2/28/01 */
+
+//Checheck here
+int AVCAVCSAD_MB_HP_HTFM_Collectxhyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ int i, j;
+ int sad = 0;
+ uint8 *p1, *p2;
+ int rx = dmin_rx & 0xFFFF;
+ int refwx4 = rx << 2;
+ int saddata[16]; /* used when collecting flag (global) is on */
+ int difmad, tmp, tmp2;
+ int madstar;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ int *offsetRef = htfm_stat->offsetRef;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+
+ j = 4;/* 4 lines */
+ do
+ {
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12] + p2[12];
+ tmp2 = p1[13] + p2[13];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 24) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8] + p2[8];
+ tmp2 = p1[9] + p2[9];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 16) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4] + p2[4];
+ tmp2 = p1[5] + p2[5];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 8) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp2 = p1[1] + p2[1];
+ tmp = p1[0] + p2[0];
+ p1 += refwx4;
+ p2 += refwx4;
+ tmp += tmp2;
+ tmp2 = (cur_word & 0xFF);
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if (sad > ((uint32)dmin_rx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+
+ return sad;
+}
+
+int AVCAVCSAD_MB_HP_HTFM_Collectyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ int i, j;
+ int sad = 0;
+ uint8 *p1, *p2;
+ int rx = dmin_rx & 0xFFFF;
+ int refwx4 = rx << 2;
+ int saddata[16]; /* used when collecting flag (global) is on */
+ int difmad, tmp, tmp2;
+ int madstar;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ int *offsetRef = htfm_stat->offsetRef;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+ j = 4;
+ do
+ {
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p2[12];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p2[8];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p2[4];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ p1 += refwx4;
+ tmp2 = p2[0];
+ p2 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if (sad > ((uint32)dmin_rx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+
+ return sad;
+}
+
+int AVCAVCSAD_MB_HP_HTFM_Collectxh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ int i, j;
+ int sad = 0;
+ uint8 *p1;
+ int rx = dmin_rx & 0xFFFF;
+ int refwx4 = rx << 2;
+ int saddata[16]; /* used when collecting flag (global) is on */
+ int difmad, tmp, tmp2;
+ int madstar;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ int *offsetRef = htfm_stat->offsetRef;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+
+ j = 4; /* 4 lines */
+ do
+ {
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p1[13];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p1[9];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p1[5];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ tmp2 = p1[1];
+ p1 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if (sad > ((uint32)dmin_rx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+
+ return sad;
+}
+
+int AVCSAD_MB_HP_HTFMxhyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ int i, j;
+ int sad = 0, tmp, tmp2;
+ uint8 *p1, *p2;
+ int rx = dmin_rx & 0xFFFF;
+ int refwx4 = rx << 2;
+ int sadstar = 0, madstar;
+ int *nrmlz_th = (int*) extra_info;
+ int *offsetRef = nrmlz_th + 32;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+
+ j = 4; /* 4 lines */
+ do
+ {
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12] + p2[12];
+ tmp2 = p1[13] + p2[13];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 24) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8] + p2[8];
+ tmp2 = p1[9] + p2[9];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 16) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4] + p2[4];
+ tmp2 = p1[5] + p2[5];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 8) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp2 = p1[1] + p2[1];
+ tmp = p1[0] + p2[0];
+ p1 += refwx4;
+ p2 += refwx4;
+ tmp += tmp2;
+ tmp2 = (cur_word & 0xFF);
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ sadstar += madstar;
+ if (sad > sadstar - nrmlz_th[i] || sad > ((uint32)dmin_rx >> 16))
+ {
+ return 65536;
+ }
+ }
+
+ return sad;
+}
+
+int AVCSAD_MB_HP_HTFMyh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ int i, j;
+ int sad = 0, tmp, tmp2;
+ uint8 *p1, *p2;
+ int rx = dmin_rx & 0xFFFF;
+ int refwx4 = rx << 2;
+ int sadstar = 0, madstar;
+ int *nrmlz_th = (int*) extra_info;
+ int *offsetRef = nrmlz_th + 32;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+ j = 4;
+ do
+ {
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p2[12];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p2[8];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p2[4];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ p1 += refwx4;
+ tmp2 = p2[0];
+ p2 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+ sadstar += madstar;
+ if (sad > sadstar - nrmlz_th[i] || sad > ((uint32)dmin_rx >> 16))
+ {
+ return 65536;
+ }
+ }
+
+ return sad;
+}
+
+int AVCSAD_MB_HP_HTFMxh(uint8 *ref, uint8 *blk, int dmin_rx, void *extra_info)
+{
+ int i, j;
+ int sad = 0, tmp, tmp2;
+ uint8 *p1;
+ int rx = dmin_rx & 0xFFFF;
+ int refwx4 = rx << 2;
+ int sadstar = 0, madstar;
+ int *nrmlz_th = (int*) extra_info;
+ int *offsetRef = nrmlz_th + 32;
+ uint32 cur_word;
+
+ madstar = (uint32)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+
+ j = 4;/* 4 lines */
+ do
+ {
+ cur_word = *((uint32*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p1[13];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p1[9];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p1[5];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ tmp2 = p1[1];
+ p1 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ sadstar += madstar;
+ if (sad > sadstar - nrmlz_th[i] || sad > ((uint32)dmin_rx >> 16))
+ {
+ return 65536;
+ }
+ }
+
+ return sad;
+}
+
+#endif /* HTFM */
+
+
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h b/media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h
new file mode 100644
index 0000000..3a21647
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_halfpel_inline.h
@@ -0,0 +1,96 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#ifndef _SAD_HALFPEL_INLINE_H_
+#define _SAD_HALFPEL_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER */
+
+ __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ tmp = (tmp2 >> 1) - tmp;
+ if (tmp > 0) sad += tmp;
+ else sad -= tmp;
+
+ return sad;
+ }
+
+ __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ tmp = (tmp >> 2) - tmp2;
+ if (tmp > 0) sad += tmp;
+ else sad -= tmp;
+
+ return sad;
+ }
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+ __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ __asm
+ {
+ rsbs tmp, tmp, tmp2, asr #1 ;
+ rsbmi tmp, tmp, #0 ;
+ add sad, sad, tmp ;
+ }
+
+ return sad;
+ }
+
+ __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ __asm
+ {
+ rsbs tmp, tmp2, tmp, asr #2 ;
+ rsbmi tmp, tmp, #0 ;
+ add sad, sad, tmp ;
+ }
+
+ return sad;
+ }
+
+#elif defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER */
+
+ __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+__asm__ volatile("rsbs %1, %1, %2, asr #1\n\trsbmi %1, %1, #0\n\tadd %0, %0, %1": "=r"(sad), "=r"(tmp): "r"(tmp2));
+
+ return sad;
+ }
+
+ __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+__asm__ volatile("rsbs %1, %2, %1, asr #2\n\trsbmi %1, %1, #0\n\tadd %0, %0, %1": "=r"(sad), "=r"(tmp): "r"(tmp2));
+
+ return sad;
+ }
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_SAD_HALFPEL_INLINE_H_
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_inline.h b/media/libstagefright/codecs/avc/enc/src/sad_inline.h
new file mode 100644
index 0000000..f39794f
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_inline.h
@@ -0,0 +1,488 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _SAD_INLINE_H_
+#define _SAD_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER */
+
+ __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ tmp = tmp - tmp2;
+ if (tmp > 0) sad += tmp;
+ else sad -= tmp;
+
+ return sad;
+ }
+
+ __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+ x7 = src2 ^ src1; /* check odd/even combination */
+ if ((uint32)src2 >= (uint32)src1)
+ {
+ src1 = src2 - src1; /* subs */
+ }
+ else
+ {
+ src1 = src1 - src2;
+ }
+ x7 = x7 ^ src1; /* only odd bytes need to add carry */
+ x7 = mask & ((uint32)x7 >> 1);
+ x7 = (x7 << 8) - x7;
+ src1 = src1 + (x7 >> 7); /* add 0xFF to the negative byte, add back carry */
+ src1 = src1 ^(x7 >> 7); /* take absolute value of negative byte */
+
+ return src1;
+ }
+
+#define NUMBER 3
+#define SHIFT 24
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#include "sad_mb_offset.h"
+
+
+ __inline int32 simd_sad_mb(uint8 *ref, uint8 *blk, int dmin, int lx)
+ {
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+
+ x8 = (uint32)ref & 0x3;
+ if (x8 == 3)
+ goto SadMBOffset3;
+ if (x8 == 2)
+ goto SadMBOffset2;
+ if (x8 == 1)
+ goto SadMBOffset1;
+
+// x5 = (x4<<8)-x4; /* x5 = x4*255; */
+ x4 = x5 = 0;
+
+ x6 = 0xFFFF00FF;
+
+ ref -= lx;
+ blk -= 16;
+
+ x8 = 16;
+
+LOOP_SAD0:
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref += lx));
+ x11 = *((uint32*)(ref + 4));
+ x12 = *((uint32*)(blk += 16));
+ x14 = *((uint32*)(blk + 4));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref + 8));
+ x11 = *((uint32*)(ref + 12));
+ x12 = *((uint32*)(blk + 8));
+ x14 = *((uint32*)(blk + 12));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if ((int)((uint32)x10 >> 16) <= dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+ goto LOOP_SAD0;
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+ return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+ return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+ return sad_mb_offset1(ref, blk, lx, dmin);
+
+ }
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+ __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ __asm
+ {
+ rsbs tmp, tmp, tmp2 ;
+ rsbmi tmp, tmp, #0 ;
+ add sad, sad, tmp ;
+ }
+
+ return sad;
+ }
+
+ __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+ __asm
+ {
+ EOR x7, src2, src1; /* check odd/even combination */
+ SUBS src1, src2, src1;
+ EOR x7, x7, src1;
+ AND x7, mask, x7, lsr #1;
+ ORRCC x7, x7, #0x80000000;
+ RSB x7, x7, x7, lsl #8;
+ ADD src1, src1, x7, asr #7; /* add 0xFF to the negative byte, add back carry */
+ EOR src1, src1, x7, asr #7; /* take absolute value of negative byte */
+ }
+
+ return src1;
+ }
+
+ __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+ __asm
+ {
+ EOR x7, src2, src1; /* check odd/even combination */
+ ADDS src1, src2, src1;
+ EOR x7, x7, src1; /* only odd bytes need to add carry */
+ ANDS x7, mask, x7, rrx;
+ RSB x7, x7, x7, lsl #8;
+ SUB src1, src1, x7, asr #7; /* add 0xFF to the negative byte, add back carry */
+ EOR src1, src1, x7, asr #7; /* take absolute value of negative byte */
+ }
+
+ return src1;
+ }
+
+#define sum_accumulate __asm{ SBC x5, x5, x10; /* accumulate low bytes */ \
+ BIC x10, x6, x10; /* x10 & 0xFF00FF00 */ \
+ ADD x4, x4, x10,lsr #8; /* accumulate high bytes */ \
+ SBC x5, x5, x11; /* accumulate low bytes */ \
+ BIC x11, x6, x11; /* x11 & 0xFF00FF00 */ \
+ ADD x4, x4, x11,lsr #8; } /* accumulate high bytes */
+
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+ __inline int32 simd_sad_mb(uint8 *ref, uint8 *blk, int dmin, int lx)
+ {
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+
+ __asm
+ {
+ MOVS x8, ref, lsl #31 ;
+ BHI SadMBOffset3;
+ BCS SadMBOffset2;
+ BMI SadMBOffset1;
+
+ MVN x6, #0xFF00;
+ }
+LOOP_SAD0:
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+ x12 = *((int32*)(blk + 8));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ __asm
+ {
+ /****** process 8 pixels ******/
+ LDR x11, [ref, #4];
+ LDR x10, [ref], lx ;
+ LDR x14, [blk, #4];
+ LDR x12, [blk], #16 ;
+ }
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ __asm
+ {
+ /****************/
+ RSBS x11, dmin, x10, lsr #16;
+ ADDLSS x8, x8, #0x10000001;
+ BLS LOOP_SAD0;
+ }
+
+ return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+ return sad_mb_offset3(ref, blk, lx, dmin, x8);
+
+SadMBOffset2:
+
+ return sad_mb_offset2(ref, blk, lx, dmin, x8);
+
+SadMBOffset1:
+
+ return sad_mb_offset1(ref, blk, lx, dmin, x8);
+ }
+
+
+#elif defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER */
+
+ __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+__asm__ volatile("rsbs %1, %1, %2\n\trsbmi %1, %1, #0\n\tadd %0, %0, %1": "=r"(sad): "r"(tmp), "r"(tmp2));
+ return sad;
+ }
+
+ __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+__asm__ volatile("EOR %1, %2, %0\n\tSUBS %0, %2, %0\n\tEOR %1, %1, %0\n\tAND %1, %3, %1, lsr #1\n\tORRCC %1, %1, #0x80000000\n\tRSB %1, %1, %1, lsl #8\n\tADD %0, %0, %1, asr #7\n\tEOR %0, %0, %1, asr #7": "=r"(src1), "=&r"(x7): "r"(src2), "r"(mask));
+
+ return src1;
+ }
+
+ __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+__asm__ volatile("EOR %1, %2, %0\n\tADDS %0, %2, %0\n\tEOR %1, %1, %0\n\tANDS %1, %3, %1, rrx\n\tRSB %1, %1, %1, lsl #8\n\tSUB %0, %0, %1, asr #7\n\tEOR %0, %0, %1, asr #7": "=r"(src1), "=&r"(x7): "r"(src2), "r"(mask));
+
+ return src1;
+ }
+
+#define sum_accumulate __asm__ volatile("SBC %0, %0, %1\n\tBIC %1, %4, %1\n\tADD %2, %2, %1, lsr #8\n\tSBC %0, %0, %3\n\tBIC %3, %4, %3\n\tADD %2, %2, %3, lsr #8": "=&r" (x5), "=&r" (x10), "=&r" (x4), "=&r" (x11): "r" (x6));
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+ __inline int32 simd_sad_mb(uint8 *ref, uint8 *blk, int dmin, int lx)
+ {
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+
+ x8 = (uint32)ref & 0x3;
+ if (x8 == 3)
+ goto SadMBOffset3;
+ if (x8 == 2)
+ goto SadMBOffset2;
+ if (x8 == 1)
+ goto SadMBOffset1;
+
+ x8 = 16;
+///
+__asm__ volatile("MVN %0, #0xFF00": "=r"(x6));
+
+LOOP_SAD0:
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+ x12 = *((int32*)(blk + 8));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 4));
+__asm__ volatile("LDR %0, [%1], %2": "=&r"(x10), "=r"(ref): "r"(lx));
+ //x10 = *((int32*)ref); ref+=lx;
+ x14 = *((int32*)(blk + 4));
+__asm__ volatile("LDR %0, [%1], #16": "=&r"(x12), "=r"(blk));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ /****************/
+
+ if (((uint32)x10 >> 16) <= dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+ goto LOOP_SAD0;
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+ return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+ return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+ return sad_mb_offset1(ref, blk, lx, dmin);
+ }
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _SAD_INLINE_H_
+
diff --git a/media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h b/media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h
new file mode 100644
index 0000000..d5d4a42
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/sad_mb_offset.h
@@ -0,0 +1,311 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#if defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(uint8 *ref, uint8 *blk, int lx, int dmin)
+#endif
+{
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ // x5 = (x4<<8) - x4;
+ x4 = x5 = 0;
+ x6 = 0xFFFF00FF;
+ x9 = 0x80808080; /* const. */
+ ref -= NUMBER; /* bic ref, ref, #3 */
+ ref -= lx;
+ blk -= 16;
+ x8 = 16;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref += lx)); /* D C B A */
+ x11 = *((uint32*)(ref + 4)); /* H G F E */
+ x12 = *((uint32*)(ref + 8)); /* L K J I */
+
+ x10 = ((uint32)x10 >> SHIFT); /* 0 0 0 D */
+ x10 = x10 | (x11 << (32 - SHIFT)); /* G F E D */
+ x11 = ((uint32)x11 >> SHIFT); /* 0 0 0 H */
+ x11 = x11 | (x12 << (32 - SHIFT)); /* K J I H */
+
+ x12 = *((uint32*)(blk += 16));
+ x14 = *((uint32*)(blk + 4));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref + 8)); /* D C B A */
+ x11 = *((uint32*)(ref + 12)); /* H G F E */
+ x12 = *((uint32*)(ref + 16)); /* L K J I */
+
+ x10 = ((uint32)x10 >> SHIFT); /* mvn x10, x10, lsr #24 = 0xFF 0xFF 0xFF ~D */
+ x10 = x10 | (x11 << (32 - SHIFT)); /* bic x10, x10, x11, lsl #8 = ~G ~F ~E ~D */
+ x11 = ((uint32)x11 >> SHIFT); /* 0xFF 0xFF 0xFF ~H */
+ x11 = x11 | (x12 << (32 - SHIFT)); /* ~K ~J ~I ~H */
+
+ x12 = *((uint32*)(blk + 8));
+ x14 = *((uint32*)(blk + 12));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if ((int)((uint32)x10 >> 16) <= dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+#if (NUMBER==3)
+ goto LOOP_SAD3;
+#elif (NUMBER==2)
+ goto LOOP_SAD2;
+#elif (NUMBER==1)
+ goto LOOP_SAD1;
+#endif
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+}
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(uint8 *ref, uint8 *blk, int lx, int dmin, int32 x8)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(uint8 *ref, uint8 *blk, int lx, int dmin, int32 x8)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(uint8 *ref, uint8 *blk, int lx, int dmin, int32 x8)
+#endif
+{
+ int32 x4, x5, x6, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+
+ __asm{
+ MVN x6, #0xff0000;
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+ BIC ref, ref, #3;
+ }
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x12 = *((int32*)(ref + 16));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+
+ __asm{
+ MVN x10, x10, lsr #SHIFT;
+ BIC x10, x10, x11, lsl #(32-SHIFT);
+ MVN x11, x11, lsr #SHIFT;
+ BIC x11, x11, x12, lsl #(32-SHIFT);
+
+ LDR x12, [blk, #8];
+ }
+
+ /* process x11 & x14 */
+ x11 = sad_4pixelN(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixelN(x10, x12, x9);
+
+ sum_accumulate;
+
+ __asm{
+ /****** process 8 pixels ******/
+ LDR x11, [ref, #4];
+ LDR x12, [ref, #8];
+ LDR x10, [ref], lx ;
+ LDR x14, [blk, #4];
+
+ MVN x10, x10, lsr #SHIFT;
+ BIC x10, x10, x11, lsl #(32-SHIFT);
+ MVN x11, x11, lsr #SHIFT;
+ BIC x11, x11, x12, lsl #(32-SHIFT);
+
+ LDR x12, [blk], #16;
+ }
+
+ /* process x11 & x14 */
+ x11 = sad_4pixelN(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixelN(x10, x12, x9);
+
+ sum_accumulate;
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ __asm{
+ RSBS x11, dmin, x10, lsr #16
+ ADDLSS x8, x8, #INC_X8
+#if (NUMBER==3)
+ BLS LOOP_SAD3;
+#elif (NUMBER==2)
+BLS LOOP_SAD2;
+#elif (NUMBER==1)
+BLS LOOP_SAD1;
+#endif
+ }
+
+ return ((uint32)x10 >> 16);
+}
+
+#elif defined(__GNUC__) && defined(__arm__) /* ARM GNU COMPILER */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(uint8 *ref, uint8 *blk, int lx, int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(uint8 *ref, uint8 *blk, int lx, int dmin)
+#endif
+{
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+ x8 = 16; //<<===========*******
+
+__asm__ volatile("MVN %0, #0xFF0000": "=r"(x6));
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+__asm__ volatile("BIC %0, %0, #3": "=r"(ref));
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x12 = *((int32*)(ref + 16));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+
+#if (SHIFT==8)
+__asm__ volatile("MVN %0, %0, lsr #8\n\tBIC %0, %0, %1,lsl #24\n\tMVN %1, %1,lsr #8\n\tBIC %1, %1, %2,lsl #24": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==16)
+__asm__ volatile("MVN %0, %0, lsr #16\n\tBIC %0, %0, %1,lsl #16\n\tMVN %1, %1,lsr #16\n\tBIC %1, %1, %2,lsl #16": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==24)
+__asm__ volatile("MVN %0, %0, lsr #24\n\tBIC %0, %0, %1,lsl #8\n\tMVN %1, %1,lsr #24\n\tBIC %1, %1, %2,lsl #8": "=&r"(x10), "=&r"(x11): "r"(x12));
+#endif
+
+ x12 = *((int32*)(blk + 8));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixelN(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixelN(x10, x12, x9);
+
+ sum_accumulate;
+
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 4));
+ x12 = *((int32*)(ref + 8));
+ x10 = *((int32*)ref); ref += lx;
+ x14 = *((int32*)(blk + 4));
+
+#if (SHIFT==8)
+__asm__ volatile("MVN %0, %0, lsr #8\n\tBIC %0, %0, %1,lsl #24\n\tMVN %1, %1,lsr #8\n\tBIC %1, %1, %2,lsl #24": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==16)
+__asm__ volatile("MVN %0, %0, lsr #16\n\tBIC %0, %0, %1,lsl #16\n\tMVN %1, %1,lsr #16\n\tBIC %1, %1, %2,lsl #16": "=&r"(x10), "=&r"(x11): "r"(x12));
+#elif (SHIFT==24)
+__asm__ volatile("MVN %0, %0, lsr #24\n\tBIC %0, %0, %1,lsl #8\n\tMVN %1, %1,lsr #24\n\tBIC %1, %1, %2,lsl #8": "=&r"(x10), "=&r"(x11): "r"(x12));
+#endif
+__asm__ volatile("LDR %0, [%1], #16": "=&r"(x12), "=r"(blk));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixelN(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixelN(x10, x12, x9);
+
+ sum_accumulate;
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+#if (NUMBER==3)
+ goto LOOP_SAD3;
+#elif (NUMBER==2)
+goto LOOP_SAD2;
+#elif (NUMBER==1)
+goto LOOP_SAD1;
+#endif
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/avc/enc/src/slice.cpp b/media/libstagefright/codecs/avc/enc/src/slice.cpp
new file mode 100644
index 0000000..f6d066e
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/slice.cpp
@@ -0,0 +1,1025 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+
+AVCEnc_Status AVCEncodeSlice(AVCEncObject *encvid)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ AVCCommonObj *video = encvid->common;
+ AVCPicParamSet *pps = video->currPicParams;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ AVCMacroblock *currMB ;
+ AVCEncBitstream *stream = encvid->bitstream;
+ uint slice_group_id;
+ int CurrMbAddr, slice_type;
+
+ slice_type = video->slice_type;
+
+ /* set the first mb in slice */
+ video->mbNum = CurrMbAddr = sliceHdr->first_mb_in_slice;// * (1+video->MbaffFrameFlag);
+ slice_group_id = video->MbToSliceGroupMap[CurrMbAddr];
+
+ video->mb_skip_run = 0;
+
+ /* while loop , see subclause 7.3.4 */
+ while (1)
+ {
+ video->mbNum = CurrMbAddr;
+ currMB = video->currMB = &(video->mblock[CurrMbAddr]);
+ currMB->slice_id = video->slice_id; // for deblocking
+
+ video->mb_x = CurrMbAddr % video->PicWidthInMbs;
+ video->mb_y = CurrMbAddr / video->PicWidthInMbs;
+
+ /* initialize QP for this MB here*/
+ /* calculate currMB->QPy */
+ RCInitMBQP(encvid);
+
+ /* check the availability of neighboring macroblocks */
+ InitNeighborAvailability(video, CurrMbAddr);
+
+ /* Assuming that InitNeighborAvailability has been called prior to this function */
+ video->intraAvailA = video->intraAvailB = video->intraAvailC = video->intraAvailD = 0;
+ /* this is necessary for all subsequent intra search */
+
+ if (!video->currPicParams->constrained_intra_pred_flag)
+ {
+ video->intraAvailA = video->mbAvailA;
+ video->intraAvailB = video->mbAvailB;
+ video->intraAvailC = video->mbAvailC;
+ video->intraAvailD = video->mbAvailD;
+ }
+ else
+ {
+ if (video->mbAvailA)
+ {
+ video->intraAvailA = video->mblock[video->mbAddrA].mb_intra;
+ }
+ if (video->mbAvailB)
+ {
+ video->intraAvailB = video->mblock[video->mbAddrB].mb_intra ;
+ }
+ if (video->mbAvailC)
+ {
+ video->intraAvailC = video->mblock[video->mbAddrC].mb_intra;
+ }
+ if (video->mbAvailD)
+ {
+ video->intraAvailD = video->mblock[video->mbAddrD].mb_intra;
+ }
+ }
+
+ /* encode_one_macroblock() */
+ status = EncodeMB(encvid);
+ if (status != AVCENC_SUCCESS)
+ {
+ break;
+ }
+
+ /* go to next MB */
+ CurrMbAddr++;
+
+ while ((uint)video->MbToSliceGroupMap[CurrMbAddr] != slice_group_id &&
+ (uint)CurrMbAddr < video->PicSizeInMbs)
+ {
+ CurrMbAddr++;
+ }
+
+ if ((uint)CurrMbAddr >= video->PicSizeInMbs)
+ {
+ /* end of slice, return, but before that check to see if there are other slices
+ to be encoded. */
+ encvid->currSliceGroup++;
+ if (encvid->currSliceGroup > (int)pps->num_slice_groups_minus1) /* no more slice group */
+ {
+ status = AVCENC_PICTURE_READY;
+ break;
+ }
+ else
+ {
+ /* find first_mb_num for the next slice */
+ CurrMbAddr = 0;
+ while (video->MbToSliceGroupMap[CurrMbAddr] != encvid->currSliceGroup &&
+ (uint)CurrMbAddr < video->PicSizeInMbs)
+ {
+ CurrMbAddr++;
+ }
+ if ((uint)CurrMbAddr >= video->PicSizeInMbs)
+ {
+ status = AVCENC_SLICE_EMPTY; /* error, one slice group has no MBs in it */
+ }
+
+ video->mbNum = CurrMbAddr;
+ status = AVCENC_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ if (video->mb_skip_run > 0)
+ {
+ /* write skip_run */
+ if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE)
+ {
+ ue_v(stream, video->mb_skip_run);
+ video->mb_skip_run = 0;
+ }
+ else /* shouldn't happen */
+ {
+ status = AVCENC_FAIL;
+ }
+ }
+
+ return status;
+}
+
+
+AVCEnc_Status EncodeMB(AVCEncObject *encvid)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ AVCCommonObj *video = encvid->common;
+ AVCPictureData *currPic = video->currPic;
+ AVCFrameIO *currInput = encvid->currInput;
+ AVCMacroblock *currMB = video->currMB;
+ AVCMacroblock *MB_A, *MB_B;
+ AVCEncBitstream *stream = encvid->bitstream;
+ AVCRateControl *rateCtrl = encvid->rateCtrl;
+ uint8 *cur, *curL, *curCb, *curCr;
+ uint8 *orgL, *orgCb, *orgCr, *org4;
+ int CurrMbAddr = video->mbNum;
+ int picPitch = currPic->pitch;
+ int orgPitch = currInput->pitch;
+ int x_position = (video->mb_x << 4);
+ int y_position = (video->mb_y << 4);
+ int offset;
+ int b8, b4, blkidx;
+ AVCResidualType resType;
+ int slice_type;
+ int numcoeff; /* output from residual_block_cavlc */
+ int cost16, cost8;
+
+ int num_bits, start_mb_bits, start_text_bits;
+
+ slice_type = video->slice_type;
+
+ /* now, point to the reconstructed frame */
+ offset = y_position * picPitch + x_position;
+ curL = currPic->Sl + offset;
+ orgL = currInput->YCbCr[0] + offset;
+ offset = (offset + x_position) >> 2;
+ curCb = currPic->Scb + offset;
+ curCr = currPic->Scr + offset;
+ orgCb = currInput->YCbCr[1] + offset;
+ orgCr = currInput->YCbCr[2] + offset;
+
+ if (orgPitch != picPitch)
+ {
+ offset = y_position * (orgPitch - picPitch);
+ orgL += offset;
+ offset >>= 2;
+ orgCb += offset;
+ orgCr += offset;
+ }
+
+ /******* determine MB prediction mode *******/
+ if (encvid->intraSearch[CurrMbAddr])
+ {
+ MBIntraSearch(encvid, CurrMbAddr, curL, picPitch);
+ }
+ /******* This part should be determined somehow ***************/
+ if (currMB->mbMode == AVC_I_PCM)
+ {
+ /* write down mb_type and PCM data */
+ /* and copy from currInput to currPic */
+ status = EncodeIntraPCM(encvid);
+
+
+ return status;
+ }
+
+ /****** for intra prediction, pred is already done *******/
+ /****** for I4, the recon is ready and Xfrm coefs are ready to be encoded *****/
+
+ //RCCalculateMAD(encvid,currMB,orgL,orgPitch); // no need to re-calculate MAD for Intra
+ // not used since totalSAD is used instead
+
+ /* compute the prediction */
+ /* output is video->pred_block */
+ if (!currMB->mb_intra)
+ {
+ AVCMBMotionComp(encvid, video); /* perform prediction and residue calculation */
+ /* we can do the loop here and call dct_luma */
+ video->pred_pitch = picPitch;
+ currMB->CBP = 0;
+ cost16 = 0;
+ cur = curL;
+ org4 = orgL;
+
+ for (b8 = 0; b8 < 4; b8++)
+ {
+ cost8 = 0;
+
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ blkidx = blkIdx2blkXY[b8][b4];
+ video->pred_block = cur;
+ numcoeff = dct_luma(encvid, blkidx, cur, org4, &cost8);
+ currMB->nz_coeff[blkidx] = numcoeff;
+ if (numcoeff)
+ {
+ video->cbp4x4 |= (1 << blkidx);
+ currMB->CBP |= (1 << b8);
+ }
+
+ if (b4&1)
+ {
+ cur += ((picPitch << 2) - 4);
+ org4 += ((orgPitch << 2) - 4);
+ }
+ else
+ {
+ cur += 4;
+ org4 += 4;
+ }
+ }
+
+ /* move the IDCT part out of dct_luma to accommodate the check
+ for coeff_cost. */
+
+ if ((currMB->CBP&(1 << b8)) && (cost8 <= _LUMA_COEFF_COST_))
+ {
+ cost8 = 0; // reset it
+
+ currMB->CBP ^= (1 << b8);
+ blkidx = blkIdx2blkXY[b8][0];
+
+ currMB->nz_coeff[blkidx] = 0;
+ currMB->nz_coeff[blkidx+1] = 0;
+ currMB->nz_coeff[blkidx+4] = 0;
+ currMB->nz_coeff[blkidx+5] = 0;
+ }
+
+ cost16 += cost8;
+
+ if (b8&1)
+ {
+ cur -= 8;
+ org4 -= 8;
+ }
+ else
+ {
+ cur += (8 - (picPitch << 3));
+ org4 += (8 - (orgPitch << 3));
+ }
+ }
+
+ /* after the whole MB, we do another check for coeff_cost */
+ if ((currMB->CBP&0xF) && (cost16 <= _LUMA_MB_COEFF_COST_))
+ {
+ currMB->CBP = 0; // reset it to zero
+ memset(currMB->nz_coeff, 0, sizeof(uint8)*16);
+ }
+
+ // now we do IDCT
+ MBInterIdct(video, curL, currMB, picPitch);
+
+// video->pred_block = video->pred + 256;
+ }
+ else /* Intra prediction */
+ {
+ encvid->numIntraMB++;
+
+ if (currMB->mbMode == AVC_I16) /* do prediction for the whole macroblock */
+ {
+ currMB->CBP = 0;
+ /* get the prediction from encvid->pred_i16 */
+ dct_luma_16x16(encvid, curL, orgL);
+ }
+ video->pred_block = encvid->pred_ic[currMB->intra_chroma_pred_mode];
+ }
+
+ /* chrominance */
+ /* not need to do anything, the result is in encvid->pred_ic
+ chroma dct must be aware that prediction block can come from either intra or inter. */
+
+ dct_chroma(encvid, curCb, orgCb, 0);
+
+ dct_chroma(encvid, curCr, orgCr, 1);
+
+
+ /* 4.1 if there's nothing in there, video->mb_skip_run++ */
+ /* 4.2 if coded, check if there is a run of skipped MB, encodes it,
+ set video->QPyprev = currMB->QPy; */
+
+ /* 5. vlc encode */
+
+ /* check for skipped macroblock, INTER only */
+ if (!currMB->mb_intra)
+ {
+ /* decide whether this MB (for inter MB) should be skipped if there's nothing left. */
+ if (!currMB->CBP && currMB->NumMbPart == 1 && currMB->QPy == video->QPy)
+ {
+ if (currMB->MBPartPredMode[0][0] == AVC_Pred_L0 && currMB->ref_idx_L0[0] == 0)
+ {
+ MB_A = &video->mblock[video->mbAddrA];
+ MB_B = &video->mblock[video->mbAddrB];
+
+ if (!video->mbAvailA || !video->mbAvailB)
+ {
+ if (currMB->mvL0[0] == 0) /* both mv components are zeros.*/
+ {
+ currMB->mbMode = AVC_SKIP;
+ video->mvd_l0[0][0][0] = 0;
+ video->mvd_l0[0][0][1] = 0;
+ }
+ }
+ else
+ {
+ if ((MB_A->ref_idx_L0[1] == 0 && MB_A->mvL0[3] == 0) ||
+ (MB_B->ref_idx_L0[2] == 0 && MB_B->mvL0[12] == 0))
+ {
+ if (currMB->mvL0[0] == 0) /* both mv components are zeros.*/
+ {
+ currMB->mbMode = AVC_SKIP;
+ video->mvd_l0[0][0][0] = 0;
+ video->mvd_l0[0][0][1] = 0;
+ }
+ }
+ else if (video->mvd_l0[0][0][0] == 0 && video->mvd_l0[0][0][1] == 0)
+ {
+ currMB->mbMode = AVC_SKIP;
+ }
+ }
+ }
+
+ if (currMB->mbMode == AVC_SKIP)
+ {
+ video->mb_skip_run++;
+
+ /* set parameters */
+ /* not sure whether we need the followings */
+ if (slice_type == AVC_P_SLICE)
+ {
+ currMB->mbMode = AVC_SKIP;
+ currMB->MbPartWidth = currMB->MbPartHeight = 16;
+ currMB->MBPartPredMode[0][0] = AVC_Pred_L0;
+ currMB->NumMbPart = 1;
+ currMB->NumSubMbPart[0] = currMB->NumSubMbPart[1] =
+ currMB->NumSubMbPart[2] = currMB->NumSubMbPart[3] = 1;
+ currMB->SubMbPartWidth[0] = currMB->SubMbPartWidth[1] =
+ currMB->SubMbPartWidth[2] = currMB->SubMbPartWidth[3] = currMB->MbPartWidth;
+ currMB->SubMbPartHeight[0] = currMB->SubMbPartHeight[1] =
+ currMB->SubMbPartHeight[2] = currMB->SubMbPartHeight[3] = currMB->MbPartHeight;
+
+ }
+ else if (slice_type == AVC_B_SLICE)
+ {
+ currMB->mbMode = AVC_SKIP;
+ currMB->MbPartWidth = currMB->MbPartHeight = 8;
+ currMB->MBPartPredMode[0][0] = AVC_Direct;
+ currMB->NumMbPart = -1;
+ }
+
+ /* for skipped MB, always look at the first entry in RefPicList */
+ currMB->RefIdx[0] = currMB->RefIdx[1] =
+ currMB->RefIdx[2] = currMB->RefIdx[3] = video->RefPicList0[0]->RefIdx;
+
+ /* do not return yet, need to do some copies */
+ }
+ }
+ }
+ /* non-skipped MB */
+
+
+ /************* START ENTROPY CODING *************************/
+
+ start_mb_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
+
+ /* encode mb_type, mb_pred, sub_mb_pred, CBP */
+ if (slice_type != AVC_I_SLICE && slice_type != AVC_SI_SLICE && currMB->mbMode != AVC_SKIP)
+ {
+ //if(!pps->entropy_coding_mode_flag) ALWAYS true
+ {
+ ue_v(stream, video->mb_skip_run);
+ video->mb_skip_run = 0;
+ }
+ }
+
+ if (currMB->mbMode != AVC_SKIP)
+ {
+ status = EncodeMBHeader(currMB, encvid);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+
+ start_text_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
+
+ /**** now decoding part *******/
+ resType = AVC_Luma;
+
+ /* DC transform for luma I16 mode */
+ if (currMB->mbMode == AVC_I16)
+ {
+ /* vlc encode level/run */
+ status = enc_residual_block(encvid, AVC_Intra16DC, encvid->numcoefdc, currMB);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ resType = AVC_Intra16AC;
+ }
+
+ /* VLC encoding for luma */
+ for (b8 = 0; b8 < 4; b8++)
+ {
+ if (currMB->CBP&(1 << b8))
+ {
+ for (b4 = 0; b4 < 4; b4++)
+ {
+ /* vlc encode level/run */
+ status = enc_residual_block(encvid, resType, (b8 << 2) + b4, currMB);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ }
+
+ /* chroma */
+ if (currMB->CBP & (3 << 4)) /* chroma DC residual present */
+ {
+ for (b8 = 0; b8 < 2; b8++) /* for iCbCr */
+ {
+ /* vlc encode level/run */
+ status = enc_residual_block(encvid, AVC_ChromaDC, encvid->numcoefcdc[b8] + (b8 << 3), currMB);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+
+ if (currMB->CBP & (2 << 4))
+ {
+ /* AC part */
+ for (b8 = 0; b8 < 2; b8++) /* for iCbCr */
+ {
+ for (b4 = 0; b4 < 4; b4++) /* for each block inside Cb or Cr */
+ {
+ /* vlc encode level/run */
+ status = enc_residual_block(encvid, AVC_ChromaAC, 16 + (b8 << 2) + b4, currMB);
+ if (status != AVCENC_SUCCESS)
+ {
+ return status;
+ }
+ }
+ }
+ }
+
+
+ num_bits = 32 + (encvid->bitstream->write_pos << 3) - encvid->bitstream->bit_left;
+
+ RCPostMB(video, rateCtrl, start_text_bits - start_mb_bits,
+ num_bits - start_text_bits);
+
+// num_bits -= start_mb_bits;
+// fprintf(fdebug,"MB #%d: %d bits\n",CurrMbAddr,num_bits);
+// fclose(fdebug);
+ return status;
+}
+
+/* copy the content from predBlock back to the reconstructed YUV frame */
+void Copy_MB(uint8 *curL, uint8 *curCb, uint8 *curCr, uint8 *predBlock, int picPitch)
+{
+ int j, offset;
+ uint32 *dst, *dst2, *src;
+
+ dst = (uint32*)curL;
+ src = (uint32*)predBlock;
+
+ offset = (picPitch - 16) >> 2;
+
+ for (j = 0; j < 16; j++)
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+
+ dst += offset;
+ }
+
+ dst = (uint32*)curCb;
+ dst2 = (uint32*)curCr;
+ offset >>= 1;
+
+ for (j = 0; j < 8; j++)
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ *dst2++ = *src++;
+ *dst2++ = *src++;
+
+ dst += offset;
+ dst2 += offset;
+ }
+ return ;
+}
+
+/* encode mb_type, mb_pred, sub_mb_pred, CBP */
+/* decide whether this MB (for inter MB) should be skipped */
+AVCEnc_Status EncodeMBHeader(AVCMacroblock *currMB, AVCEncObject *encvid)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ uint mb_type;
+ AVCCommonObj *video = encvid->common;
+ AVCEncBitstream *stream = encvid->bitstream;
+
+ if (currMB->CBP > 47) /* chroma CBP is 11 */
+ {
+ currMB->CBP -= 16; /* remove the 5th bit from the right */
+ }
+
+ mb_type = InterpretMBType(currMB, video->slice_type);
+
+ status = ue_v(stream, mb_type);
+
+ if (currMB->mbMode == AVC_P8 || currMB->mbMode == AVC_P8ref0)
+ {
+ status = sub_mb_pred(video, currMB, stream);
+ }
+ else
+ {
+ status = mb_pred(video, currMB, stream) ;
+ }
+
+ if (currMB->mbMode != AVC_I16)
+ {
+ /* decode coded_block_pattern */
+ status = EncodeCBP(currMB, stream);
+ }
+
+ /* calculate currMB->mb_qp_delta = currMB->QPy - video->QPyprev */
+ if (currMB->CBP > 0 || currMB->mbMode == AVC_I16)
+ {
+ status = se_v(stream, currMB->QPy - video->QPy);
+ video->QPy = currMB->QPy; /* = (video->QPyprev + currMB->mb_qp_delta + 52)%52; */
+ // no need video->QPc = currMB->QPc;
+ }
+ else
+ {
+ if (currMB->QPy != video->QPy) // current QP is not the same as previous QP
+ {
+ /* restore these values */
+ RCRestoreQP(currMB, video, encvid);
+ }
+ }
+
+ return status;
+}
+
+
+/* inputs are mbMode, mb_intra, i16Mode, CBP, NumMbPart, MbPartWidth, MbPartHeight */
+uint InterpretMBType(AVCMacroblock *currMB, int slice_type)
+{
+ int CBP_chrom;
+ int mb_type;// part1, part2, part3;
+// const static int MapParts2Type[2][3][3]={{{4,8,12},{10,6,14},{16,18,20}},
+// {{5,9,13},{11,7,15},{17,19,21}}};
+
+ if (currMB->mb_intra)
+ {
+ if (currMB->mbMode == AVC_I4)
+ {
+ mb_type = 0;
+ }
+ else if (currMB->mbMode == AVC_I16)
+ {
+ CBP_chrom = (currMB->CBP & 0x30);
+ if (currMB->CBP&0xF)
+ {
+ currMB->CBP |= 0xF; /* either 0x0 or 0xF */
+ mb_type = 13;
+ }
+ else
+ {
+ mb_type = 1;
+ }
+ mb_type += (CBP_chrom >> 2) + currMB->i16Mode;
+ }
+ else /* if(currMB->mbMode == AVC_I_PCM) */
+ {
+ mb_type = 25;
+ }
+ }
+ else
+ { /* P-MB *//* note that the order of the enum AVCMBMode cannot be changed
+ since we use it here. */
+ mb_type = currMB->mbMode - AVC_P16;
+ }
+
+ if (slice_type == AVC_P_SLICE)
+ {
+ if (currMB->mb_intra)
+ {
+ mb_type += 5;
+ }
+ }
+ // following codes have not been tested yet, not needed.
+ /* else if(slice_type == AVC_B_SLICE)
+ {
+ if(currMB->mbMode == AVC_BDirect16)
+ {
+ mb_type = 0;
+ }
+ else if(currMB->mbMode == AVC_P16)
+ {
+ mb_type = currMB->MBPartPredMode[0][0] + 1; // 1 or 2
+ }
+ else if(currMB->mbMode == AVC_P8)
+ {
+ mb_type = 26;
+ }
+ else if(currMB->mbMode == AVC_P8ref0)
+ {
+ mb_type = 27;
+ }
+ else
+ {
+ part1 = currMB->mbMode - AVC_P16x8;
+ part2 = currMB->MBPartPredMode[0][0];
+ part3 = currMB->MBPartPredMode[1][0];
+ mb_type = MapParts2Type[part1][part2][part3];
+ }
+ }
+
+ if(slice_type == AVC_SI_SLICE)
+ {
+ mb_type++;
+ }
+ */
+ return (uint)mb_type;
+}
+
+//const static int mbPart2raster[3][4] = {{0,0,0,0},{1,1,0,0},{1,0,1,0}};
+
+/* see subclause 7.3.5.1 */
+AVCEnc_Status mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ int mbPartIdx;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ int max_ref_idx;
+ uint code;
+
+ if (currMB->mbMode == AVC_I4 || currMB->mbMode == AVC_I16)
+ {
+ if (currMB->mbMode == AVC_I4)
+ {
+ /* perform prediction to get the actual intra 4x4 pred mode */
+ EncodeIntra4x4Mode(video, currMB, stream);
+ /* output will be in currMB->i4Mode[4][4] */
+ }
+
+ /* assume already set from MBPrediction() */
+ status = ue_v(stream, currMB->intra_chroma_pred_mode);
+ }
+ else if (currMB->MBPartPredMode[0][0] != AVC_Direct)
+ {
+
+ memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
+
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+ max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
+ /* if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+ max_ref_idx = 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1;
+ */
+ /* decode ref index for L0 */
+ if (sliceHdr->num_ref_idx_l0_active_minus1 > 0)
+ {
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ if (/*(sliceHdr->num_ref_idx_l0_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
+ currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+ {
+ code = currMB->ref_idx_L0[mbPartIdx];
+ status = te_v(stream, code, max_ref_idx);
+ }
+ }
+ }
+
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+ max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
+ /* if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+ max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;
+ */
+ /* decode ref index for L1 */
+ if (sliceHdr->num_ref_idx_l1_active_minus1 > 0)
+ {
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ if (/*(sliceHdr->num_ref_idx_l1_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
+ currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+ {
+ status = te_v(stream, currMB->ref_idx_L1[mbPartIdx], max_ref_idx);
+ }
+ }
+ }
+
+ /* encode mvd_l0 */
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ if (currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+ {
+ status = se_v(stream, video->mvd_l0[mbPartIdx][0][0]);
+ status = se_v(stream, video->mvd_l0[mbPartIdx][0][1]);
+ }
+ }
+ /* encode mvd_l1 */
+ for (mbPartIdx = 0; mbPartIdx < currMB->NumMbPart; mbPartIdx++)
+ {
+ if (currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+ {
+ status = se_v(stream, video->mvd_l1[mbPartIdx][0][0]);
+ status = se_v(stream, video->mvd_l1[mbPartIdx][0][1]);
+ }
+ }
+ }
+
+ return status;
+}
+
+/* see subclause 7.3.5.2 */
+AVCEnc_Status sub_mb_pred(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ int mbPartIdx, subMbPartIdx;
+ AVCSliceHeader *sliceHdr = video->sliceHdr;
+ uint max_ref_idx;
+ uint slice_type = video->slice_type;
+ uint sub_mb_type[4];
+
+ /* this should move somewhere else where we don't have to make this check */
+ if (currMB->mbMode == AVC_P8ref0)
+ {
+ memset(currMB->ref_idx_L0, 0, sizeof(int16)*4);
+ }
+
+ /* we have to check the values to make sure they are valid */
+ /* assign values to currMB->sub_mb_type[] */
+ if (slice_type == AVC_P_SLICE)
+ {
+ InterpretSubMBTypeP(currMB, sub_mb_type);
+ }
+ /* no need to check for B-slice
+ else if(slice_type == AVC_B_SLICE)
+ {
+ InterpretSubMBTypeB(currMB,sub_mb_type);
+ }*/
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ status = ue_v(stream, sub_mb_type[mbPartIdx]);
+ }
+
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+ max_ref_idx = sliceHdr->num_ref_idx_l0_active_minus1;
+ /* if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+ max_ref_idx = 2*sliceHdr->num_ref_idx_l0_active_minus1 + 1; */
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ if ((sliceHdr->num_ref_idx_l0_active_minus1 > 0 /*|| currMB->mb_field_decoding_flag*/) &&
+ currMB->mbMode != AVC_P8ref0 && /*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+ currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+ {
+ status = te_v(stream, currMB->ref_idx_L0[mbPartIdx], max_ref_idx);
+ }
+ /* used in deblocking */
+ currMB->RefIdx[mbPartIdx] = video->RefPicList0[currMB->ref_idx_L0[mbPartIdx]]->RefIdx;
+ }
+ /* see subclause 7.4.5.1 for the range of ref_idx_lX */
+ max_ref_idx = sliceHdr->num_ref_idx_l1_active_minus1;
+ /* if(video->MbaffFrameFlag && currMB->mb_field_decoding_flag)
+ max_ref_idx = 2*sliceHdr->num_ref_idx_l1_active_minus1 + 1;*/
+
+ if (sliceHdr->num_ref_idx_l1_active_minus1 > 0)
+ {
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ if (/*(sliceHdr->num_ref_idx_l1_active_minus1>0 || currMB->mb_field_decoding_flag) &&*/
+ /*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+ currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+ {
+ status = te_v(stream, currMB->ref_idx_L1[mbPartIdx], max_ref_idx);
+ }
+ }
+ }
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ if (/*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+ currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L1)
+ {
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ status = se_v(stream, video->mvd_l0[mbPartIdx][subMbPartIdx][0]);
+ status = se_v(stream, video->mvd_l0[mbPartIdx][subMbPartIdx][1]);
+ }
+ }
+ }
+
+ for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++)
+ {
+ if (/*currMB->subMbMode[mbPartIdx]!=AVC_BDirect8 &&*/
+ currMB->MBPartPredMode[mbPartIdx][0] != AVC_Pred_L0)
+ {
+ for (subMbPartIdx = 0; subMbPartIdx < currMB->NumSubMbPart[mbPartIdx]; subMbPartIdx++)
+ {
+ status = se_v(stream, video->mvd_l1[mbPartIdx][subMbPartIdx][0]);
+ status = se_v(stream, video->mvd_l1[mbPartIdx][subMbPartIdx][1]);
+ }
+ }
+ }
+
+ return status;
+}
+
+/* input is mblock->sub_mb_type[] */
+void InterpretSubMBTypeP(AVCMacroblock *mblock, uint *sub_mb_type)
+{
+ int i;
+ /* see enum AVCMBType declaration */
+ /*const static AVCSubMBMode map2subMbMode[4] = {AVC_8x8,AVC_8x4,AVC_4x8,AVC_4x4};
+ const static int map2subPartWidth[4] = {8,8,4,4};
+ const static int map2subPartHeight[4] = {8,4,8,4};
+ const static int map2numSubPart[4] = {1,2,2,4};*/
+
+ for (i = 0; i < 4 ; i++)
+ {
+ sub_mb_type[i] = mblock->subMbMode[i] - AVC_8x8;
+ }
+
+ return ;
+}
+
+void InterpretSubMBTypeB(AVCMacroblock *mblock, uint *sub_mb_type)
+{
+ int i;
+ /* see enum AVCMBType declaration */
+ /* const static AVCSubMBMode map2subMbMode[13] = {AVC_BDirect8,AVC_8x8,AVC_8x8,
+ AVC_8x8,AVC_8x4,AVC_4x8,AVC_8x4,AVC_4x8,AVC_8x4,AVC_4x8,AVC_4x4,AVC_4x4,AVC_4x4};
+ const static int map2subPartWidth[13] = {4,8,8,8,8,4,8,4,8,4,4,4,4};
+ const static int map2subPartHeight[13] = {4,8,8,8,4,8,4,8,4,8,4,4,4};
+ const static int map2numSubPart[13] = {4,1,1,1,2,2,2,2,2,2,4,4,4};
+ const static int map2predMode[13] = {3,0,1,2,0,0,1,1,2,2,0,1,2};*/
+
+ for (i = 0; i < 4 ; i++)
+ {
+ if (mblock->subMbMode[i] == AVC_BDirect8)
+ {
+ sub_mb_type[i] = 0;
+ }
+ else if (mblock->subMbMode[i] == AVC_8x8)
+ {
+ sub_mb_type[i] = 1 + mblock->MBPartPredMode[i][0];
+ }
+ else if (mblock->subMbMode[i] == AVC_4x4)
+ {
+ sub_mb_type[i] = 10 + mblock->MBPartPredMode[i][0];
+ }
+ else
+ {
+ sub_mb_type[i] = 4 + (mblock->MBPartPredMode[i][0] << 1) + (mblock->subMbMode[i] - AVC_8x4);
+ }
+ }
+
+ return ;
+}
+
+/* see subclause 8.3.1 */
+AVCEnc_Status EncodeIntra4x4Mode(AVCCommonObj *video, AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+ int intra4x4PredModeA = 0;
+ int intra4x4PredModeB, predIntra4x4PredMode;
+ int component, SubBlock_indx, block_x, block_y;
+ int dcOnlyPredictionFlag;
+ uint flag;
+ int rem = 0;
+ int mode;
+ int bindx = 0;
+
+ for (component = 0; component < 4; component++) /* partition index */
+ {
+ block_x = ((component & 1) << 1);
+ block_y = ((component >> 1) << 1);
+
+ for (SubBlock_indx = 0; SubBlock_indx < 4; SubBlock_indx++) /* sub-partition index */
+ {
+ dcOnlyPredictionFlag = 0;
+ if (block_x > 0)
+ {
+ intra4x4PredModeA = currMB->i4Mode[(block_y << 2) + block_x - 1 ];
+ }
+ else
+ {
+ if (video->intraAvailA)
+ {
+ if (video->mblock[video->mbAddrA].mbMode == AVC_I4)
+ {
+ intra4x4PredModeA = video->mblock[video->mbAddrA].i4Mode[(block_y << 2) + 3];
+ }
+ else
+ {
+ intra4x4PredModeA = AVC_I4_DC;
+ }
+ }
+ else
+ {
+ dcOnlyPredictionFlag = 1;
+ }
+ }
+
+ if (block_y > 0)
+ {
+ intra4x4PredModeB = currMB->i4Mode[((block_y-1) << 2) + block_x];
+ }
+ else
+ {
+ if (video->intraAvailB)
+ {
+ if (video->mblock[video->mbAddrB].mbMode == AVC_I4)
+ {
+ intra4x4PredModeB = video->mblock[video->mbAddrB].i4Mode[(3 << 2) + block_x];
+ }
+ else
+ {
+ intra4x4PredModeB = AVC_I4_DC;
+ }
+ }
+ else
+ {
+ dcOnlyPredictionFlag = 1;
+ }
+ }
+
+ if (dcOnlyPredictionFlag)
+ {
+ intra4x4PredModeA = intra4x4PredModeB = AVC_I4_DC;
+ }
+
+ predIntra4x4PredMode = AVC_MIN(intra4x4PredModeA, intra4x4PredModeB);
+
+ flag = 0;
+ mode = currMB->i4Mode[(block_y<<2)+block_x];
+
+ if (mode == (AVCIntra4x4PredMode)predIntra4x4PredMode)
+ {
+ flag = 1;
+ }
+ else if (mode < predIntra4x4PredMode)
+ {
+ rem = mode;
+ }
+ else
+ {
+ rem = mode - 1;
+ }
+
+ BitstreamWrite1Bit(stream, flag);
+
+ if (!flag)
+ {
+ BitstreamWriteBits(stream, 3, rem);
+ }
+
+ bindx++;
+ block_y += (SubBlock_indx & 1) ;
+ block_x += (1 - 2 * (SubBlock_indx & 1)) ;
+ }
+ }
+
+ return AVCENC_SUCCESS;
+}
+
+
+
diff --git a/media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp b/media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp
new file mode 100644
index 0000000..222e709
--- /dev/null
+++ b/media/libstagefright/codecs/avc/enc/src/vlc_encode.cpp
@@ -0,0 +1,336 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "avcenc_lib.h"
+
+/**
+See algorithm in subclause 9.1, Table 9-1, Table 9-2. */
+AVCEnc_Status ue_v(AVCEncBitstream *bitstream, uint codeNum)
+{
+ if (AVCENC_SUCCESS != SetEGBitstring(bitstream, codeNum))
+ return AVCENC_FAIL;
+
+ return AVCENC_SUCCESS;
+}
+
+/**
+See subclause 9.1.1, Table 9-3 */
+AVCEnc_Status se_v(AVCEncBitstream *bitstream, int value)
+{
+ uint codeNum;
+ AVCEnc_Status status;
+
+ if (value <= 0)
+ {
+ codeNum = -value * 2;
+ }
+ else
+ {
+ codeNum = value * 2 - 1;
+ }
+
+ status = ue_v(bitstream, codeNum);
+
+ return status;
+}
+
+AVCEnc_Status te_v(AVCEncBitstream *bitstream, uint value, uint range)
+{
+ AVCEnc_Status status;
+
+ if (range > 1)
+ {
+ return ue_v(bitstream, value);
+ }
+ else
+ {
+ status = BitstreamWrite1Bit(bitstream, 1 - value);
+ return status;
+ }
+}
+
+/**
+See subclause 9.1, Table 9-1, 9-2. */
+// compute leadingZeros and inforbits
+//codeNum = (1<<leadingZeros)-1+infobits;
+AVCEnc_Status SetEGBitstring(AVCEncBitstream *bitstream, uint codeNum)
+{
+ AVCEnc_Status status;
+ int leadingZeros;
+ int infobits;
+
+ if (!codeNum)
+ {
+ status = BitstreamWrite1Bit(bitstream, 1);
+ return status;
+ }
+
+ /* calculate leadingZeros and infobits */
+ leadingZeros = 1;
+ while ((uint)(1 << leadingZeros) < codeNum + 2)
+ {
+ leadingZeros++;
+ }
+ leadingZeros--;
+ infobits = codeNum - (1 << leadingZeros) + 1;
+
+ status = BitstreamWriteBits(bitstream, leadingZeros, 0);
+ infobits |= (1 << leadingZeros);
+ status = BitstreamWriteBits(bitstream, leadingZeros + 1, infobits);
+ return status;
+}
+
+/* see Table 9-4 assignment of codeNum to values of coded_block_pattern. */
+const static uint8 MapCBP2code[48][2] =
+{
+ {3, 0}, {29, 2}, {30, 3}, {17, 7}, {31, 4}, {18, 8}, {37, 17}, {8, 13}, {32, 5}, {38, 18}, {19, 9}, {9, 14},
+ {20, 10}, {10, 15}, {11, 16}, {2, 11}, {16, 1}, {33, 32}, {34, 33}, {21, 36}, {35, 34}, {22, 37}, {39, 44}, {4, 40},
+ {36, 35}, {40, 45}, {23, 38}, {5, 41}, {24, 39}, {6, 42}, {7, 43}, {1, 19}, {41, 6}, {42, 24}, {43, 25}, {25, 20},
+ {44, 26}, {26, 21}, {46, 46}, {12, 28}, {45, 27}, {47, 47}, {27, 22}, {13, 29}, {28, 23}, {14, 30}, {15, 31}, {0, 12}
+};
+
+AVCEnc_Status EncodeCBP(AVCMacroblock *currMB, AVCEncBitstream *stream)
+{
+ AVCEnc_Status status;
+ uint codeNum;
+
+ if (currMB->mbMode == AVC_I4)
+ {
+ codeNum = MapCBP2code[currMB->CBP][0];
+ }
+ else
+ {
+ codeNum = MapCBP2code[currMB->CBP][1];
+ }
+
+ status = ue_v(stream, codeNum);
+
+ return status;
+}
+
+AVCEnc_Status ce_TotalCoeffTrailingOnes(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff, int nC)
+{
+ const static uint8 totCoeffTrailOne[3][4][17][2] =
+ {
+ { // 0702
+ {{1, 1}, {6, 5}, {8, 7}, {9, 7}, {10, 7}, {11, 7}, {13, 15}, {13, 11}, {13, 8}, {14, 15}, {14, 11}, {15, 15}, {15, 11}, {16, 15}, {16, 11}, {16, 7}, {16, 4}},
+ {{0, 0}, {2, 1}, {6, 4}, {8, 6}, {9, 6}, {10, 6}, {11, 6}, {13, 14}, {13, 10}, {14, 14}, {14, 10}, {15, 14}, {15, 10}, {15, 1}, {16, 14}, {16, 10}, {16, 6}},
+ {{0, 0}, {0, 0}, {3, 1}, {7, 5}, {8, 5}, {9, 5}, {10, 5}, {11, 5}, {13, 13}, {13, 9}, {14, 13}, {14, 9}, {15, 13}, {15, 9}, {16, 13}, {16, 9}, {16, 5}},
+ {{0, 0}, {0, 0}, {0, 0}, {5, 3}, {6, 3}, {7, 4}, {8, 4}, {9, 4}, {10, 4}, {11, 4}, {13, 12}, {14, 12}, {14, 8}, {15, 12}, {15, 8}, {16, 12}, {16, 8}},
+ },
+ {
+ {{2, 3}, {6, 11}, {6, 7}, {7, 7}, {8, 7}, {8, 4}, {9, 7}, {11, 15}, {11, 11}, {12, 15}, {12, 11}, {12, 8}, {13, 15}, {13, 11}, {13, 7}, {14, 9}, {14, 7}},
+ {{0, 0}, {2, 2}, {5, 7}, {6, 10}, {6, 6}, {7, 6}, {8, 6}, {9, 6}, {11, 14}, {11, 10}, {12, 14}, {12, 10}, {13, 14}, {13, 10}, {14, 11}, {14, 8}, {14, 6}},
+ {{0, 0}, {0, 0}, {3, 3}, {6, 9}, {6, 5}, {7, 5}, {8, 5}, {9, 5}, {11, 13}, {11, 9}, {12, 13}, {12, 9}, {13, 13}, {13, 9}, {13, 6}, {14, 10}, {14, 5}},
+ {{0, 0}, {0, 0}, {0, 0}, {4, 5}, {4, 4}, {5, 6}, {6, 8}, {6, 4}, {7, 4}, {9, 4}, {11, 12}, {11, 8}, {12, 12}, {13, 12}, {13, 8}, {13, 1}, {14, 4}},
+ },
+ {
+ {{4, 15}, {6, 15}, {6, 11}, {6, 8}, {7, 15}, {7, 11}, {7, 9}, {7, 8}, {8, 15}, {8, 11}, {9, 15}, {9, 11}, {9, 8}, {10, 13}, {10, 9}, {10, 5}, {10, 1}},
+ {{0, 0}, {4, 14}, {5, 15}, {5, 12}, {5, 10}, {5, 8}, {6, 14}, {6, 10}, {7, 14}, {8, 14}, {8, 10}, {9, 14}, {9, 10}, {9, 7}, {10, 12}, {10, 8}, {10, 4}},
+ {{0, 0}, {0, 0}, {4, 13}, {5, 14}, {5, 11}, {5, 9}, {6, 13}, {6, 9}, {7, 13}, {7, 10}, {8, 13}, {8, 9}, {9, 13}, {9, 9}, {10, 11}, {10, 7}, {10, 3}},
+ {{0, 0}, {0, 0}, {0, 0}, {4, 12}, {4, 11}, {4, 10}, {4, 9}, {4, 8}, {5, 13}, {6, 12}, {7, 12}, {8, 12}, {8, 8}, {9, 12}, {10, 10}, {10, 6}, {10, 2}}
+ }
+ };
+
+
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ uint code, len;
+ int vlcnum;
+
+ if (TrailingOnes > 3)
+ {
+ return AVCENC_TRAILINGONES_FAIL;
+ }
+
+ if (nC >= 8)
+ {
+ if (TotalCoeff)
+ {
+ code = ((TotalCoeff - 1) << 2) | (TrailingOnes);
+ }
+ else
+ {
+ code = 3;
+ }
+ status = BitstreamWriteBits(stream, 6, code);
+ }
+ else
+ {
+ if (nC < 2)
+ {
+ vlcnum = 0;
+ }
+ else if (nC < 4)
+ {
+ vlcnum = 1;
+ }
+ else
+ {
+ vlcnum = 2;
+ }
+
+ len = totCoeffTrailOne[vlcnum][TrailingOnes][TotalCoeff][0];
+ code = totCoeffTrailOne[vlcnum][TrailingOnes][TotalCoeff][1];
+ status = BitstreamWriteBits(stream, len, code);
+ }
+
+ return status;
+}
+
+AVCEnc_Status ce_TotalCoeffTrailingOnesChromaDC(AVCEncBitstream *stream, int TrailingOnes, int TotalCoeff)
+{
+ const static uint8 totCoeffTrailOneChrom[4][5][2] =
+ {
+ { {2, 1}, {6, 7}, {6, 4}, {6, 3}, {6, 2}},
+ { {0, 0}, {1, 1}, {6, 6}, {7, 3}, {8, 3}},
+ { {0, 0}, {0, 0}, {3, 1}, {7, 2}, {8, 2}},
+ { {0, 0}, {0, 0}, {0, 0}, {6, 5}, {7, 0}},
+ };
+
+ AVCEnc_Status status = AVCENC_SUCCESS;
+ uint code, len;
+
+ len = totCoeffTrailOneChrom[TrailingOnes][TotalCoeff][0];
+ code = totCoeffTrailOneChrom[TrailingOnes][TotalCoeff][1];
+ status = BitstreamWriteBits(stream, len, code);
+
+ return status;
+}
+
+/* see Table 9-7 and 9-8 */
+AVCEnc_Status ce_TotalZeros(AVCEncBitstream *stream, int total_zeros, int TotalCoeff)
+{
+ const static uint8 lenTotalZeros[15][16] =
+ {
+ { 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 9},
+ { 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6},
+ { 4, 3, 3, 3, 4, 4, 3, 3, 4, 5, 5, 6, 5, 6},
+ { 5, 3, 4, 4, 3, 3, 3, 4, 3, 4, 5, 5, 5},
+ { 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 4, 5},
+ { 6, 5, 3, 3, 3, 3, 3, 3, 4, 3, 6},
+ { 6, 5, 3, 3, 3, 2, 3, 4, 3, 6},
+ { 6, 4, 5, 3, 2, 2, 3, 3, 6},
+ { 6, 6, 4, 2, 2, 3, 2, 5},
+ { 5, 5, 3, 2, 2, 2, 4},
+ { 4, 4, 3, 3, 1, 3},
+ { 4, 4, 2, 1, 3},
+ { 3, 3, 1, 2},
+ { 2, 2, 1},
+ { 1, 1},
+ };
+
+ const static uint8 codTotalZeros[15][16] =
+ {
+ {1, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 1},
+ {7, 6, 5, 4, 3, 5, 4, 3, 2, 3, 2, 3, 2, 1, 0},
+ {5, 7, 6, 5, 4, 3, 4, 3, 2, 3, 2, 1, 1, 0},
+ {3, 7, 5, 4, 6, 5, 4, 3, 3, 2, 2, 1, 0},
+ {5, 4, 3, 7, 6, 5, 4, 3, 2, 1, 1, 0},
+ {1, 1, 7, 6, 5, 4, 3, 2, 1, 1, 0},
+ {1, 1, 5, 4, 3, 3, 2, 1, 1, 0},
+ {1, 1, 1, 3, 3, 2, 2, 1, 0},
+ {1, 0, 1, 3, 2, 1, 1, 1, },
+ {1, 0, 1, 3, 2, 1, 1, },
+ {0, 1, 1, 2, 1, 3},
+ {0, 1, 1, 1, 1},
+ {0, 1, 1, 1},
+ {0, 1, 1},
+ {0, 1},
+ };
+ int len, code;
+ AVCEnc_Status status;
+
+ len = lenTotalZeros[TotalCoeff-1][total_zeros];
+ code = codTotalZeros[TotalCoeff-1][total_zeros];
+
+ status = BitstreamWriteBits(stream, len, code);
+
+ return status;
+}
+
+/* see Table 9-9 */
+AVCEnc_Status ce_TotalZerosChromaDC(AVCEncBitstream *stream, int total_zeros, int TotalCoeff)
+{
+ const static uint8 lenTotalZerosChromaDC[3][4] =
+ {
+ { 1, 2, 3, 3, },
+ { 1, 2, 2, 0, },
+ { 1, 1, 0, 0, },
+ };
+
+ const static uint8 codTotalZerosChromaDC[3][4] =
+ {
+ { 1, 1, 1, 0, },
+ { 1, 1, 0, 0, },
+ { 1, 0, 0, 0, },
+ };
+
+ int len, code;
+ AVCEnc_Status status;
+
+ len = lenTotalZerosChromaDC[TotalCoeff-1][total_zeros];
+ code = codTotalZerosChromaDC[TotalCoeff-1][total_zeros];
+
+ status = BitstreamWriteBits(stream, len, code);
+
+ return status;
+}
+
+/* see Table 9-10 */
+AVCEnc_Status ce_RunBefore(AVCEncBitstream *stream, int run_before, int zerosLeft)
+{
+ const static uint8 lenRunBefore[7][16] =
+ {
+ {1, 1},
+ {1, 2, 2},
+ {2, 2, 2, 2},
+ {2, 2, 2, 3, 3},
+ {2, 2, 3, 3, 3, 3},
+ {2, 3, 3, 3, 3, 3, 3},
+ {3, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11},
+ };
+
+ const static uint8 codRunBefore[7][16] =
+ {
+ {1, 0},
+ {1, 1, 0},
+ {3, 2, 1, 0},
+ {3, 2, 1, 1, 0},
+ {3, 2, 3, 2, 1, 0},
+ {3, 0, 1, 3, 2, 5, 4},
+ {7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+ };
+
+ int len, code;
+ AVCEnc_Status status;
+
+ if (zerosLeft <= 6)
+ {
+ len = lenRunBefore[zerosLeft-1][run_before];
+ code = codRunBefore[zerosLeft-1][run_before];
+ }
+ else
+ {
+ len = lenRunBefore[6][run_before];
+ code = codRunBefore[6][run_before];
+ }
+
+ status = BitstreamWriteBits(stream, len, code);
+
+
+ return status;
+}
diff --git a/media/libstagefright/codecs/common/Android.mk b/media/libstagefright/codecs/common/Android.mk
new file mode 100644
index 0000000..fffb2ad
--- /dev/null
+++ b/media/libstagefright/codecs/common/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_SRC_FILES := cmnMemory.c
+
+LOCAL_MODULE := libstagefright_enc_common
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/include
+
+LOCAL_CFLAGS := $(VO_CFLAGS)
+
+ifeq ($(VOTT), v5)
+LOCAL_CFLAGS += -DARM -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+endif
+
+ifeq ($(VOTT), v7)
+LOCAL_CFLAGS += -DARM -DARMV7 -DASM_OPT
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV5E
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/src/asm/ARMV7
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+
diff --git a/media/libstagefright/codecs/common/Config.mk b/media/libstagefright/codecs/common/Config.mk
new file mode 100644
index 0000000..27a17c1
--- /dev/null
+++ b/media/libstagefright/codecs/common/Config.mk
@@ -0,0 +1,24 @@
+#
+# This configure file is just for Linux projects against Android
+#
+
+VOPRJ :=
+VONJ :=
+
+# WARNING:
+# Using v7 breaks generic build
+ifeq ($(TARGET_ARCH),arm)
+VOTT := v5
+else
+VOTT := pc
+endif
+
+# Do we also need to check on ARCH_ARM_HAVE_ARMV7A? - probably not
+ifeq ($(ARCH_ARM_HAVE_NEON),true)
+VOTT := v7
+endif
+
+VOTEST := 0
+
+VO_CFLAGS:=-DLINUX
+
diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/libstagefright/codecs/common/cmnMemory.c
new file mode 100644
index 0000000..c17264c
--- /dev/null
+++ b/media/libstagefright/codecs/common/cmnMemory.c
@@ -0,0 +1,73 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: cmnMemory.c
+
+ Content: sample code for memory operator implementation
+
+*******************************************************************************/
+#include "cmnMemory.h"
+
+#include <malloc.h>
+#if defined LINUX
+#include <string.h>
+#endif
+
+//VO_MEM_OPERATOR g_memOP;
+
+VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo)
+{
+ if (!pMemInfo)
+ return VO_ERR_INVALID_ARG;
+
+ pMemInfo->VBuffer = malloc (pMemInfo->Size);
+ return 0;
+}
+
+VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pMem)
+{
+ free (pMem);
+ return 0;
+}
+
+VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize)
+{
+ memset (pBuff, uValue, uSize);
+ return 0;
+}
+
+VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)
+{
+ memcpy (pDest, pSource, uSize);
+ return 0;
+}
+
+VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize)
+{
+ return 0;
+}
+
+VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize)
+{
+ return memcmp(pBuffer1, pBuffer2, uSize);
+}
+
+VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize)
+{
+ memmove (pDest, pSource, uSize);
+ return 0;
+}
+
diff --git a/media/libstagefright/codecs/common/include/cmnMemory.h b/media/libstagefright/codecs/common/include/cmnMemory.h
new file mode 100644
index 0000000..9315600
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/cmnMemory.h
@@ -0,0 +1,106 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: cmnMemory.h
+
+ Content: memory operator implementation header file
+
+*******************************************************************************/
+
+#ifndef __cmnMemory_H__
+#define __cmnMemory_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <voMem.h>
+
+//extern VO_MEM_OPERATOR g_memOP;
+
+/**
+ * Allocate memory
+ * \param uID [in] module ID
+ * \param uSize [in] size of memory
+ * \return value is the allocated memory address. NULL is failed.
+ */
+VO_U32 cmnMemAlloc (VO_S32 uID, VO_MEM_INFO * pMemInfo);
+
+/**
+ * Free up memory
+ * \param uID [in] module ID
+ * \param pMem [in] address of memory
+ * \return value 0, if succeeded.
+ */
+VO_U32 cmnMemFree (VO_S32 uID, VO_PTR pBuffer);
+
+/**
+ * memory set function
+ * \param uID [in] module ID
+ * \param pBuff [in/out] address of memory
+ * \param uValue [in] the value to be set
+ * \param uSize [in] the size to be set
+ * \return value 0, if succeeded.
+ */
+VO_U32 cmnMemSet (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize);
+
+/**
+ * memory copy function
+ * \param uID [in] module ID
+ * \param pDest [in/out] address of destination memory
+ * \param pSource [in] address of source memory
+ * \param uSize [in] the size to be copied
+ * \return value 0, if succeeded.
+ */
+VO_U32 cmnMemCopy (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);
+
+/**
+ * memory check function
+ * \param uID [in] module ID
+ * \param pBuff [in] address of buffer to be checked
+ * \param uSize [in] the size to be checked
+ * \return value 0, if succeeded.
+ */
+VO_U32 cmnMemCheck (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize);
+
+/**
+ * memory compare function
+ * \param uID [in] module ID
+ * \param pBuffer1 [in] address of buffer 1 to be compared
+ * \param pBuffer2 [in] address of buffer 2 to be compared
+ * \param uSize [in] the size to be compared
+ * \return value: same as standard C run-time memcmp() function.
+ */
+VO_S32 cmnMemCompare (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize);
+
+/**
+ * memory move function
+ * \param uID [in] module ID
+ * \param pDest [in/out] address of destination memory
+ * \param pSource [in] address of source memory
+ * \param uSize [in] the size to be moved
+ * \return value 0, if succeeded.
+ */
+VO_U32 cmnMemMove (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __cmnMemory_H__
+
+
diff --git a/media/libstagefright/codecs/common/include/voAAC.h b/media/libstagefright/codecs/common/include/voAAC.h
new file mode 100644
index 0000000..d11ed83
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voAAC.h
@@ -0,0 +1,74 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voAAC.h
+
+ Content: AAC codec APIs & data types
+
+*******************************************************************************/
+
+#ifndef __voAAC_H__
+#define __voAAC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "voAudio.h"
+
+/*!
+ * the frame type that the decoder supports
+ */
+typedef enum {
+ VOAAC_RAWDATA = 0, /*!<contains only raw aac data in a frame*/
+ VOAAC_ADTS = 1, /*!<contains ADTS header + raw AAC data in a frame*/
+ VOAAC_FT_MAX = VO_MAX_ENUM_VALUE
+} VOAACFRAMETYPE;
+
+/*!
+ * the structure for AAC encoder input parameter
+ */
+typedef struct {
+ int sampleRate; /*! audio file sample rate */
+ int bitRate; /*! encoder bit rate in bits/sec */
+ short nChannels; /*! number of channels on input (1,2) */
+ short adtsUsed; /*! whether write adts header */
+} AACENC_PARAM;
+
+/* AAC Param ID */
+#define VO_PID_AAC_Mdoule 0x42211000
+#define VO_PID_AAC_ENCPARAM VO_PID_AAC_Mdoule | 0x0040 /*!< get/set AAC encoder parameter, the parameter is a pointer to AACENC_PARAM */
+
+/* AAC decoder error ID */
+#define VO_ERR_AAC_Mdoule 0x82210000
+#define VO_ERR_AAC_UNSFILEFORMAT (VO_ERR_AAC_Mdoule | 0xF001)
+#define VO_ERR_AAC_UNSPROFILE (VO_ERR_AAC_Mdoule | 0xF002)
+
+/**
+ * Get audio encoder API interface
+ * \param pEncHandle [out] Return the AAC Encoder handle.
+ * \retval VO_ERR_OK Succeeded.
+ */
+VO_S32 VO_API voGetAACEncAPI (VO_AUDIO_CODECAPI * pEncHandle);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __voAAC_H__
+
+
+
diff --git a/media/libstagefright/codecs/common/include/voAMRWB.h b/media/libstagefright/codecs/common/include/voAMRWB.h
new file mode 100644
index 0000000..8a93eb8
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voAMRWB.h
@@ -0,0 +1,87 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voAMRWB.h
+
+ Content: AMR-WB codec APIs & data types
+
+*******************************************************************************/
+#ifndef __VOAMRWB_H__
+#define __VOAMRWB_H__
+
+#include "voAudio.h"
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+#pragma pack(push, 4)
+
+/*!* the bit rate the codec supports*/
+typedef enum {
+ VOAMRWB_MDNONE = -1, /*!< Invalid mode */
+ VOAMRWB_MD66 = 0, /*!< 6.60kbps */
+ VOAMRWB_MD885 = 1, /*!< 8.85kbps */
+ VOAMRWB_MD1265 = 2, /*!< 12.65kbps */
+ VOAMRWB_MD1425 = 3, /*!< 14.25kbps */
+ VOAMRWB_MD1585 = 4, /*!< 15.85bps */
+ VOAMRWB_MD1825 = 5, /*!< 18.25bps */
+ VOAMRWB_MD1985 = 6, /*!< 19.85kbps */
+ VOAMRWB_MD2305 = 7, /*!< 23.05kbps */
+ VOAMRWB_MD2385 = 8, /*!< 23.85kbps> */
+ VOAMRWB_N_MODES = 9, /*!< Invalid mode */
+ VOAMRWB_MODE_MAX = VO_MAX_ENUM_VALUE
+
+}VOAMRWBMODE;
+
+/*!* the frame format the codec supports*/
+typedef enum {
+ VOAMRWB_DEFAULT = 0, /*!< the frame type is the header (defined in RFC3267) + rawdata*/
+ /*One word (2-byte) for sync word (0x6b21)*/
+ /*One word (2-byte) for frame length N.*/
+ /*N words (2-byte) containing N bits (bit 0 = 0x007f, bit 1 = 0x0081).*/
+ VOAMRWB_ITU = 1,
+ /*One word (2-byte) for sync word (0x6b21).*/
+ /*One word (2-byte) to indicate the frame type.*/
+ /*One word (2-byte) to indicate the mode.*/
+ /*N words (2-byte) containing N bits (bit 0 = 0xff81, bit 1 = 0x007f).*/
+ VOAMRWB_RFC3267 = 2, /* see RFC 3267 */
+ VOAMRWB_TMAX = VO_MAX_ENUM_VALUE
+}VOAMRWBFRAMETYPE;
+
+
+#define VO_PID_AMRWB_Module 0x42261000
+#define VO_PID_AMRWB_FORMAT (VO_PID_AMRWB_Module | 0x0002)
+#define VO_PID_AMRWB_CHANNELS (VO_PID_AMRWB_Module | 0x0003)
+#define VO_PID_AMRWB_SAMPLERATE (VO_PID_AMRWB_Module | 0x0004)
+#define VO_PID_AMRWB_FRAMETYPE (VO_PID_AMRWB_Module | 0x0005)
+#define VO_PID_AMRWB_MODE (VO_PID_AMRWB_Module | 0x0006)
+#define VO_PID_AMRWB_DTX (VO_PID_AMRWB_Module | 0x0007)
+
+/**
+ * Get audio codec API interface
+ * \param pEncHandle [out] Return the AMRWB Encoder handle.
+ * \retval VO_ERR_OK Succeeded.
+ */
+VO_S32 VO_API voGetAMRWBEncAPI(VO_AUDIO_CODECAPI *pEncHandle);
+
+
+#pragma pack(pop)
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* __cplusplus */
+
+
+#endif //__VOAMRWB_H__
+
diff --git a/media/libstagefright/codecs/common/include/voAudio.h b/media/libstagefright/codecs/common/include/voAudio.h
new file mode 100644
index 0000000..64c9dfb
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voAudio.h
@@ -0,0 +1,173 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voAudio.h
+
+ Content: Audio types and functions
+
+*******************************************************************************/
+
+#ifndef __voAudio_H__
+#define __voAudio_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "voIndex.h"
+#include "voMem.h"
+
+#define VO_PID_AUDIO_BASE 0x42000000 /*!< The base param ID for AUDIO codec */
+#define VO_PID_AUDIO_FORMAT (VO_PID_AUDIO_BASE | 0X0001) /*!< The format data of audio in track */
+#define VO_PID_AUDIO_SAMPLEREATE (VO_PID_AUDIO_BASE | 0X0002) /*!< The sample rate of audio */
+#define VO_PID_AUDIO_CHANNELS (VO_PID_AUDIO_BASE | 0X0003) /*!< The channel of audio */
+#define VO_PID_AUDIO_BITRATE (VO_PID_AUDIO_BASE | 0X0004) /*!< The bit rate of audio */
+#define VO_PID_AUDIO_CHANNELMODE (VO_PID_AUDIO_BASE | 0X0005) /*!< The channel mode of audio */
+
+#define VO_ERR_AUDIO_BASE 0x82000000
+#define VO_ERR_AUDIO_UNSCHANNEL VO_ERR_AUDIO_BASE | 0x0001
+#define VO_ERR_AUDIO_UNSSAMPLERATE VO_ERR_AUDIO_BASE | 0x0002
+#define VO_ERR_AUDIO_UNSFEATURE VO_ERR_AUDIO_BASE | 0x0003
+
+
+/**
+ *Enumeration used to define the possible audio coding formats.
+ */
+typedef enum VO_AUDIO_CODINGTYPE {
+ VO_AUDIO_CodingUnused = 0, /**< Placeholder value when coding is N/A */
+ VO_AUDIO_CodingPCM, /**< Any variant of PCM coding */
+ VO_AUDIO_CodingADPCM, /**< Any variant of ADPCM encoded data */
+ VO_AUDIO_CodingAMRNB, /**< Any variant of AMR encoded data */
+ VO_AUDIO_CodingAMRWB, /**< Any variant of AMR encoded data */
+ VO_AUDIO_CodingAMRWBP, /**< Any variant of AMR encoded data */
+ VO_AUDIO_CodingQCELP13, /**< Any variant of QCELP 13kbps encoded data */
+ VO_AUDIO_CodingEVRC, /**< Any variant of EVRC encoded data */
+ VO_AUDIO_CodingAAC, /**< Any variant of AAC encoded data, 0xA106 - ISO/MPEG-4 AAC, 0xFF - AAC */
+ VO_AUDIO_CodingAC3, /**< Any variant of AC3 encoded data */
+ VO_AUDIO_CodingFLAC, /**< Any variant of FLAC encoded data */
+ VO_AUDIO_CodingMP1, /**< Any variant of MP1 encoded data */
+ VO_AUDIO_CodingMP3, /**< Any variant of MP3 encoded data */
+ VO_AUDIO_CodingOGG, /**< Any variant of OGG encoded data */
+ VO_AUDIO_CodingWMA, /**< Any variant of WMA encoded data */
+ VO_AUDIO_CodingRA, /**< Any variant of RA encoded data */
+ VO_AUDIO_CodingMIDI, /**< Any variant of MIDI encoded data */
+ VO_AUDIO_CodingDRA, /**< Any variant of dra encoded data */
+ VO_AUDIO_CodingG729, /**< Any variant of dra encoded data */
+ VO_AUDIO_Coding_MAX = VO_MAX_ENUM_VALUE
+} VO_AUDIO_CODINGTYPE;
+
+/*!
+* the channel type value
+*/
+typedef enum {
+ VO_CHANNEL_CENTER = 1, /*!<center channel*/
+ VO_CHANNEL_FRONT_LEFT = 1<<1, /*!<front left channel*/
+ VO_CHANNEL_FRONT_RIGHT = 1<<2, /*!<front right channel*/
+ VO_CHANNEL_SIDE_LEFT = 1<<3, /*!<side left channel*/
+ VO_CHANNEL_SIDE_RIGHT = 1<<4, /*!<side right channel*/
+ VO_CHANNEL_BACK_LEFT = 1<<5, /*!<back left channel*/
+ VO_CHANNEL_BACK_RIGHT = 1<<6, /*!<back right channel*/
+ VO_CHANNEL_BACK_CENTER = 1<<7, /*!<back center channel*/
+ VO_CHANNEL_LFE_BASS = 1<<8, /*!<low-frequency effects bass channel*/
+ VO_CHANNEL_ALL = 0xffff,/*!<[default] include all channels */
+ VO_CHANNEL_MAX = VO_MAX_ENUM_VALUE
+} VO_AUDIO_CHANNELTYPE;
+
+/**
+ * General audio format info
+ */
+typedef struct
+{
+ VO_S32 SampleRate; /*!< Sample rate */
+ VO_S32 Channels; /*!< Channel count */
+ VO_S32 SampleBits; /*!< Bits per sample */
+} VO_AUDIO_FORMAT;
+
+/**
+ * General audio output info
+ */
+typedef struct
+{
+ VO_AUDIO_FORMAT Format; /*!< Sample rate */
+ VO_U32 InputUsed; /*!< Channel count */
+ VO_U32 Resever; /*!< Resevered */
+} VO_AUDIO_OUTPUTINFO;
+
+/**
+ * General audio codec function set
+ */
+typedef struct VO_AUDIO_CODECAPI
+{
+ /**
+ * Init the audio codec module and return codec handle
+ * \param phCodec [OUT] Return the video codec handle
+ * \param vType [IN] The codec type if the module support multi codec.
+ * \param pUserData [IN] The init param. It is either a memory operator or an allocated memory
+ * \retval VO_ERR_NONE Succeeded.
+ */
+ VO_U32 (VO_API * Init) (VO_HANDLE * phCodec, VO_AUDIO_CODINGTYPE vType, VO_CODEC_INIT_USERDATA * pUserData );
+
+ /**
+ * Set input audio data.
+ * \param hCodec [IN]] The codec handle which was created by Init function.
+ * \param pInput [IN] The input buffer param.
+ * \retval VO_ERR_NONE Succeeded.
+ */
+ VO_U32 (VO_API * SetInputData) (VO_HANDLE hCodec, VO_CODECBUFFER * pInput);
+
+ /**
+ * Get the outut audio data
+ * \param hCodec [IN]] The codec handle which was created by Init function.
+ * \param pOutBuffer [OUT] The output audio data
+ * \param pOutInfo [OUT] The codec fills audio format and the input data size used in current call.
+ * pOutInfo->InputUsed is total used input data size in byte.
+ * \retval VO_ERR_NONE Succeeded.
+ * VO_ERR_INPUT_BUFFER_SMALL. The input was finished or the input data was not enought. Continue to input
+ * data before next call.
+ */
+ VO_U32 (VO_API * GetOutputData) (VO_HANDLE hCodec, VO_CODECBUFFER * pOutBuffer, VO_AUDIO_OUTPUTINFO * pOutInfo);
+
+ /**
+ * Set the parameter for the specified param ID.
+ * \param hCodec [IN]] The codec handle which was created by Init function.
+ * \param uParamID [IN] The param ID.
+ * \param pData [IN] The param value.
+ * \retval VO_ERR_NONE Succeeded.
+ */
+ VO_U32 (VO_API * SetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData);
+
+ /**
+ * Get the parameter for the specified param ID.
+ * \param hCodec [IN]] The codec handle which was created by Init function.
+ * \param uParamID [IN] The param ID.
+ * \param pData [IN] The param value.
+ * \retval VO_ERR_NONE Succeeded.
+ */
+ VO_U32 (VO_API * GetParam) (VO_HANDLE hCodec, VO_S32 uParamID, VO_PTR pData);
+
+ /**
+ * Uninit the Codec.
+ * \param hCodec [IN]] The codec handle which was created by Init function.
+ * \retval VO_ERR_NONE Succeeded.
+ */
+ VO_U32 (VO_API * Uninit) (VO_HANDLE hCodec);
+} VO_AUDIO_CODECAPI;
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __voAudio_H__
diff --git a/media/libstagefright/codecs/common/include/voIndex.h b/media/libstagefright/codecs/common/include/voIndex.h
new file mode 100644
index 0000000..541a0db
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voIndex.h
@@ -0,0 +1,193 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voIndex.h
+
+ Content: module and ID definition
+
+*******************************************************************************/
+
+#ifndef __voIndex_H__
+#define __voIndex_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "voType.h"
+
+/* Define the module ID */
+#define _MAKE_SOURCE_ID(id, name) \
+VO_INDEX_SRC_##name = _VO_INDEX_SOURCE | id,
+
+#define _MAKE_CODEC_ID(id, name) \
+VO_INDEX_DEC_##name = _VO_INDEX_DEC | id, \
+VO_INDEX_ENC_##name = _VO_INDEX_ENC | id,
+
+#define _MAKE_EFFECT_ID(id, name) \
+VO_INDEX_EFT_##name = _VO_INDEX_EFFECT | id,
+
+#define _MAKE_SINK_ID(id, name) \
+VO_INDEX_SNK_##name = _VO_INDEX_SINK | id,
+
+#define _MAKE_FILTER_ID(id, name) \
+VO_INDEX_FLT_##name = _VO_INDEX_FILTER | id,
+
+#define _MAKE_OMX_ID(id, name) \
+VO_INDEX_OMX_##name = _VO_INDEX_OMX | id,
+
+#define _MAKE_MFW_ID(id, name) \
+VO_INDEX_MFW_##name = _VO_INDEX_MFW | id,
+
+enum
+{
+ _VO_INDEX_SOURCE = 0x01000000,
+ _VO_INDEX_DEC = 0x02000000,
+ _VO_INDEX_ENC = 0x03000000,
+ _VO_INDEX_EFFECT = 0x04000000,
+ _VO_INDEX_SINK = 0x05000000,
+ _VO_INDEX_FILTER = 0x06000000,
+ _VO_INDEX_OMX = 0x07000000,
+ _VO_INDEX_MFW = 0x08000000,
+
+ // define file parser modules
+ _MAKE_SOURCE_ID (0x010000, MP4)
+ _MAKE_SOURCE_ID (0x020000, AVI)
+ _MAKE_SOURCE_ID (0x030000, ASF)
+ _MAKE_SOURCE_ID (0x040000, REAL)
+ _MAKE_SOURCE_ID (0x050000, AUDIO)
+ _MAKE_SOURCE_ID (0x060000, FLASH)
+ _MAKE_SOURCE_ID (0x070000, OGG)
+ _MAKE_SOURCE_ID (0x080000, MKV)
+
+ // define network source modules
+ _MAKE_SOURCE_ID (0x110000, RTSP)
+ _MAKE_SOURCE_ID (0x120000, HTTP)
+
+ // define CMMB source modules
+ _MAKE_SOURCE_ID (0x200000, CMMB)
+ _MAKE_SOURCE_ID (0x210000, CMMB_INNO)
+ _MAKE_SOURCE_ID (0x220000, CMMB_TELE)
+ _MAKE_SOURCE_ID (0x230000, CMMB_SIANO)
+
+ // define DVBT source modules
+ _MAKE_SOURCE_ID (0x300000, DVBT)
+ _MAKE_SOURCE_ID (0x310000, DVBT_DIBCOM)
+
+ // define other source modules
+ _MAKE_SOURCE_ID (0x400000, ID3)
+
+ // define video codec modules
+ _MAKE_CODEC_ID (0x010000, H264)
+ _MAKE_CODEC_ID (0x020000, MPEG4)
+ _MAKE_CODEC_ID (0x030000, H263)
+ _MAKE_CODEC_ID (0x040000, S263)
+ _MAKE_CODEC_ID (0x050000, RV)
+ _MAKE_CODEC_ID (0x060000, WMV)
+ _MAKE_CODEC_ID (0x070000, DIVX3)
+ _MAKE_CODEC_ID (0x080000, MJPEG)
+ _MAKE_CODEC_ID (0x090000, MPEG2)
+ _MAKE_CODEC_ID (0x0A0000, VP6)
+
+ // define audio codec modules
+ _MAKE_CODEC_ID (0x210000, AAC)
+ _MAKE_CODEC_ID (0x220000, MP3)
+ _MAKE_CODEC_ID (0x230000, WMA)
+ _MAKE_CODEC_ID (0x240000, RA)
+ _MAKE_CODEC_ID (0x250000, AMRNB)
+ _MAKE_CODEC_ID (0x260000, AMRWB)
+ _MAKE_CODEC_ID (0x270000, AMRWBP)
+ _MAKE_CODEC_ID (0x280000, QCELP)
+ _MAKE_CODEC_ID (0x290000, EVRC)
+ _MAKE_CODEC_ID (0x2A0000, ADPCM)
+ _MAKE_CODEC_ID (0x2B0000, MIDI)
+ _MAKE_CODEC_ID (0x2C0000, AC3)
+ _MAKE_CODEC_ID (0x2D0000, FLAC)
+ _MAKE_CODEC_ID (0x2E0000, DRA)
+ _MAKE_CODEC_ID (0x2F0000, OGG)
+ _MAKE_CODEC_ID (0x300000, G729)
+
+ // define image codec modules
+ _MAKE_CODEC_ID (0x410000, JPEG)
+ _MAKE_CODEC_ID (0x420000, GIF)
+ _MAKE_CODEC_ID (0x430000, PNG)
+ _MAKE_CODEC_ID (0x440000, TIF)
+
+ // define effect modules
+ _MAKE_EFFECT_ID (0x010000, EQ)
+
+ // define sink modules
+ _MAKE_SINK_ID (0x010000, VIDEO)
+ _MAKE_SINK_ID (0x020000, AUDIO)
+ _MAKE_SINK_ID (0x030000, CCRRR)
+ _MAKE_SINK_ID (0x040000, CCRRV)
+
+ _MAKE_SINK_ID (0x110000, MP4)
+ _MAKE_SINK_ID (0x120000, AVI)
+ _MAKE_SINK_ID (0x130000, AFW)
+
+ // define media frame module ID
+ _MAKE_MFW_ID (0x010000, VOMMPLAY)
+ _MAKE_MFW_ID (0x020000, VOMMREC)
+ _MAKE_MFW_ID (0x030000, VOME)
+};
+
+
+/* define the error ID */
+#define VO_ERR_NONE 0x00000000
+#define VO_ERR_FINISH 0x00000001
+#define VO_ERR_BASE 0X80000000
+#define VO_ERR_FAILED 0x80000001
+#define VO_ERR_OUTOF_MEMORY 0x80000002
+#define VO_ERR_NOT_IMPLEMENT 0x80000003
+#define VO_ERR_INVALID_ARG 0x80000004
+#define VO_ERR_INPUT_BUFFER_SMALL 0x80000005
+#define VO_ERR_OUTPUT_BUFFER_SMALL 0x80000006
+#define VO_ERR_WRONG_STATUS 0x80000007
+#define VO_ERR_WRONG_PARAM_ID 0x80000008
+#define VO_ERR_LICENSE_ERROR 0x80000009
+
+/* xxx is the module ID
+#define VO_ERR_FAILED 0x8xxx0001
+#define VO_ERR_OUTOF_MEMORY 0x8xxx0002
+#define VO_ERR_NOT_IMPLEMENT 0x8xxx0003
+#define VO_ERR_INVALID_ARG 0x8xxx0004
+#define VO_ERR_INPUT_BUFFER_SMALL 0x8xxx0005
+#define VO_ERR_OUTPUT_BUFFER_SMALL 0x8xxx0006
+#define VO_ERR_WRONG_STATUS 0x8xxx0007
+#define VO_ERR_WRONG_PARAM_ID 0x8xxx0008
+#define VO_ERR_LICENSE_ERROR 0x8xxx0009
+// Module own error ID
+#define VO_ERR_Module 0x8xxx0X00
+*/
+
+#define VO_PID_COMMON_BASE 0x40000000 /*!< The base of common param ID */
+#define VO_PID_COMMON_QUERYMEM (VO_PID_COMMON_BASE | 0X0001) /*!< Query the memory needed; Reserved. */
+#define VO_PID_COMMON_INPUTTYPE (VO_PID_COMMON_BASE | 0X0002) /*!< Set or get the input buffer type. VO_INPUT_TYPE */
+#define VO_PID_COMMON_HASRESOURCE (VO_PID_COMMON_BASE | 0X0003) /*!< Query it has resource to be used. VO_U32 *, 1 have, 0 No */
+#define VO_PID_COMMON_HEADDATA (VO_PID_COMMON_BASE | 0X0004) /*!< Decoder track header data. VO_CODECBUFFER * */
+#define VO_PID_COMMON_FLUSH (VO_PID_COMMON_BASE | 0X0005) /*!< Flush the codec buffer. VO_U32 *, 1 Flush, 0 No * */
+
+/*
+// Module Param ID
+#define VO_ID_Mdoule 0x0xxx1000
+*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __voIndex_H__
diff --git a/media/libstagefright/codecs/common/include/voMem.h b/media/libstagefright/codecs/common/include/voMem.h
new file mode 100644
index 0000000..8dfb634
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voMem.h
@@ -0,0 +1,65 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voMem.h
+
+ Content: memory functions & data structures
+
+*******************************************************************************/
+
+#ifndef __voMem_H__
+#define __voMem_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include "voIndex.h"
+
+typedef struct
+{
+ VO_S32 Size; /*!< Buffer stride */
+ VO_S32 Flag;
+ VO_PTR VBuffer; /*!< user data pointer */
+ VO_PTR PBuffer; /*!< user data pointer */
+}
+VO_MEM_INFO;
+
+typedef struct VO_MEM_OPERATOR
+{
+ VO_U32 (VO_API * Alloc) (VO_S32 uID, VO_MEM_INFO * pMemInfo);
+ VO_U32 (VO_API * Free) (VO_S32 uID, VO_PTR pBuff);
+ VO_U32 (VO_API * Set) (VO_S32 uID, VO_PTR pBuff, VO_U8 uValue, VO_U32 uSize);
+ VO_U32 (VO_API * Copy) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);
+ VO_U32 (VO_API * Check) (VO_S32 uID, VO_PTR pBuffer, VO_U32 uSize);
+ VO_S32 (VO_API * Compare) (VO_S32 uID, VO_PTR pBuffer1, VO_PTR pBuffer2, VO_U32 uSize);
+ VO_U32 (VO_API * Move) (VO_S32 uID, VO_PTR pDest, VO_PTR pSource, VO_U32 uSize);
+} VO_MEM_OPERATOR;
+
+#define voMemAlloc(pBuff, pMemOP, ID, nSize) \
+{ \
+ VO_MEM_INFO voMemInfo; \
+ voMemInfo.Size=nSize; \
+ pMemOP->Alloc(ID, &voMemInfo); \
+ pBuff=(VO_PBYTE)voMemInfo.VBuffer; \
+}
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __voMem_H__
diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/libstagefright/codecs/common/include/voType.h
new file mode 100644
index 0000000..2669134
--- /dev/null
+++ b/media/libstagefright/codecs/common/include/voType.h
@@ -0,0 +1,221 @@
+/*
+ ** Copyright 2003-2010, VisualOn, Inc.
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT 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: voType.h
+
+ Content: data type definition
+
+*******************************************************************************/
+#ifndef __voType_H__
+#define __voType_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef _WIN32
+# define VO_API __cdecl
+# define VO_CBI __stdcall
+#else
+# define VO_API
+# define VO_CBI
+#endif //_WIN32
+
+/** VO_IN is used to identify inputs to an VO 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 VO_IN
+#define VO_IN
+#endif
+
+/** VO_OUT is used to identify outputs from an VO 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 VO_OUT
+#define VO_OUT
+#endif
+
+/** VO_INOUT is used to identify parameters that may be either inputs or
+ outputs from an VO 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 VO_INOUT
+#define VO_INOUT
+#endif
+
+#define VO_MAX_ENUM_VALUE 0X7FFFFFFF
+
+/** VO_VOID */
+typedef void VO_VOID;
+
+/** VO_U8 is an 8 bit unsigned quantity that is byte aligned */
+typedef unsigned char VO_U8;
+
+/** VO_BYTE is an 8 bit unsigned quantity that is byte aligned */
+typedef unsigned char VO_BYTE;
+
+/** VO_S8 is an 8 bit signed quantity that is byte aligned */
+typedef signed char VO_S8;
+
+/** VO_CHAR is an 8 bit signed quantity that is byte aligned */
+typedef char VO_CHAR;
+
+/** VO_U16 is a 16 bit unsigned quantity that is 16 bit word aligned */
+typedef unsigned short VO_U16;
+
+/** VO_WCHAR is a 16 bit unsigned quantity that is 16 bit word aligned */
+#if defined _WIN32
+typedef unsigned short VO_WCHAR;
+typedef unsigned short* VO_PWCHAR;
+#elif defined LINUX
+typedef unsigned char VO_WCHAR;
+typedef unsigned char* VO_PWCHAR;
+#endif
+
+/** VO_S16 is a 16 bit signed quantity that is 16 bit word aligned */
+typedef signed short VO_S16;
+
+/** VO_U32 is a 32 bit unsigned quantity that is 32 bit word aligned */
+typedef unsigned long VO_U32;
+
+/** VO_S32 is a 32 bit signed quantity that is 32 bit word aligned */
+typedef signed long VO_S32;
+
+/* Users with compilers that cannot accept the "long long" designation should
+ define the VO_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 VO_SKIP64BIT
+#ifdef _WIN32
+/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */
+typedef unsigned __int64 VO_U64;
+/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */
+typedef signed __int64 VO_S64;
+#else // WIN32
+/** VO_U64 is a 64 bit unsigned quantity that is 64 bit word aligned */
+typedef unsigned long long VO_U64;
+/** VO_S64 is a 64 bit signed quantity that is 64 bit word aligned */
+typedef signed long long VO_S64;
+#endif // WIN32
+#endif // VO_SKIP64BIT
+
+/** The VO_BOOL type is intended to be used to represent a true or a false
+ value when passing parameters to and from the VO core and components. The
+ VO_BOOL is a 32 bit quantity and is aligned on a 32 bit word boundary.
+ */
+typedef enum VO_BOOL {
+ VO_FALSE = 0,
+ VO_TRUE = !VO_FALSE,
+ VO_BOOL_MAX = VO_MAX_ENUM_VALUE
+} VO_BOOL;
+
+/** The VO_PTR type is intended to be used to pass pointers between the VO
+ applications and the VO Core and components. This is a 32 bit pointer and
+ is aligned on a 32 bit boundary.
+ */
+typedef void* VO_PTR;
+
+/** The VO_HANDLE type is intended to be used to pass pointers between the VO
+ applications and the VO Core and components. This is a 32 bit pointer and
+ is aligned on a 32 bit boundary.
+ */
+typedef void* VO_HANDLE;
+
+/** The VO_STRING type is intended to be used to pass "C" type strings between
+ the application and the core and component. The VO_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* VO_PCHAR;
+
+/** The VO_PBYTE type is intended to be used to pass arrays of bytes such as
+ buffers between the application and the component and core. The VO_PBYTE
+ 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* VO_PBYTE;
+
+/** The VO_PTCHAR type is intended to be used to pass arrays of wchar such as
+ unicode char between the application and the component and core. The VO_PTCHAR
+ type is a 32 bit pointer to a zero terminated string. The pointer is word
+ aligned and the string is byte aligned.
+ */
+/*
+#if !defined LINUX
+typedef unsigned short* VO_PTCHAR;
+typedef unsigned short* VO_TCHAR;
+#else
+typedef char* VO_PTCHAR;
+typedef char VO_TCHAR;
+#endif
+*/
+
+#ifndef NULL
+#ifdef __cplusplus
+#define NULL 0
+#else
+#define NULL ((void *)0)
+#endif
+#endif
+
+/**
+ * Input stream format, Frame or Stream..
+ */
+typedef enum {
+ VO_INPUT_FRAME = 1, /*!< Input contains completely frame(s) data. */
+ VO_INPUT_STREAM, /*!< Input is stream data. */
+ VO_INPUT_STREAM_MAX = VO_MAX_ENUM_VALUE
+} VO_INPUT_TYPE;
+
+
+/**
+ * General data buffer, used as input or output.
+ */
+typedef struct {
+ VO_PBYTE Buffer; /*!< Buffer pointer */
+ VO_U32 Length; /*!< Buffer size in byte */
+ VO_S64 Time; /*!< The time of the buffer */
+} VO_CODECBUFFER;
+
+
+/**
+ * The init memdata flag.
+ */
+typedef enum{
+ VO_IMF_USERMEMOPERATOR =0, /*!< memData is the pointer of memoperator function*/
+ VO_IMF_PREALLOCATEDBUFFER =1, /*!< memData is preallocated memory*/
+ VO_IMF_MAX = VO_MAX_ENUM_VALUE
+}VO_INIT_MEM_FlAG;
+
+
+/**
+ * The init memory structure..
+ */
+typedef struct{
+ VO_INIT_MEM_FlAG memflag; /*!<memory flag */
+ VO_PTR memData; /*!<a pointer to VO_MEM_OPERATOR or a preallocated buffer */
+ VO_U32 reserved1; /*!<reserved */
+ VO_U32 reserved2; /*!<reserved */
+}VO_CODEC_INIT_USERDATA;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif // __voType_H__
diff --git a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
index 8350f7a..0f08f6e 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/M4vH263Decoder.cpp
@@ -37,7 +37,8 @@ M4vH263Decoder::M4vH263Decoder(const sp<MediaSource> &source)
mStarted(false),
mHandle(new tagvideoDecControls),
mInputBuffer(NULL),
- mNumSamplesOutput(0) {
+ mNumSamplesOutput(0),
+ mTargetTimeUs(-1) {
LOGV("M4vH263Decoder");
memset(mHandle, 0, sizeof(tagvideoDecControls));
@@ -146,6 +147,7 @@ status_t M4vH263Decoder::start(MetaData *) {
mSource->start();
mNumSamplesOutput = 0;
+ mTargetTimeUs = -1;
mStarted = true;
return OK;
@@ -175,8 +177,11 @@ status_t M4vH263Decoder::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
+ bool seeking = false;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ seeking = true;
CHECK_EQ(PVResetVideoDecoder(mHandle), PV_TRUE);
}
@@ -186,6 +191,16 @@ status_t M4vH263Decoder::read(
return err;
}
+ if (seeking) {
+ int64_t targetTimeUs;
+ if (inputBuffer->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
+ && targetTimeUs >= 0) {
+ mTargetTimeUs = targetTimeUs;
+ } else {
+ mTargetTimeUs = -1;
+ }
+ }
+
uint8_t *bitstream =
(uint8_t *) inputBuffer->data() + inputBuffer->range_offset();
@@ -221,17 +236,40 @@ status_t M4vH263Decoder::read(
return INFO_FORMAT_CHANGED;
}
- *out = mFrames[mNumSamplesOutput & 0x01];
- (*out)->add_ref();
-
int64_t timeUs;
CHECK(inputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
- (*out)->meta_data()->setInt64(kKeyTime, timeUs);
- ++mNumSamplesOutput;
inputBuffer->release();
inputBuffer = NULL;
+ bool skipFrame = false;
+
+ if (mTargetTimeUs >= 0) {
+ CHECK(timeUs <= mTargetTimeUs);
+
+ if (timeUs < mTargetTimeUs) {
+ // We're still waiting for the frame with the matching
+ // timestamp and we won't return the current one.
+ skipFrame = true;
+
+ LOGV("skipping frame at %lld us", timeUs);
+ } else {
+ LOGV("found target frame at %lld us", timeUs);
+
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (skipFrame) {
+ *out = new MediaBuffer(0);
+ } else {
+ *out = mFrames[mNumSamplesOutput & 0x01];
+ (*out)->add_ref();
+ (*out)->meta_data()->setInt64(kKeyTime, timeUs);
+ }
+
+ ++mNumSamplesOutput;
+
return OK;
}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/Android.mk b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
new file mode 100644
index 0000000..f2c9320
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/Android.mk
@@ -0,0 +1,37 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ M4vH263Encoder.cpp \
+ src/bitstream_io.cpp \
+ src/combined_encode.cpp \
+ src/datapart_encode.cpp \
+ src/dct.cpp \
+ src/findhalfpel.cpp \
+ src/fastcodemb.cpp \
+ src/fastidct.cpp \
+ src/fastquant.cpp \
+ src/me_utils.cpp \
+ src/mp4enc_api.cpp \
+ src/rate_control.cpp \
+ src/motion_est.cpp \
+ src/motion_comp.cpp \
+ src/sad.cpp \
+ src/sad_halfpel.cpp \
+ src/vlc_encode.cpp \
+ src/vop.cpp
+
+
+LOCAL_MODULE := libstagefright_m4vh263enc
+
+LOCAL_CFLAGS := \
+ -DBX_RC \
+ -DOSCL_IMPORT_REF= -DOSCL_UNUSED_ARG= -DOSCL_EXPORT_REF=
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/src \
+ $(LOCAL_PATH)/include \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/frameworks/base/media/libstagefright/include
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
new file mode 100644
index 0000000..5002442
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/M4vH263Encoder.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "M4vH263Encoder"
+#include <utils/Log.h>
+
+#include "M4vH263Encoder.h"
+
+#include "mp4enc_api.h"
+#include "OMX_Video.h"
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+namespace android {
+
+inline static void ConvertYUV420SemiPlanarToYUV420Planar(
+ uint8_t *inyuv, uint8_t* outyuv,
+ int32_t width, int32_t height) {
+
+ int32_t outYsize = width * height;
+ uint32_t *outy = (uint32_t *) outyuv;
+ uint16_t *outcb = (uint16_t *) (outyuv + outYsize);
+ uint16_t *outcr = (uint16_t *) (outyuv + outYsize + (outYsize >> 2));
+
+ /* Y copying */
+ memcpy(outy, inyuv, outYsize);
+
+ /* U & V copying */
+ uint32_t *inyuv_4 = (uint32_t *) (inyuv + outYsize);
+ for (int32_t i = height >> 1; i > 0; --i) {
+ for (int32_t j = width >> 2; j > 0; --j) {
+ uint32_t temp = *inyuv_4++;
+ uint32_t tempU = temp & 0xFF;
+ tempU = tempU | ((temp >> 8) & 0xFF00);
+
+ uint32_t tempV = (temp >> 8) & 0xFF;
+ tempV = tempV | ((temp >> 16) & 0xFF00);
+
+ // Flip U and V
+ *outcb++ = tempV;
+ *outcr++ = tempU;
+ }
+ }
+}
+
+M4vH263Encoder::M4vH263Encoder(
+ const sp<MediaSource>& source,
+ const sp<MetaData>& meta)
+ : mSource(source),
+ mMeta(meta),
+ mNumInputFrames(-1),
+ mNextModTimeUs(0),
+ mStarted(false),
+ mInputBuffer(NULL),
+ mInputFrameData(NULL),
+ mGroup(NULL) {
+
+ LOGV("Construct software M4vH263Encoder");
+
+ mHandle = new tagvideoEncControls;
+ memset(mHandle, 0, sizeof(tagvideoEncControls));
+
+ mInitCheck = initCheck(meta);
+}
+
+M4vH263Encoder::~M4vH263Encoder() {
+ LOGV("Destruct software M4vH263Encoder");
+ if (mStarted) {
+ stop();
+ }
+
+ delete mEncParams;
+ delete mHandle;
+}
+
+status_t M4vH263Encoder::initCheck(const sp<MetaData>& meta) {
+ LOGV("initCheck");
+ CHECK(meta->findInt32(kKeyWidth, &mVideoWidth));
+ CHECK(meta->findInt32(kKeyHeight, &mVideoHeight));
+ CHECK(meta->findInt32(kKeySampleRate, &mVideoFrameRate));
+ CHECK(meta->findInt32(kKeyBitRate, &mVideoBitRate));
+
+ // XXX: Add more color format support
+ CHECK(meta->findInt32(kKeyColorFormat, &mVideoColorFormat));
+ if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ if (mVideoColorFormat != OMX_COLOR_FormatYUV420SemiPlanar) {
+ LOGE("Color format %d is not supported", mVideoColorFormat);
+ return BAD_VALUE;
+ }
+ // Allocate spare buffer only when color conversion is needed.
+ // Assume the color format is OMX_COLOR_FormatYUV420SemiPlanar.
+ mInputFrameData =
+ (uint8_t *) malloc((mVideoWidth * mVideoHeight * 3 ) >> 1);
+ CHECK(mInputFrameData);
+ }
+
+ // XXX: Remove this restriction
+ if (mVideoWidth % 16 != 0 || mVideoHeight % 16 != 0) {
+ LOGE("Video frame size %dx%d must be a multiple of 16",
+ mVideoWidth, mVideoHeight);
+ return BAD_VALUE;
+ }
+
+ mEncParams = new tagvideoEncOptions;
+ memset(mEncParams, 0, sizeof(tagvideoEncOptions));
+ if (!PVGetDefaultEncOption(mEncParams, 0)) {
+ LOGE("Failed to get default encoding parameters");
+ return BAD_VALUE;
+ }
+
+ // Need to know which role the encoder is in.
+ // XXX: Set the mode proper for other types of applications
+ // like streaming or video conference
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+ CHECK(!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
+ !strcmp(mime, MEDIA_MIMETYPE_VIDEO_H263));
+ if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)) {
+ mEncParams->encMode = COMBINE_MODE_WITH_ERR_RES;
+ } else {
+ mEncParams->encMode = H263_MODE;
+ }
+ mEncParams->encWidth[0] = mVideoWidth;
+ mEncParams->encHeight[0] = mVideoHeight;
+ mEncParams->encFrameRate[0] = mVideoFrameRate;
+ mEncParams->rcType = VBR_1;
+ mEncParams->vbvDelay = (float)5.0;
+
+ // Set profile and level
+ // If profile and level setting is not correct, failure
+ // is reported when the encoder is initialized.
+ mEncParams->profile_level = CORE_PROFILE_LEVEL2;
+ int32_t profileLevel;
+ if (meta->findInt32(kKeyVideoLevel, &profileLevel)) {
+ mEncParams->profile_level = (ProfileLevelType)profileLevel;
+ }
+
+ mEncParams->packetSize = 32;
+ mEncParams->rvlcEnable = PV_OFF;
+ mEncParams->numLayers = 1;
+ mEncParams->timeIncRes = 1000;
+ mEncParams->tickPerSrc = mEncParams->timeIncRes / mVideoFrameRate;
+
+ mEncParams->bitRate[0] = mVideoBitRate;
+ mEncParams->iQuant[0] = 15;
+ mEncParams->pQuant[0] = 12;
+ mEncParams->quantType[0] = 0;
+ mEncParams->noFrameSkipped = PV_OFF;
+
+ // Set IDR frame refresh interval
+ int32_t iFramesIntervalSec;
+ CHECK(meta->findInt32(kKeyIFramesInterval, &iFramesIntervalSec));
+ if (iFramesIntervalSec < 0) {
+ mEncParams->intraPeriod = -1;
+ } else if (iFramesIntervalSec == 0) {
+ mEncParams->intraPeriod = 1; // All I frames
+ } else {
+ mEncParams->intraPeriod =
+ (iFramesIntervalSec * mVideoFrameRate);
+ }
+
+ mEncParams->numIntraMB = 0;
+ mEncParams->sceneDetect = PV_ON;
+ mEncParams->searchRange = 16;
+ mEncParams->mv8x8Enable = PV_OFF;
+ mEncParams->gobHeaderInterval = 0;
+ mEncParams->useACPred = PV_ON;
+ mEncParams->intraDCVlcTh = 0;
+
+ mFormat = new MetaData;
+ mFormat->setInt32(kKeyWidth, mVideoWidth);
+ mFormat->setInt32(kKeyHeight, mVideoHeight);
+ mFormat->setInt32(kKeyBitRate, mVideoBitRate);
+ mFormat->setInt32(kKeySampleRate, mVideoFrameRate);
+ mFormat->setInt32(kKeyColorFormat, mVideoColorFormat);
+
+ mFormat->setCString(kKeyMIMEType, mime);
+ mFormat->setCString(kKeyDecoderComponent, "M4vH263Encoder");
+ return OK;
+}
+
+status_t M4vH263Encoder::start(MetaData *params) {
+ LOGV("start");
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mStarted) {
+ LOGW("Call start() when encoder already started");
+ return OK;
+ }
+
+ if (!PVInitVideoEncoder(mHandle, mEncParams)) {
+ LOGE("Failed to initialize the encoder");
+ return UNKNOWN_ERROR;
+ }
+
+ mGroup = new MediaBufferGroup();
+ int32_t maxSize;
+ if (!PVGetMaxVideoFrameSize(mHandle, &maxSize)) {
+ maxSize = 256 * 1024; // Magic #
+ }
+ LOGV("Max output buffer size: %d", maxSize);
+ mGroup->add_buffer(new MediaBuffer(maxSize));
+
+ mSource->start(params);
+ mNumInputFrames = -1; // 1st frame contains codec specific data
+ mStarted = true;
+
+ return OK;
+}
+
+status_t M4vH263Encoder::stop() {
+ LOGV("stop");
+ if (!mStarted) {
+ LOGW("Call stop() when encoder has not started");
+ return OK;
+ }
+
+ if (mInputBuffer) {
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ }
+
+ if (mGroup) {
+ delete mGroup;
+ mGroup = NULL;
+ }
+
+ if (mInputFrameData) {
+ delete mInputFrameData;
+ mInputFrameData = NULL;
+ }
+
+ CHECK(PVCleanUpVideoEncoder(mHandle));
+
+ mSource->stop();
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> M4vH263Encoder::getFormat() {
+ LOGV("getFormat");
+ return mFormat;
+}
+
+status_t M4vH263Encoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+
+ *out = NULL;
+
+ MediaBuffer *outputBuffer;
+ CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
+ uint8_t *outPtr = (uint8_t *) outputBuffer->data();
+ int32_t dataLength = outputBuffer->size();
+
+ // Output codec specific data
+ if (mNumInputFrames < 0) {
+ if (!PVGetVolHeader(mHandle, outPtr, &dataLength, 0)) {
+ LOGE("Failed to get VOL header");
+ return UNKNOWN_ERROR;
+ }
+ LOGV("Output VOL header: %d bytes", dataLength);
+ outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig, 1);
+ outputBuffer->set_range(0, dataLength);
+ *out = outputBuffer;
+ ++mNumInputFrames;
+ return OK;
+ }
+
+ // Ready for accepting an input video frame
+ if (OK != mSource->read(&mInputBuffer, options)) {
+ LOGE("Failed to read from data source");
+ outputBuffer->release();
+ return UNKNOWN_ERROR;
+ }
+ int64_t timeUs;
+ CHECK(mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ if (mNextModTimeUs > timeUs) {
+ LOGV("mNextModTimeUs %lld > timeUs %lld", mNextModTimeUs, timeUs);
+ outputBuffer->set_range(0, 0);
+ *out = outputBuffer;
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return OK;
+ }
+
+ // Color convert to OMX_COLOR_FormatYUV420Planar if necessary
+ outputBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+ uint8_t *inPtr = (uint8_t *) mInputBuffer->data();
+ if (mVideoColorFormat != OMX_COLOR_FormatYUV420Planar) {
+ CHECK(mInputFrameData);
+ CHECK(mVideoColorFormat == OMX_COLOR_FormatYUV420SemiPlanar);
+ ConvertYUV420SemiPlanarToYUV420Planar(
+ inPtr, mInputFrameData, mVideoWidth, mVideoHeight);
+ inPtr = mInputFrameData;
+ }
+ CHECK(inPtr != NULL);
+
+ // Ready for encoding a video frame
+ VideoEncFrameIO vin, vout;
+ vin.height = ((mVideoHeight + 15) >> 4) << 4;
+ vin.pitch = ((mVideoWidth + 15) >> 4) << 4;
+ vin.timestamp = (timeUs + 500) / 1000; // in ms
+ vin.yChan = inPtr;
+ vin.uChan = vin.yChan + vin.height * vin.pitch;
+ vin.vChan = vin.uChan + ((vin.height * vin.pitch) >> 2);
+ unsigned long modTimeMs = 0;
+ int32_t nLayer = 0;
+ MP4HintTrack hintTrack;
+ if (!PVEncodeVideoFrame(mHandle, &vin, &vout,
+ &modTimeMs, outPtr, &dataLength, &nLayer) ||
+ !PVGetHintTrack(mHandle, &hintTrack)) {
+ LOGE("Failed to encode frame or get hink track at frame %lld",
+ mNumInputFrames);
+ outputBuffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return UNKNOWN_ERROR;
+ }
+ CHECK_EQ(NULL, PVGetOverrunBuffer(mHandle));
+ if (hintTrack.CodeType == 0) { // I-frame serves as sync frame
+ outputBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
+ }
+
+ ++mNumInputFrames;
+ mNextModTimeUs = modTimeMs * 1000LL;
+ outputBuffer->set_range(0, dataLength);
+ *out = outputBuffer;
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return OK;
+}
+
+void M4vH263Encoder::signalBufferReturned(MediaBuffer *buffer) {
+}
+
+} // namespace android
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h b/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h
new file mode 100644
index 0000000..18e54dc
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/include/cvei.h
@@ -0,0 +1,437 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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: cvei.h */
+/* Purpose: */
+/* Date: */
+/* Revision History: */
+/** @introduction Common Video Encoder Interface (CVEI) is intended to be used by
+ application developers who want to create a multimedia application with video
+ encoding feature. CVEI is designed such that new video encoder algorithms or
+ modules can be plugged in seamlessly without user interaction. In other words,
+ any changes to the CVEI library are transparent to the users. Users can still
+ use the same set of APIs for new encoding tools.
+
+ @requirement CVEI will take an input frame in one of several format supported
+ by PV and encode it to an MPEG4 bitstream. It will also return a reconstructed
+ image in YUV 4:2:0 format. Currently the input format supported are YUV 4:2:0,
+ RGB24 and UYVY 4:2:2.
+
+ CVEI is designed such that it is simple to use. It should hides implementation
+ dependency from the users. In this version, we decided that the operation will
+ be synchronous, i.e., the encoding will be a blocked call. Asynchronous operation
+ will be in the level above CVEI, i.e., in Author Engine Video Module which will
+ take care of capturing device as well.
+
+ @brief The following classes are used to interface with codecs. Their names
+ are CPVxxxVideoEncoder where xxx is codec specific such as MPEG4, H263, H26L,
+ etc. All of them are subclasses of CPVCommonVideoEncoder.
+*/
+/*********************************************************************************/
+
+#ifndef __CVEI_H
+#define __CVEI_H
+
+#include "oscl_scheduler_ao.h"
+#include "oscl_base.h"
+#include "mp4enc_api.h" /* for MP4HintTrack */
+
+#define MAX_LAYER 2
+
+/** General returned values. */
+enum TCVEI_RETVAL
+{
+ ECVEI_SUCCESS,
+ ECVEI_FAIL,
+ ECVEI_FLUSH,
+ ECVEI_MORE_OUTPUT
+} ;
+
+/** Returned events with the callback function. */
+enum TCVEI_EVENT
+{
+ /** Called when a packet or a frame of output bitstream is ready. */
+ ECVEI_BUFFER_READY,
+
+ /** Called when the last packet of a frame of output bitstream is ready. */
+ ECVEI_FRAME_DONE,
+
+ /** Called when no buffers is available for output bitstream. A buffer can be added thru AddBuffer API. */
+ ECVEI_NO_BUFFERS,
+
+ /** Called when there is an error with the encoding operation. */
+ ECVEI_ERROR
+};
+
+/** Contains supported input format */
+enum TPVVideoFormat
+{
+ ECVEI_RGB24,
+ ECVEI_RGB12,
+ ECVEI_YUV420,
+ ECVEI_UYVY,
+ ECVEI_YUV420SEMIPLANAR
+};
+
+/** Type of contents for optimal encoding mode. */
+enum TPVContentType
+{
+ /** Content is to be streamed in real-time. */
+ ECVEI_STREAMING,
+
+ /** Content is to be downloaded and playbacked later.*/
+ ECVEI_DOWNLOAD,
+
+ /** Content is to be 3gpp baseline compliant. */
+ ECVEI_H263
+};
+
+/** Rate control type. */
+enum TMP4RateControlType
+{
+ /** Constant quality, variable bit rate, fixed quantization level. */
+ ECONSTANT_Q,
+
+ /** Short-term constant bit rate control. */
+ ECBR_1,
+
+ /** Long-term constant bit rate control. */
+ EVBR_1
+};
+
+/** Targeted profile and level to encode. */
+enum TPVM4VProfileLevel
+{
+ /* Non-scalable profile */
+ ECVEI_SIMPLE_LEVEL0 = 0,
+ ECVEI_SIMPLE_LEVEL1,
+ ECVEI_SIMPLE_LEVEL2,
+ ECVEI_SIMPLE_LEVEL3,
+ ECVEI_CORE_LEVEL1,
+ ECVEI_CORE_LEVEL2,
+
+ /* Scalable profile */
+ ECVEI_SIMPLE_SCALABLE_LEVEL0 = 6,
+ ECVEI_SIMPLE_SCALABLE_LEVEL1,
+ ECVEI_SIMPLE_SCALABLE_LEVEL2,
+
+ ECVEI_CORE_SCALABLE_LEVEL1 = 10,
+ ECVEI_CORE_SCALABLE_LEVEL2,
+ ECVEI_CORE_SCALABLE_LEVEL3
+};
+
+/** This structure contains encoder settings. */
+struct TPVVideoEncodeParam
+{
+ /** Specifies an ID that will be used to specify this encoder while returning
+ the bitstream in asynchronous mode. */
+ uint32 iEncodeID;
+
+ /** Specifies whether base only (iNumLayer = 1) or base + enhancement layer
+ (iNumLayer =2 ) is to be used. */
+ int32 iNumLayer;
+
+ /** Specifies the width in pixels of the encoded frames. IFrameWidth[0] is for
+ base layer and iFrameWidth[1] is for enhanced layer. */
+ int iFrameWidth[MAX_LAYER];
+
+ /** Specifies the height in pixels of the encoded frames. IFrameHeight[0] is for
+ base layer and iFrameHeight[1] is for enhanced layer. */
+ int iFrameHeight[MAX_LAYER];
+
+ /** Specifies the cumulative bit rate in bit per second. IBitRate[0] is for base
+ layer and iBitRate[1] is for base+enhanced layer.*/
+ int iBitRate[MAX_LAYER];
+
+ /** Specifies the cumulative frame rate in frame per second. IFrameRate[0] is for
+ base layer and iFrameRate[1] is for base+enhanced layer. */
+ float iFrameRate[MAX_LAYER];
+
+ /** Specifies the picture quality factor on the scale of 1 to 10. It trades off
+ the picture quality with the frame rate. Higher frame quality means lower frame rate.
+ Lower frame quality for higher frame rate.*/
+ int32 iFrameQuality;
+
+ /** Enable the use of iFrameQuality to determine the frame rate. If it is false,
+ the encoder will try to meet the specified frame rate regardless of the frame quality.*/
+ bool iEnableFrameQuality;
+
+ /** Specifies the maximum number of P-frames between 2 INTRA frames. An INTRA mode is
+ forced to a frame once this interval is reached. When there is only one I-frame is present
+ at the beginning of the clip, iIFrameInterval should be set to -1. */
+ int32 iIFrameInterval;
+
+ /** According to iIFrameInterval setting, the minimum number of intra MB per frame is
+ optimally calculated for error resiliency. However, when iIFrameInterval is set to -1,
+ iNumIntraMBRefresh must be specified to guarantee the minimum number of intra
+ macroblocks per frame.*/
+ uint32 iNumIntraMBRefresh;
+
+ /** Specifies the VBV buffer size which determines the end-to-end delay between the
+ encoder and the decoder. The size is in unit of seconds. For download application,
+ the buffer size can be larger than the streaming application. For 2-way application,
+ this buffer shall be kept minimal. For a special case, in VBR mode, iBufferDelay will
+ be set to -1 to allow buffer underflow. */
+ float iBufferDelay;
+
+ /** Specifies the type of the access whether it is streaming, CVEI_STREAMING
+ (data partitioning mode) or download, CVEI_DOWNLOAD (combined mode).*/
+ TPVContentType iContentType;
+
+ /** Specifies the rate control algorithm among one of the following constant Q,
+ CBR and VBR. The structure TMP4RateControlType is defined below.*/
+ TMP4RateControlType iRateControlType;
+
+ /** Specifies high quality but also high complexity mode for rate control. */
+ bool iRDOptimal;
+
+ /** Specifies the initial quantization parameter for the first I-frame. If constant Q
+ rate control is used, this QP will be used for all the I-frames. This number must be
+ set between 1 and 31, otherwise, Initialize() will fail. */
+ int iIquant[2];
+
+ /** Specifies the initial quantization parameter for the first P-frame. If constant Q
+ rate control is used, this QP will be used for all the P-frames. This number must be
+ set between 1 and 31, otherwise, Initialize() will fail. */
+ int iPquant[2];
+
+ /** Specifies the initial quantization parameter for the first B-frame. If constant Q
+ rate control is used, this QP will be used for all the B-frames. This number must be
+ set between 1 and 31, otherwise, Initialize() will fail. */
+ int iBquant[2];
+
+ /** Specifies the search range in pixel unit for motion vector. The range of the
+ motion vector will be of dimension [-iSearchRange.5, +iSearchRange.0]. */
+ int32 iSearchRange;
+
+ /** Specifies the use of 8x8 motion vectors. */
+ bool iMV8x8;
+
+ /** Specifies the use of half-pel motion vectors. */
+ bool iMVHalfPel;
+
+ /** Specifies automatic scene detection where I-frame will be used the the first frame
+ in a new scene. */
+ bool iSceneDetection;
+
+ /** Specifies the packet size in bytes which represents the number of bytes between two resync markers.
+ For ECVEI_DOWNLOAD and ECVEI_H263, if iPacketSize is set to 0, there will be no resync markers in the bitstream.
+ For ECVEI_STREAMING is parameter must be set to a value greater than 0.*/
+ uint32 iPacketSize;
+
+ /** Specifies whether the current frame skipping decision is allowed after encoding
+ the current frame. If there is no memory of what has been coded for the current frame,
+ iNoCurrentSkip has to be on. */
+ bool iNoCurrentSkip;
+
+ /** Specifies that no frame skipping is allowed. Frame skipping is a tool used to
+ control the average number of bits spent to meet the target bit rate. */
+ bool iNoFrameSkip;
+
+ /** Specifies the duration of the clip in millisecond.*/
+ int32 iClipDuration;
+
+ /** Specifies the profile and level used to encode the bitstream. When present,
+ other settings will be checked against the range allowable by this target profile
+ and level. Fail may be returned from the Initialize call. */
+ TPVM4VProfileLevel iProfileLevel;
+
+ /** Specifies FSI Buffer input */
+ uint8* iFSIBuff;
+
+ /** Specifies FSI Buffer Length */
+ int iFSIBuffLength;
+
+
+};
+
+
+/** Structure for input format information */
+struct TPVVideoInputFormat
+{
+ /** Contains the width in pixels of the input frame. */
+ int32 iFrameWidth;
+
+ /** Contains the height in pixels of the input frame. */
+ int32 iFrameHeight;
+
+ /** Contains the input frame rate in the unit of frame per second. */
+ float iFrameRate;
+
+ /** Contains Frame Orientation. Used for RGB input. 1 means Bottom_UP RGB, 0 means Top_Down RGB, -1 for video formats other than RGB*/
+ int iFrameOrientation;
+
+ /** Contains the format of the input video, e.g., YUV 4:2:0, UYVY, RGB24, etc. */
+ TPVVideoFormat iVideoFormat;
+};
+
+
+/** Contains the input data information */
+struct TPVVideoInputData
+{
+ /** Pointer to an input frame buffer in input source format.*/
+ uint8 *iSource;
+
+ /** The corresponding time stamp of the input frame. */
+ uint32 iTimeStamp;
+};
+
+/** Contains the output data information */
+struct TPVVideoOutputData
+{
+ /** Pointer to the reconstructed frame buffer in YUV 4:2:0 domain. */
+ uint8 *iFrame;
+
+ /** The number of layer encoded, 0 for base, 1 for enhanced. */
+ int32 iLayerNumber;
+
+ /** Pointer to the encoded bitstream buffer. */
+ uint8 *iBitStream;
+
+ /** The size in bytes of iBStream. */
+ int32 iBitStreamSize;
+
+ /** The time stamp of the encoded frame according to the bitstream. */
+ uint32 iVideoTimeStamp;
+
+ /** The time stamp of the encoded frame as given before the encoding. */
+ uint32 iExternalTimeStamp;
+
+ /** The hint track information. */
+ MP4HintTrack iHintTrack;
+};
+
+/** An observer class for callbacks to report the status of the CVEI */
+class MPVCVEIObserver
+{
+ public:
+ /** The callback funtion with aEvent being one of TCVEIEvent enumeration. */
+ virtual void HandlePVCVEIEvent
+ (uint32 aId, uint32 aEvent, uint32 aParam1 = 0) = 0;
+ virtual ~MPVCVEIObserver() {}
+};
+
+/** This class is the base class for codec specific interface class.
+The users must maintain an instance of the codec specific class throughout
+the encoding session.
+*/
+class CommonVideoEncoder : public OsclTimerObject
+{
+ public:
+ /** Constructor for CVEI class. */
+ CommonVideoEncoder() : OsclTimerObject(OsclActiveObject::EPriorityNominal, "PVEncoder") {};
+
+ /** Initialization function to set the input video format and the
+ encoding parameters. This function returns CVEI_ERROR if there is
+ any errors. Otherwise, the function returns CVEI_SUCCESS.*/
+ virtual TCVEI_RETVAL Initialize(TPVVideoInputFormat *aVidInFormat, TPVVideoEncodeParam *aEncParam) = 0;
+
+ /** Set the observer for asynchronous encoding mode. */
+ virtual TCVEI_RETVAL SetObserver(MPVCVEIObserver *aObserver) = 0;
+
+ /** Add a buffer to the queue of output buffers for output bitstream in
+ asynchronous encoding mode. */
+ virtual TCVEI_RETVAL AddBuffer(TPVVideoOutputData *aVidOut) = 0;
+
+ /** This function sends in an input video data structure containing a source
+ frame and the associated timestamp. The encoded bitstream will be returned by
+ observer callback.
+ The above 3 APIs only replace EncodeFrame() API. Other APIs such as initialization
+ and update parameters remain the same. */
+ virtual TCVEI_RETVAL Encode(TPVVideoInputData *aVidIn) = 0;
+
+ /** This function returns the maximum VBV buffer size such that the
+ application can allocate a buffer that guarantees to fit one frame.*/
+ virtual int32 GetBufferSize() = 0;
+
+ /** This function returns the VOL header part (starting from the VOS header)
+ of the encoded bitstream. This function must be called after Initialize.
+ The output is written to the memory (volHeader) allocated by the users.*/
+ virtual TCVEI_RETVAL GetVolHeader(uint8 *volHeader, int32 *size, int32 layer) = 0;
+
+ /** This function sends in an input video data structure containing a source
+ frame and the associated timestamp. It returns an output video data structure
+ containing coded bit stream, reconstructed frame in YUV 4:2:0 (can be changed
+ to source format) and the timestamp associated with the coded frame.
+ The input timestamp may not correspond to the output timestamp. User can send
+ an input structure in without getting any encoded data back or getting an encoded
+ frame in the past. This function returns ECVEI_ERROR if there is any errors.
+ Otherwise, the function returns ECVEI_SUCCESS.
+ In case of Overrun Buffer usage, it is possible that return value is ECVEI_MORE_OUTPUT
+ which indicates that frame cannot fit in the current buffer*/
+ virtual TCVEI_RETVAL EncodeFrame(TPVVideoInputData *aVidIn, TPVVideoOutputData *aVidOut, int *aRemainingBytes
+#ifdef PVAUTHOR_PROFILING
+ , void *aParam1 = 0
+#endif
+ ) = 0;
+
+ /** Before the termination of the encoding process, the users have to query
+ whether there are any encoded frame pending inside the CVEI. The returned value
+ will indicate whether there are more frames to be flushed (ECVEI_FLUSH).
+ FlushOutput has to be called until there are no more frames, i.e., it returns
+ ECVEI_SUCCESS. This function may be called during the encoding operation if
+ there is no input frame and the application does not want to waste the time
+ waiting for input frame. It can call this function to flush encoded frame
+ out of the memory. */
+ virtual TCVEI_RETVAL FlushOutput(TPVVideoOutputData *aVidOut) = 0;
+
+ /** This function cleanup the CVEI allocated resources. */
+ virtual TCVEI_RETVAL Terminate() = 0;
+
+ /**This function dynamically changes the target bit rate of the encoder
+ while encoding. aBitRate[n] is the new accumulate target bit rate of layer n.
+ Successful update is returned with ECVEI_SUCCESS.*/
+ virtual TCVEI_RETVAL UpdateBitRate(int32 aNumLayer, int32 *aBitRate) = 0;
+
+ /** This function dynamically changes the target frame rate of the encoder
+ while encoding. aFrameRate[n] is the new accumulate target frame rate of
+ layer n. Successful update is returned with ECVEI_SUCCESS. */
+ virtual TCVEI_RETVAL UpdateFrameRate(int32 aNumLayer, float *aFrameRate) = 0;
+
+ /** This function dynamically changes the I-Vop update interval while
+ encoding to a new value, aIFrameInterval. */
+ virtual TCVEI_RETVAL UpdateIFrameInterval(int32 aIFrameInterval) = 0;
+
+ /** This function forces an I-Vop mode to the next frame to be encoded. */
+ virtual TCVEI_RETVAL IFrameRequest() = 0;
+
+ /** This function returns the input width of a specific layer
+ (not necessarily multiple of 16). */
+ virtual int32 GetEncodeWidth(int32 aLayer) = 0;
+
+ /** This function returns the input height of a specific layer
+ (not necessarily multiple of 16). */
+ virtual int32 GetEncodeHeight(int32 aLayer) = 0;
+
+ /** This function returns the target encoded frame rate of a specific layer. */
+ virtual float GetEncodeFrameRate(int32 aLayer) = 0;
+ protected:
+ virtual void Run(void) = 0;
+ virtual void DoCancel(void) = 0;
+ /* internal enum */
+ enum TCVEIState
+ {
+ EIdle,
+ EEncode
+ };
+
+ TCVEIState iState;
+ uint32 iId;
+};
+
+#endif
diff --git a/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
new file mode 100644
index 0000000..a54fd8b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/include/mp4enc_api.h
@@ -0,0 +1,454 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _MP4ENC_API_H_
+#define _MP4ENC_API_H_
+
+#include <string.h>
+
+#ifndef _PV_TYPES_
+#define _PV_TYPES_
+typedef unsigned char UChar;
+typedef char Char;
+typedef unsigned int UInt;
+typedef int Int;
+typedef unsigned short UShort;
+typedef short Short;
+typedef unsigned int Bool;
+typedef unsigned long ULong;
+
+#define PV_CODEC_INIT 0
+#define PV_CODEC_STOP 1
+#endif
+
+#define PV_TRUE 1
+#define PV_FALSE 0
+
+typedef enum
+{
+ SHORT_HEADER,
+ SHORT_HEADER_WITH_ERR_RES,
+ H263_MODE,
+ H263_MODE_WITH_ERR_RES,
+ DATA_PARTITIONING_MODE,
+ COMBINE_MODE_NO_ERR_RES,
+ COMBINE_MODE_WITH_ERR_RES
+
+} MP4EncodingMode;
+
+typedef enum
+{
+ CONSTANT_Q,
+ CBR_1,
+ VBR_1,
+ CBR_2,
+ VBR_2,
+ CBR_LOWDELAY
+} MP4RateControlType;
+
+typedef enum
+{
+ PASS1,
+ PASS2
+} PassNum;
+
+typedef enum
+{
+ PV_OFF,
+ PV_ON
+} ParamEncMode;
+
+
+/* {SPL0, SPL1, SPL2, SPL3, CPL1, CPL2, CPL2, CPL2} , SPL0: Simple Profile@Level0 , CPL1: Core Profile@Level1 */
+/* {SSPL0, SSPL1, SSPL2, SSPL2, CSPL1, CSPL2, CSPL3, CSPL3} , SSPL0: Simple Scalable Profile@Level0, CPL1: Core Scalable Profile@Level1 */
+
+typedef enum
+{
+ /* Non-scalable profile */
+ SIMPLE_PROFILE_LEVEL0 = 0,
+ SIMPLE_PROFILE_LEVEL1,
+ SIMPLE_PROFILE_LEVEL2,
+ SIMPLE_PROFILE_LEVEL3,
+ CORE_PROFILE_LEVEL1,
+ CORE_PROFILE_LEVEL2,
+
+ /* Scalable profile */
+ SIMPLE_SCALABLE_PROFILE_LEVEL0 = 6,
+ SIMPLE_SCALABLE_PROFILE_LEVEL1,
+ SIMPLE_SCALABLE_PROFILE_LEVEL2,
+
+ CORE_SCALABLE_PROFILE_LEVEL1 = 10,
+ CORE_SCALABLE_PROFILE_LEVEL2,
+ CORE_SCALABLE_PROFILE_LEVEL3
+
+} ProfileLevelType;
+
+
+typedef struct tagMP4HintTrack
+{
+ UChar MTB;
+ UChar LayerID;
+ UChar CodeType;
+ UChar RefSelCode;
+} MP4HintTrack;
+
+typedef struct tagvideoEncControls
+{
+ void *videoEncoderData;
+ Int videoEncoderInit;
+} VideoEncControls;
+
+
+typedef struct tagvideoEncFrameIO
+{
+ UChar *yChan; /* pointer to Y */
+ UChar *uChan; /* pointer to U */
+ UChar *vChan; /* pointer to V */
+ Int height; /* height for Y */
+ Int pitch; /* stride for Y */
+ ULong timestamp; /* modulo timestamp in millisecond*/
+
+} VideoEncFrameIO ;
+
+/**
+@brief Encoding options structure */
+typedef struct tagvideoEncOptions
+{
+ /** @brief Sets the encoding mode, defined by the above enumaration. If there are conflicts between the encoding mode
+ * and subsequent encoding options, encoding mode take precedent over encoding options. */
+ MP4EncodingMode encMode;
+
+ /** @brief Sets the number of bytes per packet, only used in DATA_PARTITIONING_MODE or COMBINE_MODE_WITH_ERR_RES mode.
+ * The resync marker will be inserted as often as the size of the packet.*/
+ Int packetSize;
+
+ /** @brief Selects MPEG-4/H.263 profile and level, if specified other encoding options must conform with it. */
+ ProfileLevelType profile_level;
+
+ /** @brief Enables reversible variable length code (RVLC) mode. Normally it is set to PV_OFF.*/
+ ParamEncMode rvlcEnable;
+
+ /** @brief Set the frequency of GOB header interval */
+ Int gobHeaderInterval;
+
+ /** @brief Sets the number of bitstream layers: 1 is base only: 2 is base + enhancement */
+ Int numLayers;
+
+ /** @brief Sets the number of ticks per second used for timing information encoded in MPEG4 bitstream.*/
+ Int timeIncRes;
+
+ /** @brief Sets the number of ticks in time increment resolution between 2 source frames (equivalent to source frame rate). */
+ Int tickPerSrc;
+
+ /** @brief Specifies encoded heights in pixels, height[n] represents the n-th layer's height. */
+ Int encHeight[2];
+
+ /** @brief Specifies encoded widths in pixels, width[n] represents the n-th layer's width.*/
+ Int encWidth[2];
+
+ /** @brief Specifies target frame rates in frames per second, frameRate[n] represents the n-th layer's target frame rate.*/
+ float encFrameRate[2];
+
+ /** @brief Specifies target bit rates in bits per second unit, bitRate[n] represents the n-th layer's target bit rate. */
+ Int bitRate[2];
+
+ /** @brief Specifies default quantization parameters for I-Vop. Iquant[n] represents the n-th layer default quantization parameter. The default is Iquant[0]=12.*/
+ Int iQuant[2];
+
+ /** @brief Specifies default quantization parameters for P-Vop. Pquant[n] represents the n-th layer default quantization parameter. The default is Pquant[0]=10.*/
+ Int pQuant[2];
+
+ /** @brief specifies quantization mode (H263 mode or MPEG mode) of the encoded base and enhance layer (if any).
+ * In Simple and Simple Scalable profile, we use only H263 mode.*/
+ Int quantType[2];
+
+ /** @brief Sets rate control algorithm, one of (CONSTANT_Q, CBR_1, or VBR_1).
+ * CONSTANT_Q uses the default quantization values to encode the sequence.
+ * CBR_1 (constant bit rate) controls the output at a desired bit rate
+ * VBR_1 (variable bit rate) gives better picture quality at the expense of bit rate fluctuation
+ * Note: type=CONSTANT_Q produces sequences with arbitrary bit rate.
+ * type=CBR_1 produces sequences suitable for streaming.
+ * type=VBR_1 produces sequences suitable for download. */
+ MP4RateControlType rcType;
+
+ /** @brief Sets the VBV buffer size (in the unit of second delay) used to prevent buffer overflow and underflow
+ * on the decoder side. This function is redundant to PVSetVBVSize. Either one of them is used at a time. */
+ float vbvDelay;
+
+ /** @brief Specifies whether frame skipping is permitted or not. When rate control type is set to CONSTANT_Q
+ * frame skipping is automatically banned. In CBR_1 and VBR_1 rate control, frame skipping is allowed by default.
+ * However, users can force no frame skipping with this flag, but buffer constraint may be violated.*/
+ ParamEncMode noFrameSkipped;
+
+ /** @brief Sets the maximum number of P-frames between two I-frames. I-frame mode is periodically forced
+ * if no I-frame is encoded after the specified period to add error resiliency and help resynchronize in case of errors.
+ * If scene change detection can add additional I-frame if new scenes are detected.
+ * intraPeriod is the I frame interval in terms of second.
+ * intraPeriod =0 indicates I-frame encoding only;
+ * intraPeriod = -1 indicates I-frame followed by all P-frames; (default)
+ * intraPeriod = N, indicates the number of P-frames between 2 I-frames.*/
+ Int intraPeriod;
+
+
+ /** @brief Specifies the number Intra MBs to be refreshed in a P-frame. */
+ Int numIntraMB;
+
+ /**
+ * @brief Specifies whether the scene change detection (SCD) is enabled or disabled.
+ * With SCD enable, when a new scene is detected, I-Vop mode will be used for the first frame of
+ * the new scene resulting in better picture quality. An insertion of an I-VOP resets the intraPeriod
+ * specified by the IntraPeriodAPI().*/
+ ParamEncMode sceneDetect;
+
+ /** @brief Specifies the search range of motion estimation search. Larger value implies
+ * larger search range, better motion vector match, but more complexity.
+ * If searchRange=n, the motion vector search is in the range of [-n,n-1] pixels.
+ * If half-pel mode is on, the range is [-n, (n-1)+1/2] pixels. The default value is 16.*/
+ Int searchRange;
+
+ /** @brief Turns on/off 8x8 block motion estimation and compensation.
+ * If on, four motion vectors may be used for motion estimation and compensation of a macroblock,
+ * otherwise one motion vector per macroblock is used. When the 8x8 MV is off, the total encoding complexity
+ * is less but the image quality is also worse. Therefore, it can be used in complexity limited environment.*/
+ ParamEncMode mv8x8Enable;
+
+
+ /** @brief Set the threshold for using intra DC VLC.
+ * Value must range from 0-7.*/
+ Int intraDCVlcTh;
+
+ /** @brief This flag turns on the use of AC prediction */
+ Bool useACPred;
+
+} VideoEncOptions;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+ /* API's */
+ /* Always start with this one !!*/
+ /**
+ * @brief Gets default encoding options. This way users only have to set relevant encoding options and leave the one
+ * they are unsure of.
+ * @encOption Pointer to VideoEncOption structure.
+ * @encUseCase This value determines the set of default encoding options, for example, different encoding options
+ * are assigned to streaming use-case as compared to download use-case. It can be project dependent too.
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVGetDefaultEncOption(VideoEncOptions *encOption, Int encUseCase);
+
+ /**
+ * @brief Verifies the consistency of encoding parameters, allocates memory needed and set necessary internal variables.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encCtrl, VideoEncOptions *encOption);
+
+ /* acquiring encoder info APIs */
+ /**
+ * @brief This function returns VOL header. It has to be called before the frame is encoded. If so,
+ * then the VOL Header is passed back to the application. Then all frames that are encoded do not contain the VOL Header.
+ * If you do not call the API then the VOL Header is passed within the first frame that is encoded.
+ * The behavior is unknown if it is called after the first frame is encoded. It is mainly used for MP4 file format authoring.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs.
+ * @param volHeader is the Buffer for VOL header.
+ * @param size is the size of VOL header in bytes.
+ * @param layer is the layer of the requested VOL header.
+ * @return true for correct operation; false if error happens.
+ */
+ OSCL_IMPORT_REF Bool PVGetVolHeader(VideoEncControls *encCtrl, UChar *volHeader, Int *size, Int layer);
+
+ /**
+ * @brief This function returns the profile and level in H.263 coding when the encoding parameters are set
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs.
+ * @param profileID is the pointer of the profile ID. Right now we only support profile 0
+ * @param levelID is the pointer of the level ID that could be 10-70.
+ * @return true for correct operation; false if error happens.
+ */
+ OSCL_IMPORT_REF Bool PVGetH263ProfileLevelID(VideoEncControls *encCtrl, Int *profileID, Int *levelID);
+
+ /**
+ * @brief This function returns the profile and level of MPEG4 when the encoding parameters are set
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs.
+ * @param profile_level is the pointer of the profile enumeration
+ * @param nLayer is the index of the layer of interest
+ * @return true for correct operation; false if error happens.
+ */
+ OSCL_IMPORT_REF Bool PVGetMPEG4ProfileLevelID(VideoEncControls *encCtrl, Int *profile_level, Int nLayer);
+
+ /**
+ * @brief This function returns maximum frame size in bytes
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param maxVideoFrameSize is the pointer of the maximum frame size
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVGetMaxVideoFrameSize(VideoEncControls *encCtrl, Int *maxVideoFrameSize);
+
+#ifndef LIMITED_API
+ /**
+ * @brief This function returns the total amount of memory (in bytes) allocated by the encoder library.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Int PVGetEncMemoryUsage(VideoEncControls *encCtrl);
+
+ /**
+ * @brief This function is used by PVAuthor to get the size of the VBV buffer.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param VBVSize is the pointer of The size of the VBV buffer in bytes.
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVGetVBVSize(VideoEncControls *encCtrl, Int *VBVSize);
+#endif
+
+ /**
+ * @brief This function encodes a frame in YUV 4:2:0 format from the *video_in input frame and put the result in YUV
+ * for reconstructed frame and bstream for MPEG4 bitstream. The application is required to allocate memory for
+ * bitstream buffer.The size of the input bitstream memory and the returned output buffer are specified in the
+ * size field. The encoded layer is specified by the nLayer field. If the current frame is not encoded, size=0 and nLayer=-1.
+ * Note: If the allocated buffer size is too small to fit a bitstream of a frame, then those extra bits will be left out
+ * which can cause syntactic error at the decoder side.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param vid_in is the pointer to VideoEncFrameIO structure containing the YUV input data
+ * @param vid_out is the pointer to VideoEncFrameIO structure containing the reconstructed YUV output data after encoding
+ * @param nextModTime is the timestamp encoder expects from the next input
+ * @param bstream is the pointer to MPEG4 bitstream buffer
+ * @param size is the size of bitstream buffer allocated (input) and size of the encoded bitstream (output).
+ * @param nLayer is the layer of the encoded frame either 0 for base or 1 for enhancement layer. The value -1 indicates skipped frame due to buffer overflow.
+ * @return true newfor correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVEncodeVideoFrame(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, VideoEncFrameIO *vid_out,
+ ULong *nextModTime, UChar *bstream, Int *size, Int *nLayer);
+
+
+ /**
+ * @brief This function is used to query overrun buffer. It is used when PVEncodeVideoFrame.returns size that is
+ * larger than the input size.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @return Pointer to the overrun buffer. NULL if overrun buffer is not used.
+ */
+ OSCL_IMPORT_REF UChar* PVGetOverrunBuffer(VideoEncControls *encCtrl);
+
+#ifndef NO_SLICE_ENCODE /* This set of APIs are not working. This functionality has been partially
+ replaced by the introduction of overrun buffer. */
+
+ /* slice-based coding */
+ /**
+ * @brief This function sets the input YUV frame and timestamp to be encoded by the slice-based encoding function PVEncodeSlice().
+ * It also return the memory address the reconstructed frame will be copied to (in advance) and the coded layer number.
+ * The encoder library processes the timestamp and determine if this frame is to be encoded or not. If the current frame
+ * is not encoded, nLayer=-1. For frame-based motion estimation, the motion estimation of the entire frame is also performed
+ * in this function. For MB-based motion estimation, the motion vector is searched while coding each MB in PVEncodeSlice().
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param vid_in is the pointer to VideoEncFrameIO structure containing the YUV input data
+ * @param nextModTime is the timestamp encoder expects from the next input if this input is rejected and nLayer is set to -1.
+ * @param nLayer is the layer of the encoded frame either 0 for base or 1 for enhancement layer. The value -1 indicates skipped frame due to buffer overflow.
+ * @return true newfor correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVEncodeFrameSet(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, ULong *nextModTime, Int *nLayer);
+ /**
+ * @brief This function encodes a GOB (short header mode) or a packet (data partitioning mode or combined mode with resync marker)
+ * and output the reconstructed frame and MPEG4 bitstream. The application is required to allocate memory for the bitstream buffer.
+ * The size of the input bitstream memory and the returned output buffer are specified in the size field. If the buffer size is
+ * smaller than the requested packet size, user has to call PVEncodeSlice again to get the rest of that pending packet before moving
+ * on to the next packet. For the combined mode without resync marker, the function returns when the buffer is full.
+ * The end-of-frame flag indicates the completion of the frame encoding. Next frame must be sent in with PVEncodeFrameSet().
+ * At the end-of-frame, the next video input address and the next video modulo timestamp will be set.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param bstream is the pointer to MPEG4 bitstream buffer.
+ * @param size is the size of bitstream buffer allocated (input) and size of the encoded bitstream (output).
+ * @param endofFrame is a flag indicating the end-of-frame, '1'. Otherwise, '0'. When PVSetNoCurrentFrameSkip is OFF,
+ * end-of-frame '-1' indicates current frame bitstream must be disregarded.
+ * @param vid_out is the pointer to VideoEncFrameIO structure containing the reconstructed YUV output data after encoding
+ * @param nextModTime is the timestamp encoder expects from the next input
+ * @return true newfor correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVEncodeSlice(VideoEncControls *encCtrl, UChar *bstream, Int *size,
+ Int *endofFrame, VideoEncFrameIO *vid_out, ULong *nextModTime);
+#endif
+
+ /**
+ * @brief This function returns MP4 file format hint track information.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param info is the structure for MP4 hint track information
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVGetHintTrack(VideoEncControls *encCtrl, MP4HintTrack *info);
+
+#ifndef LIMITED_API
+ /**
+ * @brief updates target frame rates of the encoded base and enhance layer (if any) while encoding operation is ongoing.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param frameRate is the pointers to array of target frame rates in frames per second,
+ * frameRate[n] represents the n-th layer's target frame rate.
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVUpdateEncFrameRate(VideoEncControls *encCtrl, float *frameRate); /* for 2-way */
+
+
+ /**
+ * @brief updates target bit rates of the encoded base and enhance layer (if any) while encoding operation is ongoing.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param bitRate is the pointers to array of target bit rates in bits per second unit,
+ * bitRate[n] represents the n-th layer's target bit rate.
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVUpdateBitRate(VideoEncControls *encCtrl, Int *bitRate); /* for 2-way */
+
+
+ /**
+ * @brief updates the INTRA frame refresh interval while encoding operation is ongoing.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param aIFramePeriod is a new value of INTRA frame interval in the unit of number of coded frames.
+ * @return true for correct operation; false if error happens
+ */
+
+ OSCL_IMPORT_REF Bool PVUpdateIFrameInterval(VideoEncControls *encCtrl, Int aIFramePeriod);/* for 2-way */
+
+ /**
+ * @brief specifies the number Intra MBs to be refreshed
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @param numMB is the number of Intra MBs to be refreshed
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVUpdateNumIntraMBRefresh(VideoEncControls *encCtrl, Int numMB); /* for 2-way */
+
+ /**
+ * @brief This function is called whenever users want the next base frame to be encoded as an I-Vop.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVIFrameRequest(VideoEncControls *encCtrl); /* for 2-way */
+
+#endif // LIMITED_API
+
+ /* finishing encoder */
+ /**
+ * @brief This function frees up all the memory allocated by the encoder library.
+ * @param encCtrl is video encoder control structure that is always passed as input in all APIs
+ * @return true for correct operation; false if error happens
+ */
+ OSCL_IMPORT_REF Bool PVCleanUpVideoEncoder(VideoEncControls *encCtrl);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _MP4ENC_API_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp
new file mode 100644
index 0000000..5c4c4ab
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.cpp
@@ -0,0 +1,859 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/* Date: 8/02/04 */
+/* Description: */
+/* Change the bitstream parsing algorithm. Use temporary word of 2 or 4 bytes */
+/* before writing it to the bitstream buffer. */
+/* Note byteCount doesn't have to be multiple of 2 or 4 */
+/*********************************************************************************/
+
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+#include <stdlib.h>
+
+static const UChar Mask[ ] =
+{
+ 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF
+};
+
+#define WORD_SIZE 4 /* for 32-bit machine */
+
+/*Note:
+ 1. There is a problem when output the last bits(which can not form a byte yet
+ so when you output, you need to stuff to make sure it is a byte
+ 2. I now hard coded byte to be 8 bits*/
+
+
+/* ======================================================================== */
+/* Function : BitStreamCreateEnc(Int bufferSize ) */
+/* Date : 08/29/2000 */
+/* Purpose : Create a bitstream to hold one encoded video packet or frame */
+/* In/out : */
+/* bufferSize : size of the bitstream buffer in bytes */
+/* Return : Pointer to the BitstreamEncVideo */
+/* Modified : */
+/* ======================================================================== */
+
+BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize)
+{
+ BitstreamEncVideo *stream;
+ stream = (BitstreamEncVideo *) M4VENC_MALLOC(sizeof(BitstreamEncVideo));
+ if (stream == NULL)
+ {
+ return NULL;
+ }
+ stream->bufferSize = bufferSize;
+ stream->bitstreamBuffer = (UChar *) M4VENC_MALLOC(stream->bufferSize * sizeof(UChar));
+ if (stream->bitstreamBuffer == NULL)
+ {
+ M4VENC_FREE(stream);
+ stream = NULL;
+ return NULL;
+ }
+ M4VENC_MEMSET(stream->bitstreamBuffer, 0, stream->bufferSize*sizeof(UChar));
+ stream->word = 0;
+#if WORD_SIZE==4
+ stream->bitLeft = 32;
+#else
+ stream->bitLeft = 16;
+#endif
+ stream->byteCount = 0;
+
+ stream->overrunBuffer = NULL;
+ stream->oBSize = 0;
+
+ return stream;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamCloseEnc( ) */
+/* Date : 08/29/2000 */
+/* Purpose : close a bitstream */
+/* In/out :
+ stream : the bitstream to be closed */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+Void BitstreamCloseEnc(BitstreamEncVideo *stream)
+{
+ if (stream)
+ {
+ if (stream->bitstreamBuffer)
+ {
+ M4VENC_FREE(stream->bitstreamBuffer);
+ }
+
+ M4VENC_FREE(stream);
+ }
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamPutBits(BitstreamEncVideo *stream, Int Length,
+ Int Value) */
+/* Date : 08/29/2000 */
+/* Purpose : put Length (1-16) number of bits to the stream */
+/* for 32-bit machine this function can do upto 32 bit input */
+/* In/out : */
+/* stream the bitstream where the bits are put in */
+/* Length bits length (should belong to 1 to 16) */
+/* Value those bits value */
+/* Return : PV_STATUS */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value)
+{
+ PV_STATUS status;
+
+ if (stream->bitLeft > Length)
+ {
+ stream->word <<= Length;
+ stream->word |= Value; /* assuming Value is not larger than Length */
+ stream->bitLeft -= Length;
+ return PV_SUCCESS;
+ }
+ else
+ {
+
+ stream->word <<= stream->bitLeft;
+ Length -= stream->bitLeft;
+ stream->word |= ((UInt)Value >> Length);
+
+ status = BitstreamSaveWord(stream);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ /* we got new Length and Value */
+ /* note that Value is not "clean" because of msb are not masked out */
+ stream->word = Value;
+ stream->bitLeft -= Length;
+ /* assuming that Length is no more than 16 bits */
+ /* stream->bitLeft should be greater than zero at this point */
+ //if(stream->bitLeft<=0)
+ // exit(-1);
+ return PV_SUCCESS;
+ }
+}
+
+/* ======================================================================== */
+/* Function : BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, UInt32 Value) */
+/* Date : 08/29/2000 */
+/* Purpose : Use this function to put Length (17-32) number of bits to */
+/* for 16-bit machine the stream. */
+/* In/out : */
+/* stream the bitstream where the bits are put in */
+/* Length bits length (should belong to 17 to 32) */
+/* Value those bits value */
+/* Return : PV_STATUS */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value)
+{
+ PV_STATUS status;
+ UInt topValue;
+ Int topLength;
+
+ topValue = (Value >> 16);
+ topLength = Length - 16;
+
+ if (topLength > 0)
+ {
+ status = BitstreamPutBits(stream, topLength, topValue);
+
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ status = BitstreamPutBits(stream, 16, (UInt)(Value & 0xFFFF));
+
+ return status;
+ }
+ else
+ {
+ status = BitstreamPutBits(stream, Length, (UInt)Value);
+ return status;
+ }
+}
+
+/* ======================================================================== */
+/* Function : BitstreamSaveWord */
+/* Date : 08/03/2004 */
+/* Purpose : save written word into the bitstream buffer. */
+/* In/out : */
+/* stream the bitstream where the bits are put in */
+/* Return : PV_STATUS */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream)
+{
+ UChar *ptr;
+ UInt word;
+
+ /* assume that stream->bitLeft is always zero when this function is called */
+ if (stream->byteCount + WORD_SIZE > stream->bufferSize)
+ {
+ if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, WORD_SIZE))
+ {
+ stream->byteCount += WORD_SIZE;
+ return PV_FAIL;
+ }
+ }
+
+ ptr = stream->bitstreamBuffer + stream->byteCount;
+ word = stream->word;
+ stream->word = 0; /* important to reset to zero */
+
+ /* NOTE: byteCount does not have to be multiple of 2 or 4 */
+#if (WORD_SIZE == 4)
+ *ptr++ = word >> 24;
+ *ptr++ = 0xFF & (word >> 16);
+#endif
+
+ *ptr++ = 0xFF & (word >> 8);
+ *ptr = 0xFF & word;
+
+#if (WORD_SIZE == 4)
+ stream->byteCount += 4;
+ stream->bitLeft = 32;
+#else
+ stream->byteCount += 2;
+ stream->bitLeft = 16;
+#endif
+
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamSavePartial */
+/* Date : 08/03/2004 */
+/* Purpose : save unfinished written word into the bitstream buffer. */
+/* In/out : */
+/* stream the bitstream where the bits are put in */
+/* Return : PV_STATUS */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction)
+{
+ UChar *ptr;
+ UInt word, shift;
+ Int numbyte, bitleft, bitused;
+
+ bitleft = stream->bitLeft;
+ bitused = (WORD_SIZE << 3) - bitleft; /* number of bits used */
+ numbyte = bitused >> 3; /* number of byte fully used */
+
+ if (stream->byteCount + numbyte > stream->bufferSize)
+ {
+ if (PV_SUCCESS != BitstreamUseOverrunBuffer(stream, numbyte))
+ {
+ stream->byteCount += numbyte;
+ return PV_FAIL;
+ }
+ }
+
+ ptr = stream->bitstreamBuffer + stream->byteCount;
+ word = stream->word;
+ word <<= bitleft; /* word is not all consumed */
+ bitleft = bitused - (numbyte << 3); /* number of bits used (fraction) */
+ stream->byteCount += numbyte;
+ if (bitleft)
+ {
+ *fraction = 1;
+ }
+ else
+ {
+ *fraction = 0;
+ }
+ bitleft = (WORD_SIZE << 3) - bitleft;
+ /* save new value */
+ stream->bitLeft = bitleft;
+
+ shift = ((WORD_SIZE - 1) << 3);
+ while (numbyte)
+ {
+ *ptr++ = (UChar)((word >> shift) & 0xFF);
+ word <<= 8;
+ numbyte--;
+ }
+
+ if (*fraction)
+ {// this could lead to buffer overrun when ptr is already out of bound.
+ // *ptr = (UChar)((word>>shift)&0xFF); /* need to do it for the last fractional byte */
+ }
+
+ /* save new values */
+ stream->word = word >> bitleft;
+
+ /* note we don't update byteCount, bitLeft and word */
+ /* so that encoder can continue PutBits if they don't */
+
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : BitstreamShortHeaderByteAlignStuffing( */
+/* BitstreamEncVideo *stream) */
+/* Date : 08/29/2000 */
+/* Purpose : bit stuffing for next start code in short video header */
+/* In/out : */
+/* Return : number of bits to be stuffed */
+/* Modified : */
+/* ======================================================================== */
+
+Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream)
+{
+ UInt restBits;
+ Int fraction;
+
+ restBits = (stream->bitLeft & 0x7); /* modulo 8 */
+
+ if (restBits) /*short_video_header[0] is 1 in h263 baseline*/
+ {
+ /* H.263 style stuffing */
+ BitstreamPutBits(stream, restBits, 0);
+ }
+
+ if (stream->bitLeft != (WORD_SIZE << 3))
+ {
+ BitstreamSavePartial(stream, &fraction);
+ }
+
+ return restBits;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream) */
+/* Date : 08/29/2000 */
+/* Purpose : bit stuffing for next start code in MPEG-4 */
+/* In/out : */
+/* Return : number of bits to be stuffed */
+/* Modified : */
+/* ======================================================================== */
+Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream)
+{
+
+ UInt restBits;
+ Int fraction;
+ /* Question: in MPEG-4 , short_video_header[0]==0 => even already byte aligned, will still stuff 8 bits
+ need to check with */
+ /*if (!(getPointerENC(index1, index2)%8) && short_video_header[0]) return 0;*/
+
+ /* need stuffing bits, */
+ BitstreamPutBits(stream, 1, 0);
+
+ restBits = (stream->bitLeft & 0x7); /* modulo 8 */
+
+ if (restBits) /*short_video_header[0] is 1 in h263 baseline*/
+ {
+ /* need stuffing bits, */
+ BitstreamPutBits(stream, restBits, Mask[restBits]);
+ }
+
+ if (stream->bitLeft != (WORD_SIZE << 3))
+ {
+ BitstreamSavePartial(stream, &fraction);
+ }
+
+ return (restBits);
+}
+
+/*does bit stuffing for next resync marker*/
+/* does bit stuffing for next resync marker
+ * "0"
+ * "01"
+ * "011"
+ * "0111"
+ * "01111"
+ * "011111"
+ * "0111111"
+ * "01111111" (8-bit codeword)
+ */
+
+/*Int BitstreamNextResyncMarkerEnc(BitstreamEncVideo *stream)
+{
+ Int count;
+ BitstreamPut1Bits(stream,0);
+ count=8-stream->totalBits & 8;
+ BitstreamPutBits(stream,count,Mask[count]);
+ return count;
+}*/
+
+/* ======================================================================== */
+/* Function : BitstreamAppendEnc( BitstreamEncVideo *bitstream1, */
+/* BitstreamEncVideo *bitstream2 ) */
+/* Date : 08/29/2000 */
+/* Purpose : Append the intermediate bitstream (bitstream2) to the end of */
+/* output bitstream(bitstream1) */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+
+PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+ PV_STATUS status;
+ UChar *ptrBS2, *ptrBS1;
+ UChar byteBS2, byteBS1;
+ Int numbyte2;
+ Int bitused, bitleft, offset, fraction;
+
+ status = BitstreamSavePartial(bitstream1, &fraction);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ offset = fraction;
+ status = BitstreamSavePartial(bitstream2, &fraction);
+ if (status != PV_SUCCESS)
+ {
+ return status;
+ }
+
+ if (!offset) /* bitstream1 is byte-aligned */
+ {
+ return BitstreamAppendPacket(bitstream1, bitstream2);
+ }
+
+ offset += fraction;
+
+ /* since bitstream1 doesn't have to be byte-aligned, we have to process byte by byte */
+ /* we read one byte from bitstream2 and use BitstreamPutBits to do the job */
+ if (bitstream1->byteCount + bitstream2->byteCount + offset > bitstream1->bufferSize)
+ {
+ if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount + offset))
+ {
+ bitstream1->byteCount += (bitstream2->byteCount + offset);
+ return PV_FAIL;
+ }
+ }
+
+ ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
+ ptrBS2 = bitstream2->bitstreamBuffer;
+
+ bitused = (WORD_SIZE << 3) - bitstream1->bitLeft; /* this must be between 1-7 */
+ bitleft = 8 - bitused;
+
+ numbyte2 = bitstream2->byteCount; /* number of byte to copy from bs2 */
+ bitstream1->byteCount += numbyte2; /* new byteCount */
+
+ byteBS1 = ((UChar) bitstream1->word) << bitleft; /* fraction byte from bs1 */
+
+ while (numbyte2)
+ {
+ byteBS2 = *ptrBS2++;
+ byteBS1 |= (byteBS2 >> bitused);
+ *ptrBS1++ = byteBS1;
+ byteBS1 = byteBS2 << bitleft;
+ numbyte2--;
+ }
+
+ bitstream1->word = byteBS1 >> bitleft; /* bitstream->bitLeft remains the same */
+
+ /* now save bs2->word in bs1 */
+ status = BitstreamPutBits(bitstream1, (WORD_SIZE << 3) - bitstream2->bitLeft, bitstream2->word);
+
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamAppendPacket( BitstreamEncVideo *bitstream1, */
+/* BitstreamEncVideo *bitstream2 ) */
+/* Date : 05/31/2001 */
+/* Purpose : Append the intermediate bitstream (bitstream2) to the end of */
+/* output bitstream(bitstream1) knowing that bitstream1 is byte-aligned*/
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+ UChar *ptrBS2, *ptrBS1;
+ Int numbyte2;
+
+ if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
+ {
+ if (PV_SUCCESS != BitstreamUseOverrunBuffer(bitstream1, bitstream2->byteCount))
+ {
+ bitstream1->byteCount += bitstream2->byteCount; /* legacy, to keep track of total bytes */
+ return PV_FAIL;
+ }
+ }
+
+ ptrBS1 = bitstream1->bitstreamBuffer + bitstream1->byteCount; /* move ptr bs1*/
+ ptrBS2 = bitstream2->bitstreamBuffer;
+
+ numbyte2 = bitstream2->byteCount;
+ bitstream1->byteCount += numbyte2; /* new byteCount */
+
+ /*copy all the bytes in bitstream2*/
+ M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
+
+ bitstream1->word = bitstream2->word; /* bitstream1->bitLeft is the same */
+ bitstream1->bitLeft = bitstream2->bitLeft;
+
+ return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamAppendPacketNoOffset( BitstreamEncVideo *bitstream1,*/
+/* BitstreamEncVideo *bitstream2 ) */
+/* Date : 04/23/2002 */
+/* Purpose : Append the intermediate bitstream (bitstream2) to the end of */
+/* output bitstream(bitstream1) , for slice-based coding only */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+ PV_STATUS status = PV_SUCCESS;
+ UChar *ptrBS2, *ptrBS1;
+ Int numbyte2;
+ Int byteleft;
+
+ numbyte2 = bitstream2->byteCount;
+
+ if (bitstream1->byteCount + bitstream2->byteCount > bitstream1->bufferSize)
+ {
+ numbyte2 = bitstream1->bufferSize - bitstream1->byteCount;
+ status = PV_END_OF_BUF; /* signal end of buffer */
+ }
+
+ ptrBS1 = bitstream1->bitstreamBuffer; /* move ptr bs1*/
+ ptrBS2 = bitstream2->bitstreamBuffer;
+
+ bitstream1->byteCount += numbyte2; /* should be equal to bufferSize */
+
+ /*copy all the bytes in bitstream2*/
+ M4VENC_MEMCPY(ptrBS1, ptrBS2, sizeof(UChar)*numbyte2);
+ bitstream1->word = 0;
+ bitstream1->bitLeft = (WORD_SIZE << 3);
+
+ if (status == PV_END_OF_BUF) /* re-position bitstream2 */
+ {
+ byteleft = bitstream2->byteCount - numbyte2;
+
+ M4VENC_MEMCPY(ptrBS2, ptrBS2 + numbyte2, sizeof(UChar)*byteleft);
+
+ bitstream2->byteCount = byteleft;
+ /* bitstream2->word and bitstream->bitLeft are unchanged.
+ they should be 0 and (WORD_SIZE<<3) */
+ }
+
+ return status;
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/* Function : BitstreamRepos( BitstreamEncVideo *bitstream, */
+/* Int byteCount, Int bitCount) */
+/* Date : 04/28/2002 */
+/* Purpose : Reposition the size of the buffer content (curtail) */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount)
+{
+ UChar *ptr, byte;
+ UInt word;
+ Int fraction;
+
+ BitstreamSavePartial(bitstream, &fraction);
+
+ bitstream->byteCount = byteCount;
+ ptr = bitstream->bitstreamBuffer + byteCount; /* get fraction of the byte */
+ if (bitCount)
+ {
+ bitstream->bitLeft = (WORD_SIZE << 3) - bitCount; /* bitCount should be 0-31 */
+ word = *ptr++;
+ byte = *ptr++;
+ word = byte | (word << 8);
+#if (WORD_SIZE == 4)
+ byte = *ptr++;
+ word = byte | (word << 8);
+ byte = *ptr++;
+ word = byte | (word << 8);
+#endif
+ bitstream->word = word >> (bitstream->bitLeft);
+ }
+ else
+ {
+ bitstream->word = 0;
+ bitstream->bitLeft = (WORD_SIZE << 3);
+ }
+
+ return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamFlushBits(BitstreamEncVideo *bitstream1, */
+/* Int num_bit_left) */
+/* Date : 04/24/2002 */
+/* Purpose : Flush buffer except the last num_bit_left bits. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+
+PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left)
+{
+ Int i;
+ UChar *ptrDst, *ptrSrc;
+ Int leftover, bitused;
+ Int new_byte = (num_bit_left >> 3);
+ Int new_bit = num_bit_left - (new_byte << 3); /* between 0-7 */
+
+ ptrSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
+ ptrDst = bitstream1->bitstreamBuffer;
+
+ bitused = (WORD_SIZE << 3) - bitstream1->bitLeft;
+
+ leftover = 8 - bitused; /* bitused should be between 0-7 */
+
+ bitstream1->byteCount = new_byte;
+ bitstream1->bitLeft = (WORD_SIZE << 3) - new_bit;
+
+ if (!bitused) /* byte aligned */
+ {
+ M4VENC_MEMCPY(ptrDst, ptrSrc, new_byte + 1);
+ }
+ else
+ {
+ /*copy all the bytes in bitstream2*/
+ for (i = 0; i < new_byte; i++)
+ {
+ *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
+ ptrSrc++;
+ }
+ /* copy for the last byte of ptrSrc, copy extra bits doesn't hurt */
+ if (new_bit)
+ {
+ *ptrDst++ = (ptrSrc[0] << bitused) | (ptrSrc[1] >> leftover);
+ ptrSrc++;
+ }
+ }
+ if (new_bit)
+ {
+ ptrSrc = bitstream1->bitstreamBuffer + new_byte;
+ bitstream1->word = (*ptrSrc) >> (8 - new_bit);
+ }
+
+ return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : BitstreamPrependPacket( BitstreamEncVideo *bitstream1, */
+/* BitstreamEncVideo *bitstream2 ) */
+/* Date : 04/26/2002 */
+/* Purpose : Prepend the intermediate bitstream (bitstream2) to the beginning of */
+/* output bitstream(bitstream1) */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2)
+{
+ UChar *pSrc, *pDst, byte;
+ Int movebyte, bitused, leftover, i, fraction;
+
+ BitstreamSavePartial(bitstream2, &fraction); /* make sure only fraction of byte left */
+ BitstreamSavePartial(bitstream1, &fraction);
+
+ if (bitstream1->byteCount + bitstream2->byteCount >= bitstream1->bufferSize)
+ {
+ bitstream1->byteCount += bitstream2->byteCount;
+ return PV_END_OF_BUF;
+ }
+
+ movebyte = bitstream1->byteCount;
+ if (movebyte < bitstream2->byteCount)
+ movebyte = bitstream2->byteCount;
+ movebyte++;
+
+ /* shift bitstream1 to the right by movebyte */
+ pSrc = bitstream1->bitstreamBuffer;
+ pDst = pSrc + movebyte;
+
+ M4VENC_MEMCPY(pDst, pSrc, bitstream1->byteCount + 1);
+
+ /* copy bitstream2 to the beginning of bitstream1 */
+ M4VENC_MEMCPY(pSrc, bitstream2->bitstreamBuffer, bitstream2->byteCount + 1);
+
+ /* now shift back previous bitstream1 buffer to the end */
+ pSrc = pDst;
+ pDst = bitstream1->bitstreamBuffer + bitstream2->byteCount;
+
+ bitused = (WORD_SIZE << 3) - bitstream2->bitLeft;
+ leftover = 8 - bitused; /* bitused should be 0-7 */
+
+ byte = (bitstream2->word) << leftover;
+
+ *pDst++ = byte | (pSrc[0] >> bitused);
+
+ for (i = 0; i < bitstream1->byteCount + 1; i++)
+ {
+ *pDst++ = ((pSrc[0] << leftover) | (pSrc[1] >> bitused));
+ pSrc++;
+ }
+
+ bitstream1->byteCount += bitstream2->byteCount;
+ //bitstream1->bitCount += bitstream2->bitCount;
+ bitused = (WORD_SIZE << 4) - (bitstream1->bitLeft + bitstream2->bitLeft);
+
+ if (bitused >= 8)
+ {
+ bitused -= 8;
+ bitstream1->byteCount++;
+ }
+
+ bitstream1->bitLeft = (WORD_SIZE << 3) - bitused;
+
+ bitstream2->byteCount = bitstream2->word = 0;
+ bitstream2->bitLeft = (WORD_SIZE << 3);
+
+ pSrc = bitstream1->bitstreamBuffer + bitstream1->byteCount;
+ leftover = 8 - bitused;
+ //*pSrc = (pSrc[0]>>leftover)<<leftover; /* make sure the rest of bits are zeros */
+
+ bitstream1->word = (UInt)((pSrc[0]) >> leftover);
+
+ return PV_SUCCESS;
+}
+#endif /* NO_SLICE_ENCODE */
+
+
+/* ======================================================================== */
+/* Function : BitstreamGetPos( BitstreamEncVideo *stream */
+/* Date : 08/05/2004 */
+/* Purpose : Get the bit position. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+Int BitstreamGetPos(BitstreamEncVideo *stream)
+{
+
+ return stream->byteCount*8 + (WORD_SIZE << 3) - stream->bitLeft;
+}
+
+void BitstreamEncReset(BitstreamEncVideo *stream)
+{
+ stream->bitLeft = (WORD_SIZE << 3);
+ stream->word = 0;
+ stream->byteCount = 0;
+ return ;
+}
+
+/* This function set the overrun buffer, and VideoEncData context for callback to reallocate
+overrun buffer. */
+Void BitstreamSetOverrunBuffer(BitstreamEncVideo* stream, UChar* overrunBuffer, Int oBSize, VideoEncData *video)
+{
+ stream->overrunBuffer = overrunBuffer;
+ stream->oBSize = oBSize;
+ stream->video = video;
+
+ return ;
+}
+
+
+/* determine whether overrun buffer can be used or not */
+PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes)
+{
+ VideoEncData *video = stream->video;
+
+ if (stream->overrunBuffer != NULL) // overrunBuffer is set
+ {
+ if (stream->bitstreamBuffer != stream->overrunBuffer) // not already used
+ {
+ if (stream->byteCount + numExtraBytes >= stream->oBSize)
+ {
+ stream->oBSize = stream->byteCount + numExtraBytes + 100;
+ stream->oBSize &= (~0x3); // make it multiple of 4
+
+ // allocate new overrun Buffer
+ if (video->overrunBuffer)
+ {
+ M4VENC_FREE(video->overrunBuffer);
+ }
+ video->oBSize = stream->oBSize;
+ video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
+ stream->overrunBuffer = video->overrunBuffer;
+ if (stream->overrunBuffer == NULL)
+ {
+ return PV_FAIL;
+ }
+ }
+
+ // copy everything to overrun buffer and start using it.
+ memcpy(stream->overrunBuffer, stream->bitstreamBuffer, stream->byteCount);
+ stream->bitstreamBuffer = stream->overrunBuffer;
+ stream->bufferSize = stream->oBSize;
+ }
+ else // overrun buffer is already used
+ {
+ if (stream->byteCount + numExtraBytes >= stream->oBSize)
+ {
+ stream->oBSize = stream->byteCount + numExtraBytes + 100;
+ }
+
+ // allocate new overrun buffer
+ stream->oBSize &= (~0x3); // make it multiple of 4
+ video->oBSize = stream->oBSize;
+ video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * stream->oBSize);
+ if (video->overrunBuffer == NULL)
+ {
+ return PV_FAIL;
+ }
+
+ // copy from the old buffer to new buffer
+ memcpy(video->overrunBuffer, stream->overrunBuffer, stream->byteCount);
+ // free old buffer
+ M4VENC_FREE(stream->overrunBuffer);
+ // assign pointer to new buffer
+ stream->overrunBuffer = video->overrunBuffer;
+ stream->bitstreamBuffer = stream->overrunBuffer;
+ stream->bufferSize = stream->oBSize;
+ }
+
+ return PV_SUCCESS;
+ }
+ else // overrunBuffer is not enable.
+ {
+ return PV_FAIL;
+ }
+
+}
+
+
+
+
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h
new file mode 100644
index 0000000..0bce257
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/bitstream_io.h
@@ -0,0 +1,57 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _BITSTREAM_IO_H_
+#define _BITSTREAM_IO_H_
+
+#define BitstreamPut1Bits(x,y) BitstreamPutBits(x,1,y)
+#define BitstreamPutGT8Bits(x,y,z) BitstreamPutBits(x,y,z)
+
+#include "mp4lib_int.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ BitstreamEncVideo *BitStreamCreateEnc(Int bufferSize);
+ Void BitstreamCloseEnc(BitstreamEncVideo *stream);
+ PV_STATUS BitstreamPutBits(BitstreamEncVideo *stream, Int Length, UInt Value);
+ PV_STATUS BitstreamPutGT16Bits(BitstreamEncVideo *stream, Int Length, ULong Value);
+ PV_STATUS BitstreamSaveWord(BitstreamEncVideo *stream);
+ PV_STATUS BitstreamSavePartial(BitstreamEncVideo *stream, Int *fraction);
+ Int BitstreamGetPos(BitstreamEncVideo *stream);
+ void BitstreamEncReset(BitstreamEncVideo *stream);
+
+ Int BitstreamShortHeaderByteAlignStuffing(BitstreamEncVideo *stream);
+ Int BitstreamMpeg4ByteAlignStuffing(BitstreamEncVideo *stream);
+ PV_STATUS BitstreamAppendEnc(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+ PV_STATUS BitstreamAppendPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+ PV_STATUS BitstreamAppendPacketNoOffset(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+ PV_STATUS BitstreamRepos(BitstreamEncVideo *bitstream, Int byteCount, Int bitCount);
+ PV_STATUS BitstreamFlushBits(BitstreamEncVideo *bitstream1, Int num_bit_left);
+ PV_STATUS BitstreamPrependPacket(BitstreamEncVideo *bitstream1, BitstreamEncVideo *bitstream2);
+
+
+ Void BitstreamSetOverrunBuffer(BitstreamEncVideo *stream, UChar *overrunBuffer, Int oBSize, VideoEncData *video);
+ PV_STATUS BitstreamUseOverrunBuffer(BitstreamEncVideo* stream, Int numExtraBytes);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BITSTREAM_IO_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp
new file mode 100644
index 0000000..e725680
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/combined_encode.cpp
@@ -0,0 +1,693 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "bitstream_io.h"
+#include "vlc_encode.h"
+#include "m4venc_oscl.h"
+
+PV_STATUS EncodeGOBHeader(VideoEncData *video, Int GOB_number, Int quant_scale, Int bs1stream);
+
+/* ======================================================================== */
+/* Function : EncodeFrameCombinedMode() */
+/* Date : 09/01/2000 */
+/* History : */
+/* Purpose : Encode a frame of MPEG4 bitstream in Combined mode. */
+/* In/out : */
+/* Return : PV_SUCCESS if successful else PV_FAIL */
+/* Modified : */
+/* */
+/* ======================================================================== */
+PV_STATUS EncodeFrameCombinedMode(VideoEncData *video)
+{
+ PV_STATUS status = PV_SUCCESS;
+ Vol *currVol = video->vol[video->currLayer];
+ Vop *currVop = video->currVop;
+ VideoEncParams *encParams = video->encParams;
+ Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+ Int lx = currVop->pitch; /* with padding */
+ Int offset = 0;
+ Int ind_x, ind_y;
+ Int start_packet_header = 0;
+ UChar *QPMB = video->QPMB;
+ Int QP;
+ Int mbnum = 0, slice_counter = 0, curr_slice_counter = 0;
+ Int num_bits, packet_size = encParams->ResyncPacketsize;
+ Int GOB_Header_Interval = encParams->GOB_Header_Interval;
+ BitstreamEncVideo *bs1 = video->bitstream1;
+ Int numHeaderBits;
+ approxDCT fastDCTfunction;
+ Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB, 5/18/2001 */
+ PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+ void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+ void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+
+ /* for H263 GOB changes */
+//MP4RateControlType rc_type = encParams->RC_Type;
+
+ video->QP_prev = currVop->quantizer;
+
+ numHeaderBits = BitstreamGetPos(bs1);
+
+ /* determine type of quantization */
+#ifndef NO_MPEG_QUANT
+ if (currVol->quantType == 0)
+ CodeMB = &CodeMB_H263;
+ else
+ CodeMB = &CodeMB_MPEG;
+#else
+ CodeMB = &CodeMB_H263;
+#endif
+
+ /* determine which functions to be used, in MB-level */
+ if (currVop->predictionType == P_VOP)
+ MBVlcEncode = &MBVlcEncodeCombined_P_VOP;
+ else if (currVop->predictionType == I_VOP)
+ MBVlcEncode = &MBVlcEncodeCombined_I_VOP;
+ else /* B_VOP not implemented yet */
+ return PV_FAIL;
+
+ /* determine which VLC table to be used */
+#ifndef H263_ONLY
+ if (currVol->shortVideoHeader)
+ BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#ifndef NO_RVLC
+ else if (currVol->useReverseVLC)
+ BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+#endif
+ else
+ BlockCodeCoeff = &BlockCodeCoeff_Normal;
+#else
+ BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#endif
+
+ /* gob_frame_id is the same for different vop types - the reason should be SCD */
+ if (currVol->shortVideoHeader && currVop->gobFrameID != currVop->predictionType)
+ currVop->gobFrameID = currVop->predictionType;
+
+
+ video->usePrevQP = 0;
+
+ for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++) /* Col MB Loop */
+ {
+
+ video->outputMB->mb_y = ind_y; /* 5/28/01 */
+
+ if (currVol->shortVideoHeader) /* ShortVideoHeader Mode */
+ {
+
+ if (slice_counter && GOB_Header_Interval && (ind_y % GOB_Header_Interval == 0)) /* Encode GOB Header */
+ {
+ QP = QPMB[mbnum]; /* Get quant_scale */
+ video->header_bits -= BitstreamGetPos(currVol->stream); /* Header Bits */
+ status = EncodeGOBHeader(video, slice_counter, QP, 0); //ind_y /* Encode GOB Header */
+ video->header_bits += BitstreamGetPos(currVol->stream); /* Header Bits */
+ curr_slice_counter = slice_counter;
+ }
+ }
+
+ for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++) /* Row MB Loop */
+ {
+ video->outputMB->mb_x = ind_x; /* 5/28/01 */
+ video->mbnum = mbnum;
+ QP = QPMB[mbnum]; /* always read new QP */
+
+ if (GOB_Header_Interval)
+ video->sliceNo[mbnum] = curr_slice_counter; /* Update MB slice number */
+ else
+ video->sliceNo[mbnum] = slice_counter;
+
+ /****************************************************************************************/
+ /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+ /****************************************************************************************/
+ getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+#ifndef H263_ONLY
+ if (start_packet_header)
+ {
+ slice_counter++; /* Increment slice counter */
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number*/
+ video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+ video->QP_prev = currVop->quantizer;
+ status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
+ video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+ numHeaderBits = BitstreamGetPos(bs1);
+ start_packet_header = 0;
+ video->usePrevQP = 0;
+ }
+#endif
+ /***********************************************/
+ /* Code_MB: DCT, Q, Q^(-1), IDCT, Motion Comp */
+ /***********************************************/
+
+ status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+
+ /************************************/
+ /* MB VLC Encode: VLC Encode MB */
+ /************************************/
+
+ (*MBVlcEncode)(video, ncoefblck, (void*)BlockCodeCoeff);
+
+ /*************************************************************/
+ /* Assemble Packets: Assemble the MB VLC codes into Packets */
+ /*************************************************************/
+
+ /* Assemble_Packet(video) */
+#ifndef H263_ONLY
+ if (!currVol->shortVideoHeader) /* Not in ShortVideoHeader mode */
+ {
+ if (!currVol->ResyncMarkerDisable) /* RESYNC MARKER MODE */
+ {
+ num_bits = BitstreamGetPos(bs1) - numHeaderBits;
+ if (num_bits > packet_size)
+ {
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+
+ status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+ /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+ BitstreamEncReset(bs1);
+
+ start_packet_header = 1;
+ }
+ }
+ else /* NO RESYNC MARKER MODE */
+ {
+ status = BitstreamAppendEnc(currVol->stream, bs1); /* Initialize to 0 */
+ /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+ BitstreamEncReset(bs1);
+ }
+ }
+ else
+#endif /* H263_ONLY */
+ { /* ShortVideoHeader Mode */
+ status = BitstreamAppendEnc(currVol->stream, bs1); /* Initialize to 0 */
+ /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+ BitstreamEncReset(bs1);
+ }
+ mbnum++;
+ offset += 16;
+ } /* End of For ind_x */
+
+ offset += (lx << 4) - width;
+ if (currVol->shortVideoHeader) /* ShortVideoHeader = 1 */
+ {
+
+ if (GOB_Header_Interval) slice_counter++;
+ }
+
+ } /* End of For ind_y */
+
+ if (currVol->shortVideoHeader) /* ShortVideoHeader = 1 */
+ {
+
+ video->header_bits += BitstreamShortHeaderByteAlignStuffing(currVol->stream); /* Byte Align */
+ }
+#ifndef H263_ONLY
+ else /* Combined Mode*/
+ {
+ if (!currVol->ResyncMarkerDisable) /* Resync Markers */
+ {
+
+ if (!start_packet_header)
+ {
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1);/* Byte Align */
+
+ status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+ /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+ BitstreamEncReset(bs1);
+ }
+ }
+ else /* No Resync Markers */
+ {
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(currVol->stream); /* Byte Align */
+ }
+ }
+#endif /* H263_ONLY */
+
+ return status; /* if status == PV_END_OF_BUF, this frame will be pre-skipped */
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/* Function : EncodeSliceCombinedMode() */
+/* Date : 04/19/2002 */
+/* History : */
+/* Purpose : Encode a slice of MPEG4 bitstream in Combined mode and save */
+/* the current MB to continue next time it is called. */
+/* In/out : */
+/* Return : PV_SUCCESS if successful else PV_FAIL */
+/* Modified : */
+/* */
+/* ======================================================================== */
+PV_STATUS EncodeSliceCombinedMode(VideoEncData *video)
+{
+ PV_STATUS status = PV_SUCCESS;
+ Vol *currVol = video->vol[video->currLayer];
+ Vop *currVop = video->currVop;
+ UChar mode = MODE_INTRA;
+ UChar *Mode = video->headerInfo.Mode;
+ VideoEncParams *encParams = video->encParams;
+ Int nTotalMB = currVol->nTotalMB;
+ Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+ Int lx = currVop->pitch; /* , with padding */
+// rateControl *rc = encParams->rc[video->currLayer];
+ UChar *QPMB = video->QPMB;
+ Int QP;
+ Int ind_x = video->outputMB->mb_x, ind_y = video->outputMB->mb_y;
+ Int offset = video->offset; /* get current MB location */
+ Int mbnum = video->mbnum, slice_counter = video->sliceNo[mbnum]; /* get current MB location */
+ Int firstMB = mbnum;
+ Int start_packet_header = 0;
+ Int num_bits = 0;
+ Int packet_size = encParams->ResyncPacketsize - 1;
+ Int resync_marker = ((!currVol->shortVideoHeader) && (!currVol->ResyncMarkerDisable));
+ BitstreamEncVideo *bs1 = video->bitstream1;
+ Int byteCount = 0, byteCount1 = 0, bitCount = 0;
+ Int numHeaderBits = 0;
+ approxDCT fastDCTfunction;
+ Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB, 5/18/2001 */
+ UChar CBP = 0;
+ Short outputMB[6][64];
+ Int k;
+ PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+ void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+ void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+
+ video->QP_prev = 31;
+
+#define H263_GOB_CHANGES
+
+
+ if (video->end_of_buf) /* left-over from previous run */
+ {
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+ if (status != PV_END_OF_BUF)
+ {
+ BitstreamEncReset(bs1);
+ video->end_of_buf = 0;
+ }
+ return status;
+ }
+
+
+ if (mbnum == 0) /* only do this at the start of a frame */
+ {
+ QPMB[0] = video->QP_prev = QP = currVop->quantizer;
+ video->usePrevQP = 0;
+
+ numHeaderBits = BitstreamGetPos(bs1);
+ }
+
+ /* Re-assign fast functions on every slice, don't have to put it in the memory */
+ QP = QPMB[mbnum];
+ if (mbnum > 0) video->QP_prev = QPMB[mbnum-1];
+
+ /* determine type of quantization */
+#ifndef NO_MPEG_QUANT
+ if (currVol->quantType == 0)
+ CodeMB = &CodeMB_H263;
+ else
+ CodeMB = &CodeMB_MPEG;
+#else
+ CodeMB = &CodeMB_H263;
+#endif
+
+ /* determine which functions to be used, in MB-level */
+ if (currVop->predictionType == P_VOP)
+ MBVlcEncode = &MBVlcEncodeCombined_P_VOP;
+ else if (currVop->predictionType == I_VOP)
+ MBVlcEncode = &MBVlcEncodeCombined_I_VOP;
+ else /* B_VOP not implemented yet */
+ return PV_FAIL;
+
+ /* determine which VLC table to be used */
+#ifndef H263_ONLY
+ if (currVol->shortVideoHeader)
+ BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#ifndef NO_RVLC
+ else if (currVol->useReverseVLC)
+ BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+#endif
+ else
+ BlockCodeCoeff = &BlockCodeCoeff_Normal;
+#else
+ BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#endif
+
+ /* (gob_frame_id is the same for different vop types) The reason should be SCD */
+ if (currVol->shortVideoHeader && currVop->gobFrameID != currVop->predictionType)
+ currVop->gobFrameID = currVop->predictionType;
+
+
+ if (mbnum != 0)
+ {
+ if (currVol->shortVideoHeader)
+ {
+ /* Encode GOB Header */
+ bitCount = BitstreamGetPos(bs1);
+ byteCount1 = byteCount = bitCount >> 3; /* save the position before GOB header */
+ bitCount = bitCount & 0x7;
+
+#ifdef H263_GOB_CHANGES
+ video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+ status = EncodeGOBHeader(video, slice_counter, QP, 1); //ind_y /* Encode GOB Header */
+ video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+#endif
+ goto JUMP_IN_SH;
+ }
+ else if (currVol->ResyncMarkerDisable)
+ {
+ goto JUMP_IN_SH;
+ }
+ else
+ {
+ start_packet_header = 1;
+ goto JUMP_IN;
+ }
+ }
+
+ for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++) /* Col MB Loop */
+ {
+
+ video->outputMB->mb_y = ind_y; /* 5/28/01, do not remove */
+
+ for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++) /* Row MB Loop */
+ {
+
+ video->outputMB->mb_x = ind_x; /* 5/28/01, do not remove */
+ video->mbnum = mbnum;
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number */
+JUMP_IN_SH:
+ /****************************************************************************************/
+ /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+ /****************************************************************************************/
+ getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+JUMP_IN:
+ QP = QPMB[mbnum]; /* always read new QP */
+#ifndef H263_ONLY
+ if (start_packet_header)
+ {
+ slice_counter++; /* Increment slice counter */
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number*/
+ video->QP_prev = currVop->quantizer; /* store QP */
+ num_bits = BitstreamGetPos(bs1);
+ status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 1);
+ numHeaderBits = BitstreamGetPos(bs1) - num_bits;
+ video->header_bits += numHeaderBits; /* Header Bits */
+ start_packet_header = 0;
+ video->usePrevQP = 0;
+ }
+ else /* don't encode the first MB in packet again */
+#endif /* H263_ONLY */
+ {
+ /***********************************************/
+ /* Code_MB: DCT, Q, Q^(-1), IDCT, Motion Comp */
+ /***********************************************/
+ status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+ }
+
+ /************************************/
+ /* MB VLC Encode: VLC Encode MB */
+ /************************************/
+
+ /* save the state before VLC encoding */
+ if (resync_marker)
+ {
+ bitCount = BitstreamGetPos(bs1);
+ byteCount = bitCount >> 3; /* save the state before encoding */
+ bitCount = bitCount & 0x7;
+ mode = Mode[mbnum];
+ CBP = video->headerInfo.CBP[mbnum];
+ for (k = 0; k < 6; k++)
+ {
+ M4VENC_MEMCPY(outputMB[k], video->outputMB->block[k], sizeof(Short) << 6);
+ }
+ }
+ /*************************************/
+
+ (*MBVlcEncode)(video, ncoefblck, (void*)BlockCodeCoeff);
+
+ /*************************************************************/
+ /* Assemble Packets: Assemble the MB VLC codes into Packets */
+ /*************************************************************/
+
+ /* Assemble_Packet(video) */
+#ifndef H263_ONLY
+ if (!currVol->shortVideoHeader)
+ {
+ if (!currVol->ResyncMarkerDisable)
+ {
+ /* Not in ShortVideoHeader mode and RESYNC MARKER MODE */
+
+ num_bits = BitstreamGetPos(bs1) ;//- numHeaderBits; // include header
+
+ /* Assemble packet and return when size reached */
+ if (num_bits > packet_size && mbnum != firstMB)
+ {
+
+ BitstreamRepos(bs1, byteCount, bitCount); /* rewind one MB */
+
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Put Packet to Buffer */
+
+ if (status == PV_END_OF_BUF)
+ {
+ video->end_of_buf = 1;
+ }
+ else
+ {
+ BitstreamEncReset(bs1);
+ }
+
+ start_packet_header = 1;
+
+ if (mbnum < nTotalMB || video->end_of_buf) /* return here */
+ {
+ video->mbnum = mbnum;
+ video->sliceNo[mbnum] = slice_counter;
+ video->offset = offset;
+ Mode[mbnum] = mode;
+ video->headerInfo.CBP[mbnum] = CBP;
+
+ for (k = 0; k < 6; k++)
+ {
+ M4VENC_MEMCPY(video->outputMB->block[k], outputMB[k], sizeof(Short) << 6);
+ }
+
+ return status;
+ }
+ }
+ }
+ else /* NO RESYNC MARKER , return when buffer is full*/
+ {
+
+ if (mbnum < nTotalMB - 1 && currVol->stream->byteCount + bs1->byteCount + 1 >= currVol->stream->bufferSize)
+ {
+ /* find maximum bytes to fit in the buffer */
+ byteCount = currVol->stream->bufferSize - currVol->stream->byteCount - 1;
+
+ num_bits = BitstreamGetPos(bs1) - (byteCount << 3);
+ BitstreamRepos(bs1, byteCount, 0);
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+ BitstreamFlushBits(bs1, num_bits);
+
+ /* move on to next MB */
+ mbnum++ ;
+ offset += 16;
+ video->outputMB->mb_x++;
+ if (video->outputMB->mb_x >= currVol->nMBPerRow)
+ {
+ video->outputMB->mb_x = 0;
+ video->outputMB->mb_y++;
+ offset += (lx << 4) - width;
+ }
+ video->mbnum = mbnum;
+ video->offset = offset;
+ video->sliceNo[mbnum] = slice_counter;
+ return status;
+ }
+ }
+ }
+#endif /* H263_ONLY */
+ offset += 16;
+ mbnum++; /* has to increment before SCD, to preserve Mode[mbnum] */
+
+ } /* End of For ind_x */
+
+ offset += (lx << 4) - width;
+
+ if (currVol->shortVideoHeader) /* ShortVideoHeader = 1 */
+ {
+#ifdef H263_GOB_CHANGES
+ slice_counter++;
+ video->header_bits += BitstreamShortHeaderByteAlignStuffing(bs1);
+#endif
+ //video->header_bits+=BitstreamShortHeaderByteAlignStuffing(bs1);
+
+ /* check if time to packetize */
+ if (currVol->stream->byteCount + bs1->byteCount > currVol->stream->bufferSize)
+ {
+ if (byteCount == byteCount1) /* a single GOB bigger than packet size */
+ {
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+ status = PV_END_OF_BUF;
+ video->end_of_buf = 1;
+ start_packet_header = 1;
+ }
+ else /* for short_header scooch back to previous GOB */
+ {
+ num_bits = ((bs1->byteCount - byteCount) << 3);
+ //num_bits = ((bs1->byteCount<<3) + bs1->bitCount) - ((byteCount<<3) + bitCount);
+ BitstreamRepos(bs1, byteCount, 0);
+ //BitstreamRepos(bs1,byteCount,bitCount);
+// k = currVol->stream->byteCount; /* save state before appending */
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+ BitstreamFlushBits(bs1, num_bits);
+// if(mbnum == nTotalMB || k + bs1->byteCount >= currVol->stream->bufferSize){
+ /* last GOB or current one with larger size will be returned next run */
+// status = PV_END_OF_BUF;
+// video->end_of_buf = 1;
+// }
+ start_packet_header = 1;
+ if (mbnum == nTotalMB) /* there's one more GOB to packetize for the next round */
+ {
+ status = PV_END_OF_BUF;
+ video->end_of_buf = 1;
+ }
+ }
+
+ if (mbnum < nTotalMB) /* return here */
+ {
+ /* move on to next MB */
+ video->outputMB->mb_x = 0;
+ video->outputMB->mb_y++;
+ video->mbnum = mbnum;
+ video->offset = offset;
+ video->sliceNo[mbnum] = slice_counter;
+ return status;
+ }
+ }
+ else if (mbnum < nTotalMB) /* do not write GOB header if end of vop */
+ {
+ bitCount = BitstreamGetPos(bs1);
+ byteCount = bitCount >> 3; /* save the position before GOB header */
+ bitCount = bitCount & 0x7;
+#ifdef H263_GOB_CHANGES
+ video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+ status = EncodeGOBHeader(video, slice_counter, QP, 1); /* Encode GOB Header */
+ video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+#endif
+ }
+ }
+
+ } /* End of For ind_y */
+#ifndef H263_ONLY
+ if (!currVol->shortVideoHeader) /* Combined Mode*/
+ {
+ if (!currVol->ResyncMarkerDisable) /* Resync Markers */
+ {
+
+ if (!start_packet_header)
+ {
+
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1);/* Byte Align */
+
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Put Packet to Buffer */
+ if (status == PV_END_OF_BUF)
+ {
+ video->end_of_buf = 1;
+ }
+ else
+ {
+ BitstreamEncReset(bs1);
+ }
+ }
+ }
+ else /* No Resync Markers */
+ {
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte Align */
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1); /* Initialize to 0 */
+ if (status == PV_END_OF_BUF)
+ {
+ video->end_of_buf = 1;
+ }
+ else
+ {
+ BitstreamEncReset(bs1);
+ }
+ }
+ }
+ else
+#endif /* H263_ONLY */
+ {
+ if (!start_packet_header) /* not yet packetized */
+ {
+ video->header_bits += BitstreamShortHeaderByteAlignStuffing(bs1);
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+ if (status == PV_END_OF_BUF)
+ {
+ video->end_of_buf = 1;
+ }
+ else
+ {
+ BitstreamEncReset(bs1);
+ video->end_of_buf = 0;
+ }
+ }
+ }
+
+ video->mbnum = mbnum;
+ if (mbnum < nTotalMB)
+ video->sliceNo[mbnum] = slice_counter;
+ video->offset = offset;
+
+ return status;
+}
+#endif /* NO_SLICE_ENCODE */
+
+/* ======================================================================== */
+/* Function : EncodeGOBHeader() */
+/* Date : 09/05/2000 */
+/* History : */
+/* Purpose : Encode a frame of MPEG4 bitstream in Combined mode. */
+/* In/out : */
+/* Return : PV_SUCCESS if successful else PV_FAIL */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+PV_STATUS EncodeGOBHeader(VideoEncData *video, Int GOB_number, Int quant_scale, Int bs1stream)
+{
+ PV_STATUS status = PV_SUCCESS;
+ BitstreamEncVideo *stream = (bs1stream ? video->bitstream1 : video->vol[video->currLayer]->stream);
+
+ status = BitstreamPutGT16Bits(stream, 17, GOB_RESYNC_MARKER); /* gob_resync_marker */
+ status = BitstreamPutBits(stream, 5, GOB_number); /* Current gob_number */
+ status = BitstreamPutBits(stream, 2, video->currVop->gobFrameID); /* gob_frame_id */
+ status = BitstreamPutBits(stream, 5, quant_scale); /* quant_scale */
+ return status;
+}
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp
new file mode 100644
index 0000000..16c8e79
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/datapart_encode.cpp
@@ -0,0 +1,482 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef H263_ONLY
+
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "bitstream_io.h"
+#include "mp4enc_lib.h"
+#include "m4venc_oscl.h"
+
+/* ======================================================================== */
+/* Function : EncodeFrameDataPartMode() */
+/* Date : 09/6/2000 */
+/* History : */
+/* Purpose : Encode a frame of MPEG4 bitstream in datapartitioning mode. */
+/* In/out : */
+/* Return : PV_SUCCESS if successful else PV_FAIL */
+/* Modified : */
+/* */
+/* ======================================================================== */
+PV_STATUS EncodeFrameDataPartMode(VideoEncData *video)
+{
+ PV_STATUS status = PV_SUCCESS;
+ Vol *currVol = video->vol[video->currLayer];
+ Vop *currVop = video->currVop;
+ VideoEncParams *encParams = video->encParams;
+ Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+ Int lx = currVop->pitch; /* with padding */
+ Int offset = 0;
+ Int ind_x, ind_y;
+ Int start_packet_header = 0;
+ UChar *QPMB = video->QPMB;
+ Int QP;
+ Int mbnum = 0, slice_counter = 0;
+ Int num_bits, packet_size = encParams->ResyncPacketsize;
+ BitstreamEncVideo *bs1 = video->bitstream1;
+ BitstreamEncVideo *bs2 = video->bitstream2;
+ BitstreamEncVideo *bs3 = video->bitstream3;
+ Int numHeaderBits;
+ approxDCT fastDCTfunction;
+ Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB, 5/18/2001 */
+ PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+ void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+ void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+
+ video->QP_prev = currVop->quantizer;
+
+ numHeaderBits = BitstreamGetPos(bs1); /* Number of bits in VOP Header */
+
+ /* determine type of quantization */
+#ifndef NO_MPEG_QUANT
+ if (currVol->quantType == 0)
+ CodeMB = &CodeMB_H263;
+ else
+ CodeMB = &CodeMB_MPEG;
+#else
+ CodeMB = &CodeMB_H263;
+#endif
+
+ /* determine which functions to be used, in MB-level */
+ if (currVop->predictionType == P_VOP)
+ MBVlcEncode = &MBVlcEncodeDataPar_P_VOP;
+ else if (currVop->predictionType == I_VOP)
+ MBVlcEncode = &MBVlcEncodeDataPar_I_VOP;
+ else /* B_VOP not implemented yet */
+ return PV_FAIL;
+
+ /* determine which VLC table to be used */
+ if (currVol->shortVideoHeader)
+ BlockCodeCoeff = &BlockCodeCoeff_ShortHeader;
+#ifndef NO_RVLC
+ else if (currVol->useReverseVLC)
+ BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+#endif
+ else
+ BlockCodeCoeff = &BlockCodeCoeff_Normal;
+
+ video->usePrevQP = 0;
+
+ for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++) /* Col MB Loop */
+ {
+
+ video->outputMB->mb_y = ind_y; /* 5/28/01 */
+
+ for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++) /* Row MB Loop */
+ {
+ video->outputMB->mb_x = ind_x; /* 5/28/01 */
+ video->mbnum = mbnum;
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number */
+ QP = QPMB[mbnum]; /* always read new QP */
+
+ /****************************************************************************************/
+ /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+ /****************************************************************************************/
+
+ getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+ if (start_packet_header)
+ {
+ slice_counter++; /* Increment slice counter */
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number*/
+ video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+ video->QP_prev = currVop->quantizer; /* store QP */
+ status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
+ video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+ numHeaderBits = BitstreamGetPos(bs1);
+ start_packet_header = 0;
+ video->usePrevQP = 0;
+ }
+
+ /***********************************************/
+ /* Code_MB: DCT, Q, Q^(-1), IDCT, Motion Comp */
+ /***********************************************/
+
+ status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+
+ /************************************/
+ /* MB VLC Encode: VLC Encode MB */
+ /************************************/
+
+ MBVlcEncode(video, ncoefblck, (void*)BlockCodeCoeff);
+
+ /*************************************************************/
+ /* Assemble Packets: Assemble the MB VLC codes into Packets */
+ /*************************************************************/
+
+ /* INCLUDE VOP HEADER IN COUNT */
+
+ num_bits = BitstreamGetPos(bs1) + BitstreamGetPos(bs2) +
+ BitstreamGetPos(bs3) - numHeaderBits;
+
+ /* Assemble_Packet(video) */
+
+ if (num_bits > packet_size)
+ {
+ if (video->currVop->predictionType == I_VOP)
+ BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
+ else
+ BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
+ BitstreamAppendEnc(bs1, bs2); /* Combine bs1 and bs2 */
+ BitstreamAppendEnc(bs1, bs3); /* Combine bs1 and bs3 */
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+
+ status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+ /* continue even if status == PV_END_OF_BUF, to get the stats */
+
+ BitstreamEncReset(bs1); /* Initialize to 0 */
+ BitstreamEncReset(bs2);
+ BitstreamEncReset(bs3);
+ start_packet_header = 1;
+ }
+ mbnum++;
+ offset += 16;
+ } /* End of For ind_x */
+
+ offset += (lx << 4) - width;
+ } /* End of For ind_y */
+
+ if (!start_packet_header)
+ {
+ if (video->currVop->predictionType == I_VOP)
+ {
+ BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
+ video->header_bits += 19;
+ }
+ else
+ {
+ BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /* Add motion_marker */
+ video->header_bits += 17;
+ }
+ BitstreamAppendEnc(bs1, bs2);
+ BitstreamAppendEnc(bs1, bs3);
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+ status = BitstreamAppendPacket(currVol->stream, bs1); /* Put Packet to Buffer */
+ /* continue even if status == PV_END_OF_BUF, to get the stats */
+ BitstreamEncReset(bs1); /* Initialize to 0 */
+ BitstreamEncReset(bs2);
+ BitstreamEncReset(bs3);
+ }
+
+ return status; /* if status == PV_END_OF_BUF, this frame will be pre-skipped */
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/* Function : EncodeSliceDataPartMode() */
+/* Date : 04/19/2002 */
+/* History : */
+/* Purpose : Encode a slice of MPEG4 bitstream in DataPar mode and save */
+/* the current MB to continue next time it is called. */
+/* In/out : */
+/* Return : PV_SUCCESS if successful else PV_FAIL */
+/* Modified : */
+/* */
+/* ======================================================================== */
+PV_STATUS EncodeSliceDataPartMode(VideoEncData *video)
+{
+ PV_STATUS status = PV_SUCCESS;
+ Vol *currVol = video->vol[video->currLayer];
+ Vop *currVop = video->currVop;
+ UChar mode, *Mode = video->headerInfo.Mode;
+ VideoEncParams *encParams = video->encParams;
+ Int nTotalMB = currVol->nTotalMB;
+ Int width = currVop->width; /* has to be Vop, for multiple of 16 */
+ Int lx = currVop->pitch; /* , with pading */
+ UChar *QPMB = video->QPMB;
+ Int QP;
+ Int ind_x = video->outputMB->mb_x, ind_y = video->outputMB->mb_y;
+ Int offset = video->offset; /* get current MB location */
+ Int mbnum = video->mbnum, slice_counter = video->sliceNo[mbnum]; /* get current MB location */
+ Int firstMB = mbnum;
+ Int start_packet_header = (mbnum != 0);
+ Int num_bits = 0;
+ Int packet_size = encParams->ResyncPacketsize - 1 - (currVop->predictionType == I_VOP ? 19 : 17);
+ BitstreamEncVideo *bs1 = video->bitstream1;
+ BitstreamEncVideo *bs2 = video->bitstream2;
+ BitstreamEncVideo *bs3 = video->bitstream3;
+ Int bitCount1 = 0, bitCount2 = 0, bitCount3 = 0, byteCount1 = 0, byteCount2 = 0, byteCount3 = 0;
+ Int numHeaderBits = 0;
+ approxDCT fastDCTfunction;
+ Int ncoefblck[6] = {64, 64, 64, 64, 64, 64}; /* for FastCodeMB, 5/18/2001 */
+ UChar CBP;
+ Short outputMB[6][64];
+ PV_STATUS(*CodeMB)(VideoEncData *, approxDCT *, Int, Int[]);
+ void (*MBVlcEncode)(VideoEncData*, Int[], void *);
+ void (*BlockCodeCoeff)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar);
+ Int k;
+
+ video->QP_prev = 31;
+
+ if (video->end_of_buf) /* left-over from previous run */
+ {
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+ if (status != PV_END_OF_BUF)
+ {
+ BitstreamEncReset(bs1);
+ video->end_of_buf = 0;
+ }
+ return status;
+ }
+
+ if (mbnum == 0) /* only do this at the start of a frame */
+ {
+ QPMB[0] = video->QP_prev = QP = currVop->quantizer;
+ video->usePrevQP = 0;
+
+ numHeaderBits = BitstreamGetPos(bs1); /* Number of bits in VOP Header */
+
+ }
+
+
+ /* Re-assign fast functions on every slice, don't have to put it in the memory */
+ QP = QPMB[mbnum];
+ if (mbnum > 0) video->QP_prev = QPMB[mbnum-1];
+
+ /* determine type of quantization */
+#ifndef NO_MPEG_QUANT
+ if (currVol->quantType == 0)
+ CodeMB = &CodeMB_H263;
+ else
+ CodeMB = &CodeMB_MPEG;
+#else
+ CodeMB = &CodeMB_H263;
+#endif
+
+ /* determine which functions to be used, in MB-level */
+ if (currVop->predictionType == P_VOP)
+ MBVlcEncode = &MBVlcEncodeDataPar_P_VOP;
+ else if (currVop->predictionType == I_VOP)
+ MBVlcEncode = &MBVlcEncodeDataPar_I_VOP;
+ else /* B_VOP not implemented yet */
+ return PV_FAIL;
+
+ /* determine which VLC table to be used */
+#ifndef NO_RVLC
+ if (currVol->useReverseVLC)
+ BlockCodeCoeff = &BlockCodeCoeff_RVLC;
+ else
+#endif
+ BlockCodeCoeff = &BlockCodeCoeff_Normal;
+
+ if (mbnum != 0)
+ {
+ goto JUMP_IN;
+ }
+
+ for (ind_y = 0; ind_y < currVol->nMBPerCol; ind_y++) /* Col MB Loop */
+ {
+
+ video->outputMB->mb_y = ind_y; /* 5/28/01 */
+
+ for (ind_x = 0; ind_x < currVol->nMBPerRow; ind_x++) /* Row MB Loop */
+ {
+
+ video->outputMB->mb_x = ind_x; /* 5/28/01 */
+ video->mbnum = mbnum;
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number */
+
+ /****************************************************************************************/
+ /* MB Prediction:Put into MC macroblock, substract from currVop, put in predMB */
+ /****************************************************************************************/
+ getMotionCompensatedMB(video, ind_x, ind_y, offset);
+
+JUMP_IN:
+
+ QP = QPMB[mbnum]; /* always read new QP */
+
+ if (start_packet_header)
+ {
+ slice_counter++; /* Increment slice counter */
+ video->sliceNo[mbnum] = slice_counter; /* Update MB slice number*/
+ video->QP_prev = currVop->quantizer; /* store QP */
+ num_bits = BitstreamGetPos(bs1);
+ status = EncodeVideoPacketHeader(video, mbnum, video->QP_prev, 0);
+ numHeaderBits = BitstreamGetPos(bs1) - num_bits;
+ video->header_bits += numHeaderBits; /* Header Bits */
+ start_packet_header = 0;
+ video->usePrevQP = 0;
+ }
+ else /* don't encode the first MB in packet again */
+ {
+ /***********************************************/
+ /* Code_MB: DCT, Q, Q^(-1), IDCT, Motion Comp */
+ /***********************************************/
+
+ status = (*CodeMB)(video, &fastDCTfunction, (offset << 5) + QP, ncoefblck);
+ for (k = 0; k < 6; k++)
+ {
+ M4VENC_MEMCPY(outputMB[k], video->outputMB->block[k], sizeof(Short) << 6);
+ }
+ }
+
+ /************************************/
+ /* MB VLC Encode: VLC Encode MB */
+ /************************************/
+
+ /* save the state before VLC encoding */
+ bitCount1 = BitstreamGetPos(bs1);
+ bitCount2 = BitstreamGetPos(bs2);
+ bitCount3 = BitstreamGetPos(bs3);
+ byteCount1 = bitCount1 >> 3;
+ byteCount2 = bitCount2 >> 3;
+ byteCount3 = bitCount3 >> 3;
+ bitCount1 &= 0x7;
+ bitCount2 &= 0x7;
+ bitCount3 &= 0x7;
+ mode = Mode[mbnum];
+ CBP = video->headerInfo.CBP[mbnum];
+
+ /*************************************/
+
+ MBVlcEncode(video, ncoefblck, (void*)BlockCodeCoeff);
+
+ /*************************************************************/
+ /* Assemble Packets: Assemble the MB VLC codes into Packets */
+ /*************************************************************/
+
+ num_bits = BitstreamGetPos(bs1) + BitstreamGetPos(bs2) +
+ BitstreamGetPos(bs3);// - numHeaderBits; //include header bits
+
+ /* Assemble_Packet(video) */
+ if (num_bits > packet_size && mbnum != firstMB) /* encoding at least one more MB*/
+ {
+
+ BitstreamRepos(bs1, byteCount1, bitCount1); /* rewind one MB */
+ BitstreamRepos(bs2, byteCount2, bitCount2); /* rewind one MB */
+ BitstreamRepos(bs3, byteCount3, bitCount3); /* rewind one MB */
+
+ if (video->currVop->predictionType == I_VOP)
+ {
+ BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
+ video->header_bits += 19;
+ }
+ else
+ {
+ BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
+ video->header_bits += 17;
+ }
+
+ status = BitstreamAppendEnc(bs1, bs2); /* Combine with bs2 */
+ status = BitstreamAppendEnc(bs1, bs3); /* Combine with bs3 */
+
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+
+ BitstreamEncReset(bs2);
+ BitstreamEncReset(bs3);
+
+ if (status == PV_END_OF_BUF) /* if cannot fit a buffer */
+ {
+ video->end_of_buf = 1;
+ }
+ else
+ {
+ BitstreamEncReset(bs1);
+ }
+
+ start_packet_header = 1;
+
+ if (mbnum < nTotalMB || video->end_of_buf) /* return here */
+ {
+ video->mbnum = mbnum;
+ video->sliceNo[mbnum] = slice_counter;
+ video->offset = offset;
+ Mode[mbnum] = mode;
+ video->headerInfo.CBP[mbnum] = CBP;
+
+ for (k = 0; k < 6; k++)
+ {
+ M4VENC_MEMCPY(video->outputMB->block[k], outputMB[k], sizeof(Short) << 6);
+ }
+
+ return status;
+ }
+ }
+
+ offset += 16;
+ mbnum++; /* has to increment before SCD, to preserve Mode[mbnum] */
+ } /* End of For ind_x */
+
+ offset += (lx << 4) - width;
+
+ } /* End of For ind_y */
+
+ if (!start_packet_header)
+ {
+ if (video->currVop->predictionType == I_VOP)
+ {
+ BitstreamPutGT16Bits(bs1, 19, DC_MARKER); /* Add dc_marker */
+ video->header_bits += 19;
+ }
+ else
+ {
+ BitstreamPutGT16Bits(bs1, 17, MOTION_MARKER_COMB); /*Add motion_marker*/
+ video->header_bits += 17;
+ }
+
+ status = BitstreamAppendEnc(bs1, bs2); /* Combine with bs2 */
+ status = BitstreamAppendEnc(bs1, bs3); /* Combine with bs3 */
+
+ video->header_bits += BitstreamMpeg4ByteAlignStuffing(bs1); /* Byte align Packet */
+ status = BitstreamAppendPacketNoOffset(currVol->stream, bs1);
+
+ BitstreamEncReset(bs2);
+ BitstreamEncReset(bs3);
+
+ if (status == PV_END_OF_BUF)
+ {
+ video->end_of_buf = 1;
+ }
+ else
+ {
+ BitstreamEncReset(bs1);
+ }
+ }
+
+ video->mbnum = mbnum;
+ if (mbnum < nTotalMB)
+ video->sliceNo[mbnum] = slice_counter;
+ video->offset = offset;
+
+ return status;
+}
+#endif /* NO_SLICE_ENCODE */
+#endif /* H263_ONLY */
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
new file mode 100644
index 0000000..fa50eeb
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.cpp
@@ -0,0 +1,1283 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "dct_inline.h"
+
+#define FDCT_SHIFT 10
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /**************************************************************************/
+ /* Function: BlockDCT_AANwSub
+ Date: 7/31/01
+ Input:
+ Output: out[64] ==> next block
+ Purpose: Do subtraction for zero MV first
+ Modified:
+ **************************************************************************/
+
+ Void BlockDCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
+ {
+ Short *dst;
+ Int k0, k1, k2, k3, k4, k5, k6, k7;
+ Int round;
+ Int k12 = 0x022A02D4;
+ Int k14 = 0x0188053A;
+ Int abs_sum;
+ Int mask;
+ Int tmp, tmp2;
+ Int ColTh;
+
+ dst = out + 64 ;
+ ColTh = *dst;
+ out += 128;
+ round = 1 << (FDCT_SHIFT - 1);
+
+ do /* fdct_nextrow */
+ {
+ /* assuming the block is word-aligned */
+ mask = 0x1FE;
+ tmp = *((Int*) cur); /* contains 4 pixels */
+ tmp2 = *((Int*) pred); /* prediction 4 pixels */
+ k0 = tmp2 & 0xFF;
+ k1 = mask & (tmp << 1);
+ k0 = k1 - (k0 << 1);
+ k1 = (tmp2 >> 8) & 0xFF;
+ k2 = mask & (tmp >> 7);
+ k1 = k2 - (k1 << 1);
+ k2 = (tmp2 >> 16) & 0xFF;
+ k3 = mask & (tmp >> 15);
+ k2 = k3 - (k2 << 1);
+ k3 = (tmp2 >> 24) & 0xFF;
+ k4 = mask & (tmp >> 23);
+ k3 = k4 - (k3 << 1);
+ tmp = *((Int*)(cur + 4)); /* another 4 pixels */
+ tmp2 = *((Int*)(pred + 4));
+ k4 = tmp2 & 0xFF;
+ k5 = mask & (tmp << 1);
+ k4 = k5 - (k4 << 1);
+ k5 = (tmp2 >> 8) & 0xFF;
+ k6 = mask & (tmp >> 7);
+ k5 = k6 - (k5 << 1);
+ k6 = (tmp2 >> 16) & 0xFF;
+ k7 = mask & (tmp >> 15);
+ k6 = k7 - (k6 << 1);
+ k7 = (tmp2 >> 24) & 0xFF;
+ tmp = mask & (tmp >> 23);
+ k7 = tmp - (k7 << 1);
+ cur += width;
+ pred += 16;
+
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ k1 = k0 - (k1 << 1);
+ /**********/
+ dst[0] = k0;
+ dst[4] = k1; /* col. 4 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ k3 = (k3 << 1) - k2;
+ /********/
+ dst[2] = k2; /* col. 2 */
+ k3 <<= 1; /* scale up col. 6 */
+ dst[6] = k3; /* col. 6 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k4 = k4 + k7;
+ k7 = (k7 << 1) - k4;
+ k5 = k5 + k6;
+ k4 <<= 1; /* scale up col.5 */
+ k6 = k5 - (k6 << 1);
+ /********/
+ dst[5] = k4; /* col. 5 */
+ k6 <<= 2; /* scale up col. 7 */
+ dst[1] = k5; /* col. 1 */
+ dst[7] = k6; /* col. 7 */
+ dst[3] = k7; /* col. 3 */
+ dst += 8;
+ }
+ while (dst < out);
+
+ out -= 64;
+ dst = out + 8;
+
+ /* Vertical Block Loop */
+ do /* Vertical 8xDCT loop */
+ {
+ k0 = out[0];
+ k1 = out[8];
+ k2 = out[16];
+ k3 = out[24];
+ k4 = out[32];
+ k5 = out[40];
+ k6 = out[48];
+ k7 = out[56];
+ /* deadzone thresholding for column */
+
+ abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+ if (abs_sum < ColTh)
+ {
+ out[0] = 0x7fff;
+ out++;
+ continue;
+ }
+
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ k1 = k0 - (k1 << 1);
+ /**********/
+ out[32] = k1; /* row 4 */
+ out[0] = k0; /* row 0 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ k3 = (k3 << 1) - k2;
+ k3 <<= 1; /* scale up col. 6 */
+ /********/
+ out[48] = k3; /* row 6 */
+ out[16] = k2; /* row 2 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k4 = k4 + k7;
+ k7 = (k7 << 1) - k4;
+ k5 = k5 + k6;
+ k4 <<= 1; /* scale up col. 5 */
+ k6 = k5 - (k6 << 1);
+ /********/
+ out[24] = k7 ; /* row 3 */
+ k6 <<= 2; /* scale up col. 7 */
+ out[56] = k6 ; /* row 7 */
+ out[8] = k5 ; /* row 1 */
+ out[40] = k4 ; /* row 5 */
+ out++;
+ }
+ while ((UInt)out < (UInt)dst) ;
+
+ return ;
+ }
+
+ /**************************************************************************/
+ /* Function: Block4x4DCT_AANwSub
+ Date: 7/31/01
+ Input:
+ Output: out[64] ==> next block
+ Purpose: Do subtraction for zero MV first before 4x4 DCT
+ Modified:
+ **************************************************************************/
+
+ Void Block4x4DCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
+ {
+ Short *dst;
+ register Int k0, k1, k2, k3, k4, k5, k6, k7;
+ Int round;
+ Int k12 = 0x022A02D4;
+ Int k14 = 0x0188053A;
+ Int mask;
+ Int tmp, tmp2;
+ Int abs_sum;
+ Int ColTh;
+
+ dst = out + 64 ;
+ ColTh = *dst;
+ out += 128;
+ round = 1 << (FDCT_SHIFT - 1);
+
+ do /* fdct_nextrow */
+ {
+ /* assuming the block is word-aligned */
+ mask = 0x1FE;
+ tmp = *((Int*) cur); /* contains 4 pixels */
+ tmp2 = *((Int*) pred); /* prediction 4 pixels */
+ k0 = tmp2 & 0xFF;
+ k1 = mask & (tmp << 1);
+ k0 = k1 - (k0 << 1);
+ k1 = (tmp2 >> 8) & 0xFF;
+ k2 = mask & (tmp >> 7);
+ k1 = k2 - (k1 << 1);
+ k2 = (tmp2 >> 16) & 0xFF;
+ k3 = mask & (tmp >> 15);
+ k2 = k3 - (k2 << 1);
+ k3 = (tmp2 >> 24) & 0xFF;
+ k4 = mask & (tmp >> 23);
+ k3 = k4 - (k3 << 1);
+ tmp = *((Int*)(cur + 4)); /* another 4 pixels */
+ tmp2 = *((Int*)(pred + 4));
+ k4 = tmp2 & 0xFF;
+ k5 = mask & (tmp << 1);
+ k4 = k5 - (k4 << 1);
+ k5 = (tmp2 >> 8) & 0xFF;
+ k6 = mask & (tmp >> 7);
+ k5 = k6 - (k5 << 1);
+ k6 = (tmp2 >> 16) & 0xFF;
+ k7 = mask & (tmp >> 15);
+ k6 = k7 - (k6 << 1);
+ k7 = (tmp2 >> 24) & 0xFF;
+ tmp = mask & (tmp >> 23);
+ k7 = tmp - (k7 << 1);
+ cur += width;
+ pred += 16;
+
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ dst[0] = k0;
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ /********/
+ dst[2] = k2; /* col. 2 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k7 = k7 - k4;
+ k5 = k5 + k6;
+ /********/
+ dst[1] = k5; /* col. 1 */
+ dst[3] = k7; /* col. 3 */
+ dst += 8;
+ }
+ while (dst < out);
+
+ out -= 64;
+ dst = out + 4;
+
+ /* Vertical Block Loop */
+ do /* Vertical 8xDCT loop */
+ {
+ k0 = out[0];
+ k1 = out[8];
+ k2 = out[16];
+ k3 = out[24];
+ k4 = out[32];
+ k5 = out[40];
+ k6 = out[48];
+ k7 = out[56];
+
+ abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+ if (abs_sum < ColTh)
+ {
+ out[0] = 0x7fff;
+ out++;
+ continue;
+ }
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ out[0] = k0; /* row 0 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ /********/
+ out[16] = k2; /* row 2 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k7 = k7 - k4 ;
+ k5 = k5 + k6;
+ /********/
+ out[24] = k7 ; /* row 3 */
+ out[8] = k5 ; /* row 1 */
+ out++;
+ }
+ while ((UInt)out < (UInt)dst) ;
+
+ return ;
+ }
+
+ /**************************************************************************/
+ /* Function: Block2x2DCT_AANwSub
+ Date: 7/31/01
+ Input:
+ Output: out[64] ==> next block
+ Purpose: Do subtraction for zero MV first before 2x2 DCT
+ Modified:
+ **************************************************************************/
+
+
+ Void Block2x2DCT_AANwSub(Short *out, UChar *cur, UChar *pred, Int width)
+ {
+ Short *dst;
+ register Int k0, k1, k2, k3, k4, k5, k6, k7;
+ Int round;
+ Int k12 = 0x022A02D4;
+ Int k14 = 0x018803B2;
+ Int mask;
+ Int tmp, tmp2;
+ Int abs_sum;
+ Int ColTh;
+
+ dst = out + 64 ;
+ ColTh = *dst;
+ out += 128;
+ round = 1 << (FDCT_SHIFT - 1);
+
+ do /* fdct_nextrow */
+ {
+ /* assuming the block is word-aligned */
+ mask = 0x1FE;
+ tmp = *((Int*) cur); /* contains 4 pixels */
+ tmp2 = *((Int*) pred); /* prediction 4 pixels */
+ k0 = tmp2 & 0xFF;
+ k1 = mask & (tmp << 1);
+ k0 = k1 - (k0 << 1);
+ k1 = (tmp2 >> 8) & 0xFF;
+ k2 = mask & (tmp >> 7);
+ k1 = k2 - (k1 << 1);
+ k2 = (tmp2 >> 16) & 0xFF;
+ k3 = mask & (tmp >> 15);
+ k2 = k3 - (k2 << 1);
+ k3 = (tmp2 >> 24) & 0xFF;
+ k4 = mask & (tmp >> 23);
+ k3 = k4 - (k3 << 1);
+ tmp = *((Int*)(cur + 4)); /* another 4 pixels */
+ tmp2 = *((Int*)(pred + 4));
+ k4 = tmp2 & 0xFF;
+ k5 = mask & (tmp << 1);
+ k4 = k5 - (k4 << 1);
+ k5 = (tmp2 >> 8) & 0xFF;
+ k6 = mask & (tmp >> 7);
+ k5 = k6 - (k5 << 1);
+ k6 = (tmp2 >> 16) & 0xFF;
+ k7 = mask & (tmp >> 15);
+ k6 = k7 - (k6 << 1);
+ k7 = (tmp2 >> 24) & 0xFF;
+ tmp = mask & (tmp >> 23);
+ k7 = tmp - (k7 << 1);
+ cur += width;
+ pred += 16;
+
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ dst[0] = k0;
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ /*****************/
+ /********/
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k1 = mla392(k4, k14, round);
+ k1 = mla946(k6, k14, k1);
+
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k5 = k5 + k6;
+ /********/
+ dst[1] = k5;
+ dst += 8;
+ }
+ while (dst < out);
+ out -= 64;
+ dst = out + 2;
+ /* Vertical Block Loop */
+ do /* Vertical 8xDCT loop */
+ {
+ k0 = out[0];
+ k1 = out[8];
+ k2 = out[16];
+ k3 = out[24];
+ k4 = out[32];
+ k5 = out[40];
+ k6 = out[48];
+ k7 = out[56];
+
+ abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+ if (abs_sum < ColTh)
+ {
+ out[0] = 0x7fff;
+ out++;
+ continue;
+ }
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ out[0] = k0; /* row 0 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ /*****************/
+ /********/
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k1 = mla392(k4, k14, round);
+ k1 = mla946(k6, k14, k1);
+
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k5 = k5 + k6;
+ /********/
+ out[8] = k5 ; /* row 1 */
+ out++;
+ }
+ while ((UInt)out < (UInt)dst) ;
+
+ return ;
+ }
+
+ /**************************************************************************/
+ /* Function: BlockDCT_AANIntra
+ Date: 8/9/01
+ Input: rec
+ Output: out[64] ==> next block
+ Purpose: Input directly from rec frame.
+ Modified:
+ **************************************************************************/
+
+ Void BlockDCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+ {
+ Short *dst;
+ Int k0, k1, k2, k3, k4, k5, k6, k7;
+ Int round;
+ Int k12 = 0x022A02D4;
+ Int k14 = 0x0188053A;
+ Int abs_sum;
+ Int mask;
+ Int *curInt, tmp;
+ Int ColTh;
+
+ OSCL_UNUSED_ARG(dummy2);
+
+ dst = out + 64 ;
+ ColTh = *dst;
+ out += 128;
+ round = 1 << (FDCT_SHIFT - 1);
+
+ do /* fdct_nextrow */
+ {
+ mask = 0x1FE;
+ curInt = (Int*) cur;
+ tmp = curInt[0]; /* contains 4 pixels */
+ k0 = mask & (tmp << 1);
+ k1 = mask & (tmp >> 7);
+ k2 = mask & (tmp >> 15);
+ k3 = mask & (tmp >> 23);
+ tmp = curInt[1]; /* another 4 pixels */
+ k4 = mask & (tmp << 1);
+ k5 = mask & (tmp >> 7);
+ k6 = mask & (tmp >> 15);
+ k7 = mask & (tmp >> 23);
+ cur += width;
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ k1 = k0 - (k1 << 1);
+ /**********/
+ dst[0] = k0;
+ dst[4] = k1; /* col. 4 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ k3 = (k3 << 1) - k2;
+ /********/
+ dst[2] = k2; /* col. 2 */
+ k3 <<= 1; /* scale up col. 6 */
+ dst[6] = k3; /* col. 6 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k4 = k4 + k7;
+ k7 = (k7 << 1) - k4;
+ k5 = k5 + k6;
+ k4 <<= 1; /* scale up col.5 */
+ k6 = k5 - (k6 << 1);
+ /********/
+ dst[5] = k4; /* col. 5 */
+ k6 <<= 2; /* scale up col. 7 */
+ dst[1] = k5; /* col. 1 */
+ dst[7] = k6; /* col. 7 */
+ dst[3] = k7; /* col. 3 */
+ dst += 8;
+ }
+ while (dst < out);
+
+ out -= 64;
+ dst = out + 8;
+
+ /* Vertical Block Loop */
+ do /* Vertical 8xDCT loop */
+ {
+ k0 = out[0];
+ k1 = out[8];
+ k2 = out[16];
+ k3 = out[24];
+ k4 = out[32];
+ k5 = out[40];
+ k6 = out[48];
+ k7 = out[56];
+ /* deadzone thresholding for column */
+
+ abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+ if (abs_sum < ColTh)
+ {
+ out[0] = 0x7fff;
+ out++;
+ continue;
+ }
+
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ k1 = k0 - (k1 << 1);
+ /**********/
+ out[32] = k1; /* row 4 */
+ out[0] = k0; /* row 0 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ k3 = (k3 << 1) - k2;
+ k3 <<= 1; /* scale up col. 6 */
+ /********/
+ out[48] = k3; /* row 6 */
+ out[16] = k2; /* row 2 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k4 = k4 + k7;
+ k7 = (k7 << 1) - k4;
+ k5 = k5 + k6;
+ k4 <<= 1; /* scale up col. 5 */
+ k6 = k5 - (k6 << 1);
+ /********/
+ out[24] = k7 ; /* row 3 */
+ k6 <<= 2; /* scale up col. 7 */
+ out[56] = k6 ; /* row 7 */
+ out[8] = k5 ; /* row 1 */
+ out[40] = k4 ; /* row 5 */
+ out++;
+ }
+ while ((UInt)out < (UInt)dst) ;
+
+ return ;
+ }
+
+ /**************************************************************************/
+ /* Function: Block4x4DCT_AANIntra
+ Date: 8/9/01
+ Input: prev
+ Output: out[64] ==> next block
+ Purpose: Input directly from prev frame. output 2x2 DCT
+ Modified:
+ **************************************************************************/
+
+ Void Block4x4DCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+ {
+ Short *dst;
+ register Int k0, k1, k2, k3, k4, k5, k6, k7;
+ Int round;
+ Int k12 = 0x022A02D4;
+ Int k14 = 0x0188053A;
+ Int mask;
+ Int *curInt, tmp;
+ Int abs_sum;
+ Int ColTh;
+
+ OSCL_UNUSED_ARG(dummy2);
+
+ dst = out + 64 ;
+ ColTh = *dst;
+ out += 128;
+ round = 1 << (FDCT_SHIFT - 1);
+
+ do /* fdct_nextrow */
+ {
+ mask = 0x1FE;
+ curInt = (Int*) cur;
+ tmp = curInt[0]; /* contains 4 pixels */
+ k0 = mask & (tmp << 1);
+ k1 = mask & (tmp >> 7);
+ k2 = mask & (tmp >> 15);
+ k3 = mask & (tmp >> 23);
+ tmp = curInt[1]; /* another 4 pixels */
+ k4 = mask & (tmp << 1);
+ k5 = mask & (tmp >> 7);
+ k6 = mask & (tmp >> 15);
+ k7 = mask & (tmp >> 23);
+ cur += width;
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ dst[0] = k0;
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ /********/
+ dst[2] = k2; /* col. 2 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k7 = k7 - k4;
+ k5 = k5 + k6;
+ /********/
+ dst[1] = k5; /* col. 1 */
+ dst[3] = k7; /* col. 3 */
+ dst += 8;
+ }
+ while (dst < out);
+
+ out -= 64;
+ dst = out + 4;
+
+ /* Vertical Block Loop */
+ do /* Vertical 8xDCT loop */
+ {
+ k0 = out[0];
+ k1 = out[8];
+ k2 = out[16];
+ k3 = out[24];
+ k4 = out[32];
+ k5 = out[40];
+ k6 = out[48];
+ k7 = out[56];
+
+ abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+ if (abs_sum < ColTh)
+ {
+ out[0] = 0x7fff;
+ out++;
+ continue;
+ }
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ out[0] = k0; /* row 0 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ k2 = k2 + k3;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+ k0 = mla724(k12, k2, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ k2 = k0 >> FDCT_SHIFT;
+ /*****************/
+ k2 = k2 + k3;
+ /********/
+ out[16] = k2; /* row 2 */
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k0 = k4 - k6;
+
+ k1 = mla392(k0, k14, round);
+ k0 = mla554(k4, k12, k1);
+ k1 = mla1338(k6, k14, k1);
+
+ k4 = k0 >> FDCT_SHIFT;
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k7 = (k7 << 1) - k5;
+ k7 = k7 - k4 ;
+ k5 = k5 + k6;
+ /********/
+ out[24] = k7 ; /* row 3 */
+ out[8] = k5 ; /* row 1 */
+ out++;
+ }
+ while ((UInt)out < (UInt)dst) ;
+
+ return ;
+ }
+
+ /**************************************************************************/
+ /* Function: Block2x2DCT_AANIntra
+ Date: 8/9/01
+ Input: prev
+ Output: out[64] ==> next block
+ Purpose: Input directly from prev frame. output 2x2 DCT
+ Modified:
+ **************************************************************************/
+
+ Void Block2x2DCT_AANIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+ {
+ Short *dst;
+ register Int k0, k1, k2, k3, k4, k5, k6, k7;
+ Int round;
+ Int k12 = 0x022A02D4;
+ Int k14 = 0x018803B2;
+ Int mask;
+ Int *curInt, tmp;
+ Int abs_sum;
+ Int ColTh;
+
+ OSCL_UNUSED_ARG(dummy2);
+
+ dst = out + 64 ;
+ ColTh = *dst;
+ out += 128;
+ round = 1 << (FDCT_SHIFT - 1);
+
+ do /* fdct_nextrow */
+ {
+ mask = 0x1FE;
+ curInt = (Int*) cur;
+ tmp = curInt[0]; /* contains 4 pixels */
+ k0 = mask & (tmp << 1);
+ k1 = mask & (tmp >> 7);
+ k2 = mask & (tmp >> 15);
+ k3 = mask & (tmp >> 23);
+ tmp = curInt[1]; /* another 4 pixels */
+ k4 = mask & (tmp << 1);
+ k5 = mask & (tmp >> 7);
+ k6 = mask & (tmp >> 15);
+ k7 = mask & (tmp >> 23);
+ cur += width;
+
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ dst[0] = k0;
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ /*****************/
+ /********/
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k1 = mla392(k4, k14, round);
+ k1 = mla946(k6, k14, k1);
+
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k5 = k5 + k6;
+ /********/
+ dst[1] = k5;
+ dst += 8;
+ }
+ while (dst < out);
+ out -= 64;
+ dst = out + 2;
+ /* Vertical Block Loop */
+ do /* Vertical 8xDCT loop */
+ {
+ k0 = out[0];
+ k1 = out[8];
+ k2 = out[16];
+ k3 = out[24];
+ k4 = out[32];
+ k5 = out[40];
+ k6 = out[48];
+ k7 = out[56];
+
+ abs_sum = sum_abs(k0, k1, k2, k3, k4, k5, k6, k7);
+
+ if (abs_sum < ColTh)
+ {
+ out[0] = 0x7fff;
+ out++;
+ continue;
+ }
+ /* fdct_1 */
+ k0 = k0 + k7;
+ k7 = k0 - (k7 << 1);
+ k1 = k1 + k6;
+ k6 = k1 - (k6 << 1);
+ k2 = k2 + k5;
+ k5 = k2 - (k5 << 1);
+ k3 = k3 + k4;
+ k4 = k3 - (k4 << 1);
+
+ k0 = k0 + k3;
+ k3 = k0 - (k3 << 1);
+ k1 = k1 + k2;
+ k2 = k1 - (k2 << 1);
+
+ k0 = k0 + k1;
+ /**********/
+ out[0] = k0; /* row 0 */
+ /* fdct_2 */
+ k4 = k4 + k5;
+ k5 = k5 + k6;
+ k6 = k6 + k7;
+ /* MUL2C k2,k5,724,FDCT_SHIFT */
+ /* k0, k1 become scratch */
+ /* assume FAST MULTIPLY */
+ k1 = mla724(k12, k5, round);
+
+ k5 = k1 >> FDCT_SHIFT;
+ /*****************/
+ /********/
+ /* fdct_3 */
+ /* ROTATE k4,k6,392,946, FDCT_SHIFT */
+ /* assume FAST MULTIPLY */
+ /* k0, k1 are output */
+ k1 = mla392(k4, k14, round);
+ k1 = mla946(k6, k14, k1);
+
+ k6 = k1 >> FDCT_SHIFT;
+ /***********************/
+ k5 = k5 + k7;
+ k5 = k5 + k6;
+ /********/
+ out[8] = k5 ; /* row 1 */
+ out++;
+ }
+ while ((UInt)out < (UInt)dst) ;
+
+ return ;
+ }
+ /**************************************************************************/
+ /* Function: Block1x1DCTwSub
+ Date: 8/9/01
+ Input: block
+ Output: y
+ Purpose: Compute DC value only
+ Modified:
+ **************************************************************************/
+ void Block1x1DCTwSub(Short *out, UChar *cur, UChar *pred, Int width)
+ {
+ UChar *end;
+ Int temp = 0;
+ Int offset2;
+
+ offset2 = width - 8;
+ end = pred + (16 << 3);
+ do
+ {
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ temp += (*cur++ - *pred++);
+ cur += offset2;
+ pred += 8;
+ }
+ while (pred < end) ;
+
+ out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0;
+ out[0] = temp >> 3;
+
+ return ;
+ }
+
+ /**************************************************************************/
+ /* Function: Block1x1DCTIntra
+ Date: 8/9/01
+ Input: prev
+ Output: out
+ Purpose: Compute DC value only
+ Modified:
+ **************************************************************************/
+ void Block1x1DCTIntra(Short *out, UChar *cur, UChar *dummy2, Int width)
+ {
+ UChar *end;
+ Int temp = 0;
+ ULong word;
+
+ OSCL_UNUSED_ARG(dummy2);
+
+ end = cur + (width << 3);
+ do
+ {
+ word = *((ULong*)cur);
+ temp += (word >> 24);
+ temp += ((word >> 16) & 0xFF);
+ temp += ((word >> 8) & 0xFF);
+ temp += (word & 0xFF);
+
+ word = *((ULong*)(cur + 4));
+ temp += (word >> 24);
+ temp += ((word >> 16) & 0xFF);
+ temp += ((word >> 8) & 0xFF);
+ temp += (word & 0xFF);
+
+ cur += width;
+ }
+ while (cur < end) ;
+
+ out[1] = out[2] = out[3] = out[4] = out[5] = out[6] = out[7] = 0;
+ out[0] = temp >> 3;
+
+ return ;
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct.h b/media/libstagefright/codecs/m4v_h263/enc/src/dct.h
new file mode 100644
index 0000000..3dceb66
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct.h
@@ -0,0 +1,191 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _DCT_H_
+#define _DCT_H_
+
+const static Int ColThInter[32] = {0, 0x1C, 0x4C, 0x6C, 0x9C, 0xBC, 0xEC, 0x10C,
+ 0x13C, 0x15C, 0x18C, 0x1AC, 0x1DC, 0x1FC, 0x22C, 0x24C,
+ 0x27C, 0x29C, 0x2CC, 0x2EC, 0x31C, 0x33C, 0x36C, 0x38C,
+ 0x3BC, 0x3DC, 0x40C, 0x42C, 0x45C, 0x47C, 0x4AC, 0x4CC
+ };
+
+const static Int ColThIntra[32] = {0, 0x1C, 0x3C, 0x5C, 0x7C, 0x9C, 0xBC, 0xDC,
+ 0xFC, 0x11C, 0x13C, 0x15C, 0x17C, 0x19C, 0x1BC, 0x1DC,
+ 0x1FC, 0x21C, 0x23C, 0x25C, 0x27C, 0x29C, 0x2BC, 0x2DC,
+ 0x2FC, 0x31C, 0x33C, 0x35C, 0x37C, 0x39C, 0x3BC, 0x3DC
+ };
+
+/******************************************************/
+/********** IDCT part **************************/
+const static unsigned char imask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+const static unsigned char mask[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe};
+
+#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
+#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
+#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
+#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
+#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
+#define W7 565 /* 2048*sqrt(2)*cos(7*pi/16) */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* Reduced input IDCT */
+ void idct_col0(Short *blk);
+ void idct_col1(Short *blk);
+ void idct_col2(Short *blk);
+ void idct_col3(Short *blk);
+ void idct_col4(Short *blk);
+ void idct_col0x40(Short *blk);
+ void idct_col0x20(Short *blk);
+ void idct_col0x10(Short *blk);
+
+ void idct_rowInter(Short *srce, UChar *rec, Int lx);
+ void idct_row0Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row1Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row2Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row3Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row4Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row0x40Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row0x20Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row0x10Inter(Short *blk, UChar *rec, Int lx);
+ void idct_row0xCCInter(Short *blk, UChar *rec, Int lx);
+ void idct_rowIntra(Short *srce, UChar *rec, Int lx);
+ void idct_row0Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row1Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row2Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row3Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row4Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row0x40Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row0x20Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row0x10Intra(Short *blk, UChar *rec, Int lx);
+ void idct_row0xCCIntra(Short *blk, UChar *rec, Int lx);
+ void idct_rowzmv(Short *srce, UChar *rec, UChar *prev, Int lx);
+ void idct_row0zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row1zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row2zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row3zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row4zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row0x40zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row0x20zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row0x10zmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+ void idct_row0xCCzmv(Short *blk, UChar *rec, UChar *prev, Int lx);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Look-up table mapping to RIDCT from bitmap */
+#ifdef SMALL_DCT
+
+static void (*const idctcolVCA[16])(Short*) =
+{
+ &idct_col0, &idct_col4, &idct_col3, &idct_col4,
+ &idct_col2, &idct_col4, &idct_col3, &idct_col4,
+ &idct_col1, &idct_col4, &idct_col3, &idct_col4,
+ &idct_col2, &idct_col4, &idct_col3, &idct_col4
+};
+
+static void (*const idctrowVCAInter[16])(Short*, UChar*, Int) =
+{
+ &idct_row0Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+ &idct_row2Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+ &idct_row1Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+ &idct_row2Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter
+};
+
+static void (*const idctrowVCAzmv[16])(Short*, UChar*, UChar*, Int) =
+{
+ &idct_row0zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+ &idct_row2zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+ &idct_row1zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+ &idct_row2zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv
+};
+
+
+static void (*const idctrowVCAIntra[16])(Short*, UChar*, Int) =
+{
+ &idct_row0Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+ &idct_row2Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+ &idct_row1Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+ &idct_row2Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra
+};
+
+#else /* SMALL_DCT */
+
+static void (*const idctcolVCA[16])(Short*) =
+{
+ &idct_col0, &idct_col0x10, &idct_col0x20, &idct_col4,
+ &idct_col0x40, &idct_col4, &idct_col3, &idct_col4,
+ &idct_col1, &idct_col4, &idct_col3, &idct_col4,
+ &idct_col2, &idct_col4, &idct_col3, &idct_col4
+};
+
+static void (*const idctrowVCAInter[16])(Short*, UChar*, Int) =
+{
+ &idct_row0Inter, &idct_row0x10Inter, &idct_row0x20Inter, &idct_row4Inter,
+ &idct_row0x40Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+ &idct_row1Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter,
+ &idct_row2Inter, &idct_row4Inter, &idct_row3Inter, &idct_row4Inter
+};
+
+static void (*const idctrowVCAzmv[16])(Short*, UChar*, UChar*, Int) =
+{
+ &idct_row0zmv, &idct_row0x10zmv, &idct_row0x20zmv, &idct_row4zmv,
+ &idct_row0x40zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+ &idct_row1zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv,
+ &idct_row2zmv, &idct_row4zmv, &idct_row3zmv, &idct_row4zmv
+};
+
+static void (*const idctrowVCAIntra[16])(Short*, UChar*, Int) =
+{
+ &idct_row0Intra, &idct_row0x10Intra, &idct_row0x20Intra, &idct_row4Intra,
+ &idct_row0x40Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+ &idct_row1Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra,
+ &idct_row2Intra, &idct_row4Intra, &idct_row3Intra, &idct_row4Intra
+};
+
+#endif /* SMALL_DCT */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /* part in AppVCA_dct.c */
+//void Block1x1DCTzmv (Short *out,UChar *prev,UChar *cur,UChar *rec,Int lx,Int chroma);
+ void Block1x1DCTwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+ void Block1x1DCTIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+ /* This part is in dct_aan.c */
+ Void BlockDCT_AANwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+ Void Block4x4DCT_AANwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+ Void Block2x2DCT_AANwSub(Short *out, UChar *cur, UChar *prev, Int pitch_chroma);
+//Void BlockDCT_AANzmv(Short *out,UChar *prev,UChar *cur,UChar *rec,Int ColTh,Int lx,Int chroma);
+//Void Block4x4DCT_AANzmv(Short *out,UChar *prev,UChar *cur,UChar *rec,Int ColTh,Int lx,Int chroma);
+//Void Block2x2DCT_AANzmv(Short *out,UChar *prev,UChar *cur,UChar *rec,Int ColTh,Int lx,Int chroma);
+ Void BlockDCT_AANIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+ Void Block4x4DCT_AANIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+ Void Block2x2DCT_AANIntra(Short *out, UChar *cur, UChar *dummy1, Int pitch_chroma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_DCT_H_
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h
new file mode 100644
index 0000000..f795bd9
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/dct_inline.h
@@ -0,0 +1,395 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/* Filename: dct_inline.h */
+/* Description: Implementation for in-line functions used in dct.cpp */
+/* Modified: */
+/*********************************************************************************/
+#ifndef _DCT_INLINE_H_
+#define _DCT_INLINE_H_
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4)
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+ int32 out;
+
+ OSCL_UNUSED_ARG(op1);
+
+ out = op2 * 724 + op3; /* op1 is not used here */
+
+ return out;
+}
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+ int32 k1;
+
+ OSCL_UNUSED_ARG(k14);
+
+ k1 = k0 * 392 + round;
+
+ return k1;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+ int32 k0;
+
+ OSCL_UNUSED_ARG(k12);
+
+ k0 = k4 * 554 + k1;
+
+ return k0;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+ int32 out;
+
+ OSCL_UNUSED_ARG(k14);
+
+ out = k6 * 1338 + k1;
+
+ return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+ int32 out;
+
+ OSCL_UNUSED_ARG(k14);
+
+ out = k6 * 946 + k1;
+
+ return out;
+}
+
+__inline int32 sum_abs(int32 k0, int32 k1, int32 k2, int32 k3,
+ int32 k4, int32 k5, int32 k6, int32 k7)
+{
+ int32 carry, abs_sum;
+
+ carry = k0 >> 31;
+ abs_sum = (k0 ^ carry);
+ carry = k1 >> 31;
+ abs_sum += (k1 ^ carry) - carry;
+ carry = k2 >> 31;
+ abs_sum += (k2 ^ carry) - carry;
+ carry = k3 >> 31;
+ abs_sum += (k3 ^ carry) - carry;
+ carry = k4 >> 31;
+ abs_sum += (k4 ^ carry) - carry;
+ carry = k5 >> 31;
+ abs_sum += (k5 ^ carry) - carry;
+ carry = k6 >> 31;
+ abs_sum += (k6 ^ carry) - carry;
+ carry = k7 >> 31;
+ abs_sum += (k7 ^ carry) - carry;
+
+ return abs_sum;
+}
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+#if defined(__TARGET_ARCH_5TE)
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+ int32 out;
+
+ __asm
+ {
+ smlabb out, op1, op2, op3
+ }
+
+ return out;
+}
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+ int32 k1;
+
+ __asm
+ {
+ smlabt k1, k0, k14, round
+ }
+
+ return k1;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+ int32 k0;
+
+ __asm
+ {
+ smlabt k0, k4, k12, k1
+ }
+
+ return k0;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+ int32 out;
+
+ __asm
+ {
+ smlabb out, k6, k14, k1
+ }
+
+ return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+ int32 out;
+
+ __asm
+ {
+ smlabb out, k6, k14, k1
+ }
+
+ return out;
+}
+
+#else // not ARM5TE
+
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+ int32 out;
+
+ __asm
+ {
+ and out, op2, #0xFFFF
+ mla out, op1, out, op3
+ }
+
+ return out;
+}
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+ int32 k1;
+
+ __asm
+ {
+ mov k1, k14, asr #16
+ mla k1, k0, k1, round
+ }
+
+ return k1;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+ int32 k0;
+
+ __asm
+ {
+ mov k0, k12, asr #16
+ mla k0, k4, k0, k1
+ }
+
+ return k0;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+ int32 out;
+
+ __asm
+ {
+ and out, k14, 0xFFFF
+ mla out, k6, out, k1
+ }
+
+ return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+ int32 out;
+
+ __asm
+ {
+ and out, k14, 0xFFFF
+ mla out, k6, out, k1
+ }
+
+ return out;
+}
+
+#endif
+
+__inline int32 sum_abs(int32 k0, int32 k1, int32 k2, int32 k3,
+ int32 k4, int32 k5, int32 k6, int32 k7)
+{
+ int32 carry, abs_sum;
+ __asm
+ {
+ eor carry, k0, k0, asr #31 ;
+ eors abs_sum, k1, k1, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ eors carry, k2, k2, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ eors carry, k3, k3, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ eors carry, k4, k4, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ eors carry, k5, k5, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ eors carry, k6, k6, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ eors carry, k7, k7, asr #31 ;
+ adc abs_sum, abs_sum, carry ;
+ }
+
+ return abs_sum;
+}
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER */
+
+__inline int32 mla724(int32 op1, int32 op2, int32 op3)
+{
+ register int32 out;
+ register int32 aa = (int32)op1;
+ register int32 bb = (int32)op2;
+ register int32 cc = (int32)op3;
+
+ asm volatile("smlabb %0, %1, %2, %3"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb),
+ "r"(cc));
+ return out;
+}
+
+
+__inline int32 mla392(int32 k0, int32 k14, int32 round)
+{
+ register int32 out;
+ register int32 aa = (int32)k0;
+ register int32 bb = (int32)k14;
+ register int32 cc = (int32)round;
+
+ asm volatile("smlabt %0, %1, %2, %3"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb),
+ "r"(cc));
+
+ return out;
+}
+
+__inline int32 mla554(int32 k4, int32 k12, int32 k1)
+{
+ register int32 out;
+ register int32 aa = (int32)k4;
+ register int32 bb = (int32)k12;
+ register int32 cc = (int32)k1;
+
+ asm volatile("smlabt %0, %1, %2, %3"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb),
+ "r"(cc));
+
+ return out;
+}
+
+__inline int32 mla1338(int32 k6, int32 k14, int32 k1)
+{
+ register int32 out;
+ register int32 aa = (int32)k6;
+ register int32 bb = (int32)k14;
+ register int32 cc = (int32)k1;
+
+ asm volatile("smlabb %0, %1, %2, %3"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb),
+ "r"(cc));
+ return out;
+}
+
+__inline int32 mla946(int32 k6, int32 k14, int32 k1)
+{
+ register int32 out;
+ register int32 aa = (int32)k6;
+ register int32 bb = (int32)k14;
+ register int32 cc = (int32)k1;
+
+ asm volatile("smlabb %0, %1, %2, %3"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb),
+ "r"(cc));
+ return out;
+}
+
+__inline int32 sum_abs(int32 k0, int32 k1, int32 k2, int32 k3,
+ int32 k4, int32 k5, int32 k6, int32 k7)
+{
+ register int32 carry;
+ register int32 abs_sum;
+ register int32 aa = (int32)k0;
+ register int32 bb = (int32)k1;
+ register int32 cc = (int32)k2;
+ register int32 dd = (int32)k3;
+ register int32 ee = (int32)k4;
+ register int32 ff = (int32)k5;
+ register int32 gg = (int32)k6;
+ register int32 hh = (int32)k7;
+
+ asm volatile("eor %0, %2, %2, asr #31\n\t"
+ "eors %1, %3, %3, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+ "eors %0, %4, %4, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+ "eors %0, %5, %5, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+ "eors %0, %6, %6, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+ "eors %0, %7, %7, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+ "eors %0, %8, %8, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+ "eors %0, %9, %9, asr #31\n\t"
+ "adc %1, %1, %0\n\t"
+
+ : "=&r"(carry),
+ "=&r"(abs_sum):
+ "r"(aa),
+ "r"(bb),
+ "r"(cc),
+ "r"(dd),
+ "r"(ee),
+ "r"(ff),
+ "r"(gg),
+ "r"(hh));
+
+ return abs_sum;
+}
+
+#endif // Diff. OS
+
+#endif //_DCT_INLINE_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp
new file mode 100644
index 0000000..6fd41c3
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.cpp
@@ -0,0 +1,622 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+#include "dct.h"
+#include "m4venc_oscl.h"
+
+/* ======================================================================== */
+/* Function : CodeMB_H263( ) */
+/* Date : 8/15/2001 */
+/* Purpose : Perform residue calc (only zero MV), DCT, H263 Quant/Dequant,*/
+/* IDCT and motion compensation.Modified from FastCodeMB() */
+/* Input : */
+/* video Video encoder data structure */
+/* function Approximate DCT function, scaling and threshold */
+/* ncoefblck Array for last nonzero coeff for speedup in VlcEncode */
+/* QP Combined offset from the origin to the current */
+/* macroblock and QP for current MB. */
+/* Output : */
+/* video->outputMB Quantized DCT coefficients. */
+/* currVop->yChan,uChan,vChan Reconstructed pixels */
+/* */
+/* Return : PV_STATUS */
+/* Modified : */
+/* 2/26/01
+ -modified threshold based on correlation coeff 0.75 only for mode H.263
+ -ncoefblck[] as input, to keep position of last non-zero coeff*/
+/* 8/10/01
+ -modified threshold based on correlation coeff 0.5
+ -used column threshold to speedup column DCT.
+ -used bitmap zigzag to speedup RunLevel(). */
+/* ======================================================================== */
+
+PV_STATUS CodeMB_H263(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[])
+{
+ Int sad, k, CBP, mbnum = video->mbnum;
+ Short *output, *dataBlock;
+ UChar Mode = video->headerInfo.Mode[mbnum];
+ UChar *bitmapcol, *bitmaprow = video->bitmaprow;
+ UInt *bitmapzz ;
+ UChar shortHeader = video->vol[video->currLayer]->shortVideoHeader;
+ Int dc_scaler = 8;
+ Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+ struct QPstruct QuantParam;
+ Int dctMode, DctTh1;
+ Int ColTh;
+ Int(*BlockQuantDequantH263)(Short *, Short *, struct QPstruct *,
+ UChar[], UChar *, UInt *, Int, Int, Int, UChar);
+ Int(*BlockQuantDequantH263DC)(Short *, Short *, struct QPstruct *,
+ UChar *, UInt *, Int, UChar);
+ void (*BlockDCT1x1)(Short *, UChar *, UChar *, Int);
+ void (*BlockDCT2x2)(Short *, UChar *, UChar *, Int);
+ void (*BlockDCT4x4)(Short *, UChar *, UChar *, Int);
+ void (*BlockDCT8x8)(Short *, UChar *, UChar *, Int);
+
+ /* motion comp. related var. */
+ Vop *currVop = video->currVop;
+ VideoEncFrameIO *inputFrame = video->input;
+ Int ind_x = video->outputMB->mb_x;
+ Int ind_y = video->outputMB->mb_y;
+ Int lx = currVop->pitch;
+ Int width = currVop->width;
+ UChar *rec, *input, *pred;
+ Int offset = QP >> 5; /* QP is combined offset and QP */
+ Int offsetc = (offset >> 2) + (ind_x << 2); /* offset for chrom */
+ /*****************************/
+
+ OSCL_UNUSED_ARG(function);
+
+ output = video->outputMB->block[0];
+ CBP = 0;
+ QP = QP & 0x1F;
+// M4VENC_MEMSET(output,0,(sizeof(Short)<<6)*6); /* reset quantized coeff. to zero , 7/24/01*/
+
+ QuantParam.QPx2 = QP << 1;
+ QuantParam.QP = QP;
+ QuantParam.QPdiv2 = QP >> 1;
+ QuantParam.QPx2plus = QuantParam.QPx2 + QuantParam.QPdiv2;
+ QuantParam.Addition = QP - 1 + (QP & 0x1);
+
+ if (intra)
+ {
+ BlockDCT1x1 = &Block1x1DCTIntra;
+ BlockDCT2x2 = &Block2x2DCT_AANIntra;
+ BlockDCT4x4 = &Block4x4DCT_AANIntra;
+ BlockDCT8x8 = &BlockDCT_AANIntra;
+ BlockQuantDequantH263 = &BlockQuantDequantH263Intra;
+ BlockQuantDequantH263DC = &BlockQuantDequantH263DCIntra;
+ if (shortHeader)
+ {
+ dc_scaler = 8;
+ }
+ else
+ {
+ dc_scaler = cal_dc_scalerENC(QP, 1); /* luminance blocks */
+ }
+ DctTh1 = (Int)(dc_scaler * 3);//*1.829
+ ColTh = ColThIntra[QP];
+ }
+ else
+ {
+ BlockDCT1x1 = &Block1x1DCTwSub;
+ BlockDCT2x2 = &Block2x2DCT_AANwSub;
+ BlockDCT4x4 = &Block4x4DCT_AANwSub;
+ BlockDCT8x8 = &BlockDCT_AANwSub;
+
+ BlockQuantDequantH263 = &BlockQuantDequantH263Inter;
+ BlockQuantDequantH263DC = &BlockQuantDequantH263DCInter;
+ ColTh = ColThInter[QP];
+ DctTh1 = (Int)(16 * QP); //9*QP;
+ }
+
+ rec = currVop->yChan + offset;
+ input = inputFrame->yChan + offset;
+ if (lx != width) input -= (ind_y << 9); /* non-padded offset */
+
+ dataBlock = video->dataBlock;
+ pred = video->predictedMB;
+
+ for (k = 0; k < 6; k++)
+ {
+ CBP <<= 1;
+ bitmapcol = video->bitmapcol[k];
+ bitmapzz = video->bitmapzz[k]; /* 7/30/01 */
+ if (k < 4)
+ {
+ sad = video->mot[mbnum][k+1].sad;
+ if (k&1)
+ {
+ rec += 8;
+ input += 8;
+ }
+ else if (k == 2)
+ {
+ dctMode = ((width << 3) - 8);
+ input += dctMode;
+ dctMode = ((lx << 3) - 8);
+ rec += dctMode;
+ }
+ }
+ else
+ {
+ if (k == 4)
+ {
+ rec = currVop->uChan + offsetc;
+ input = inputFrame->uChan + offsetc;
+ if (lx != width) input -= (ind_y << 7);
+ lx >>= 1;
+ width >>= 1;
+ if (intra)
+ {
+ sad = getBlockSum(input, width);
+ if (shortHeader)
+ dc_scaler = 8;
+ else
+ {
+ dc_scaler = cal_dc_scalerENC(QP, 2); /* chrominance blocks */
+ }
+ DctTh1 = (Int)(dc_scaler * 3);//*1.829
+ }
+ else
+ sad = Sad8x8(input, pred, width);
+ }
+ else
+ {
+ rec = currVop->vChan + offsetc;
+ input = inputFrame->vChan + offsetc;
+ if (lx != width) input -= (ind_y << 7);
+ if (intra)
+ {
+ sad = getBlockSum(input, width);
+ }
+ else
+ sad = Sad8x8(input, pred, width);
+ }
+ }
+
+ if (sad < DctTh1 && !(shortHeader && intra)) /* all-zero */
+ { /* For shortHeader intra block, DC value cannot be zero */
+ dctMode = 0;
+ CBP |= 0;
+ ncoefblck[k] = 0;
+ }
+ else if (sad < 18*QP/*(QP<<4)*/) /* DC-only */
+ {
+ dctMode = 1;
+ BlockDCT1x1(dataBlock, input, pred, width);
+
+ CBP |= (*BlockQuantDequantH263DC)(dataBlock, output, &QuantParam,
+ bitmaprow + k, bitmapzz, dc_scaler, shortHeader);
+ ncoefblck[k] = 1;
+ }
+ else
+ {
+
+ dataBlock[64] = ColTh;
+
+ if (sad < 22*QP/*(QP<<4)+(QP<<1)*/) /* 2x2 DCT */
+ {
+ dctMode = 2;
+ BlockDCT2x2(dataBlock, input, pred, width);
+ ncoefblck[k] = 6;
+ }
+ else if (sad < (QP << 5)) /* 4x4 DCT */
+ {
+ dctMode = 4;
+ BlockDCT4x4(dataBlock, input, pred, width);
+ ncoefblck[k] = 26;
+ }
+ else /* Full-DCT */
+ {
+ dctMode = 8;
+ BlockDCT8x8(dataBlock, input, pred, width);
+ ncoefblck[k] = 64;
+ }
+
+ CBP |= (*BlockQuantDequantH263)(dataBlock, output, &QuantParam,
+ bitmapcol, bitmaprow + k, bitmapzz, dctMode, k, dc_scaler, shortHeader);
+ }
+ BlockIDCTMotionComp(dataBlock, bitmapcol, bitmaprow[k], dctMode, rec, pred, (lx << 1) | intra);
+ output += 64;
+ if (!(k&1))
+ {
+ pred += 8;
+ }
+ else
+ {
+ pred += 120;
+ }
+ }
+
+ video->headerInfo.CBP[mbnum] = CBP; /* 5/18/2001 */
+ return PV_SUCCESS;
+}
+
+#ifndef NO_MPEG_QUANT
+/* ======================================================================== */
+/* Function : CodeMB_MPEG( ) */
+/* Date : 8/15/2001 */
+/* Purpose : Perform residue calc (only zero MV), DCT, MPEG Quant/Dequant,*/
+/* IDCT and motion compensation.Modified from FastCodeMB() */
+/* Input : */
+/* video Video encoder data structure */
+/* function Approximate DCT function, scaling and threshold */
+/* ncoefblck Array for last nonzero coeff for speedup in VlcEncode */
+/* QP Combined offset from the origin to the current */
+/* macroblock and QP for current MB. */
+/* Output : */
+/* video->outputMB Quantized DCT coefficients. */
+/* currVop->yChan,uChan,vChan Reconstructed pixels */
+/* */
+/* Return : PV_STATUS */
+/* Modified : */
+/* 2/26/01
+ -modified threshold based on correlation coeff 0.75 only for mode H.263
+ -ncoefblck[] as input, keep position of last non-zero coeff*/
+/* 8/10/01
+ -modified threshold based on correlation coeff 0.5
+ -used column threshold to speedup column DCT.
+ -used bitmap zigzag to speedup RunLevel(). */
+/* ======================================================================== */
+
+PV_STATUS CodeMB_MPEG(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[])
+{
+ Int sad, k, CBP, mbnum = video->mbnum;
+ Short *output, *dataBlock;
+ UChar Mode = video->headerInfo.Mode[mbnum];
+ UChar *bitmapcol, *bitmaprow = video->bitmaprow;
+ UInt *bitmapzz ;
+ Int dc_scaler = 8;
+ Vol *currVol = video->vol[video->currLayer];
+ Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+ Int *qmat;
+ Int dctMode, DctTh1, DctTh2, DctTh3, DctTh4;
+ Int ColTh;
+
+ Int(*BlockQuantDequantMPEG)(Short *, Short *, Int, Int *,
+ UChar [], UChar *, UInt *, Int, Int, Int);
+ Int(*BlockQuantDequantMPEGDC)(Short *, Short *, Int, Int *,
+ UChar [], UChar *, UInt *, Int);
+
+ void (*BlockDCT1x1)(Short *, UChar *, UChar *, Int);
+ void (*BlockDCT2x2)(Short *, UChar *, UChar *, Int);
+ void (*BlockDCT4x4)(Short *, UChar *, UChar *, Int);
+ void (*BlockDCT8x8)(Short *, UChar *, UChar *, Int);
+
+ /* motion comp. related var. */
+ Vop *currVop = video->currVop;
+ VideoEncFrameIO *inputFrame = video->input;
+ Int ind_x = video->outputMB->mb_x;
+ Int ind_y = video->outputMB->mb_y;
+ Int lx = currVop->pitch;
+ Int width = currVop->width;
+ UChar *rec, *input, *pred;
+ Int offset = QP >> 5;
+ Int offsetc = (offset >> 2) + (ind_x << 2); /* offset for chrom */
+ /*****************************/
+
+ OSCL_UNUSED_ARG(function);
+
+ output = video->outputMB->block[0];
+ CBP = 0;
+ QP = QP & 0x1F;
+// M4VENC_MEMSET(output,0,(sizeof(Short)<<6)*6); /* reset quantized coeff. to zero , 7/24/01*/
+
+ if (intra)
+ {
+ BlockDCT1x1 = &Block1x1DCTIntra;
+ BlockDCT2x2 = &Block2x2DCT_AANIntra;
+ BlockDCT4x4 = &Block4x4DCT_AANIntra;
+ BlockDCT8x8 = &BlockDCT_AANIntra;
+
+ BlockQuantDequantMPEG = &BlockQuantDequantMPEGIntra;
+ BlockQuantDequantMPEGDC = &BlockQuantDequantMPEGDCIntra;
+ dc_scaler = cal_dc_scalerENC(QP, 1); /* luminance blocks */
+ qmat = currVol->iqmat;
+ DctTh1 = (Int)(3 * dc_scaler);//2*dc_scaler);
+ DctTh2 = (Int)((1.25 * QP - 1) * qmat[1] * 0.45);//0.567);//0.567);
+ DctTh3 = (Int)((1.25 * QP - 1) * qmat[2] * 0.55);//1.162); /* 8/2/2001 */
+ DctTh4 = (Int)((1.25 * QP - 1) * qmat[32] * 0.8);//1.7583);//0.7942);
+ ColTh = ColThIntra[QP];
+ }
+ else
+ {
+ BlockDCT1x1 = &Block1x1DCTwSub;
+ BlockDCT2x2 = &Block2x2DCT_AANwSub;
+ BlockDCT4x4 = &Block4x4DCT_AANwSub;
+ BlockDCT8x8 = &BlockDCT_AANwSub;
+
+ BlockQuantDequantMPEG = &BlockQuantDequantMPEGInter;
+ BlockQuantDequantMPEGDC = &BlockQuantDequantMPEGDCInter;
+ qmat = currVol->niqmat;
+ DctTh1 = (Int)(((QP << 1) - 0.5) * qmat[0] * 0.4);//0.2286);//0.3062);
+ DctTh2 = (Int)(((QP << 1) - 0.5) * qmat[1] * 0.45);//0.567);//0.4);
+ DctTh3 = (Int)(((QP << 1) - 0.5) * qmat[2] * 0.55);//1.162); /* 8/2/2001 */
+ DctTh4 = (Int)(((QP << 1) - 0.5) * qmat[32] * 0.8);//1.7583);//0.7942);
+ ColTh = ColThInter[QP];
+ }// get qmat, DctTh1, DctTh2, DctTh3
+
+ rec = currVop->yChan + offset;
+ input = inputFrame->yChan + offset;
+ if (lx != width) input -= (ind_y << 9); /* non-padded offset */
+
+ dataBlock = video->dataBlock;
+ pred = video->predictedMB;
+
+ for (k = 0; k < 6; k++)
+ {
+ CBP <<= 1;
+ bitmapcol = video->bitmapcol[k];
+ bitmapzz = video->bitmapzz[k]; /* 8/2/01 */
+ if (k < 4)
+ {//Y block
+ sad = video->mot[mbnum][k+1].sad;
+ if (k&1)
+ {
+ rec += 8;
+ input += 8;
+ }
+ else if (k == 2)
+ {
+ dctMode = ((width << 3) - 8);
+ input += dctMode;
+ dctMode = ((lx << 3) - 8);
+ rec += dctMode;
+ }
+ }
+ else
+ {// U, V block
+ if (k == 4)
+ {
+ rec = currVop->uChan + offsetc;
+ input = inputFrame->uChan + offsetc;
+ if (lx != width) input -= (ind_y << 7);
+ lx >>= 1;
+ width >>= 1;
+ if (intra)
+ {
+ dc_scaler = cal_dc_scalerENC(QP, 2); /* luminance blocks */
+ DctTh1 = dc_scaler * 3;
+ sad = getBlockSum(input, width);
+ }
+ else
+ sad = Sad8x8(input, pred, width);
+ }
+ else
+ {
+ rec = currVop->vChan + offsetc;
+ input = inputFrame->vChan + offsetc;
+ if (lx != width) input -= (ind_y << 7);
+ if (intra)
+ sad = getBlockSum(input, width);
+ else
+ sad = Sad8x8(input, pred, width);
+ }
+ }
+
+ if (sad < DctTh1) /* all-zero */
+ {
+ dctMode = 0;
+ CBP |= 0;
+ ncoefblck[k] = 0;
+ }
+ else if (sad < DctTh2) /* DC-only */
+ {
+ dctMode = 1;
+ BlockDCT1x1(dataBlock, input, pred, width);
+
+ CBP |= (*BlockQuantDequantMPEGDC)(dataBlock, output, QP, qmat,
+ bitmapcol, bitmaprow + k, bitmapzz, dc_scaler);
+ ncoefblck[k] = 1;
+ }
+ else
+ {
+ dataBlock[64] = ColTh;
+
+ if (sad < DctTh3) /* 2x2-DCT */
+ {
+ dctMode = 2;
+ BlockDCT2x2(dataBlock, input, pred, width);
+ ncoefblck[k] = 6;
+ }
+ else if (sad < DctTh4) /* 4x4 DCT */
+ {
+ dctMode = 4;
+ BlockDCT4x4(dataBlock, input, pred, width);
+ ncoefblck[k] = 26;
+ }
+ else /* full-DCT */
+ {
+ dctMode = 8;
+ BlockDCT8x8(dataBlock, input, pred, width);
+ ncoefblck[k] = 64;
+ }
+
+ CBP |= (*BlockQuantDequantMPEG)(dataBlock, output, QP, qmat,
+ bitmapcol, bitmaprow + k, bitmapzz, dctMode, k, dc_scaler); //
+ }
+ dctMode = 8; /* for mismatch handle */
+ BlockIDCTMotionComp(dataBlock, bitmapcol, bitmaprow[k], dctMode, rec, pred, (lx << 1) | (intra));
+
+ output += 64;
+ if (!(k&1))
+ {
+ pred += 8;
+ }
+ else
+ {
+ pred += 120;
+ }
+ }
+
+ video->headerInfo.CBP[mbnum] = CBP; /* 5/18/2001 */
+ return PV_SUCCESS;
+}
+
+#endif
+
+/* ======================================================================== */
+/* Function : getBlockSAV( ) */
+/* Date : 8/10/2000 */
+/* Purpose : Get SAV for one block */
+/* In/out : block[64] contain one block data */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+/* can be written in MMX or SSE, 2/22/2001 */
+Int getBlockSAV(Short block[])
+{
+ Int i, val, sav = 0;
+
+ i = 8;
+ while (i--)
+ {
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ val = *block++;
+ if (val > 0) sav += val;
+ else sav -= val;
+ }
+
+ return sav;
+
+}
+
+/* ======================================================================== */
+/* Function : Sad8x8( ) */
+/* Date : 8/10/2000 */
+/* Purpose : Find SAD between prev block and current block */
+/* In/out : Previous and current frame block pointers, and frame width */
+/* Return : */
+/* Modified : */
+/* 8/15/01, - do 4 pixel at a time assuming 32 bit register */
+/* ======================================================================== */
+Int Sad8x8(UChar *cur, UChar *prev, Int width)
+{
+ UChar *end = cur + (width << 3);
+ Int sad = 0;
+ Int *curInt = (Int*) cur;
+ Int *prevInt = (Int*) prev;
+ Int cur1, cur2, prev1, prev2;
+ UInt mask, sgn_msk = 0x80808080;
+ Int sum2 = 0, sum4 = 0;
+ Int tmp;
+ do
+ {
+ mask = ~(0xFF00);
+ cur1 = curInt[1]; /* load cur[4..7] */
+ cur2 = curInt[0];
+ curInt += (width >> 2); /* load cur[0..3] and +=lx */
+ prev1 = prevInt[1];
+ prev2 = prevInt[0];
+ prevInt += 4;
+
+ tmp = prev2 ^ cur2;
+ cur2 = prev2 - cur2;
+ tmp = tmp ^ cur2; /* (^)^(-) last bit is one if carry */
+ tmp = sgn_msk & ((UInt)tmp >> 1); /* check the sign of each byte */
+ if (cur2 < 0) tmp = tmp | 0x80000000; /* corcurt sign of first byte */
+ tmp = (tmp << 8) - tmp; /* carry borrowed bytes are marked with 0x1FE */
+ cur2 = cur2 + (tmp >> 7); /* negative bytes is added with 0xFF, -1 */
+ cur2 = cur2 ^(tmp >> 7); /* take absolute by inverting bits (EOR) */
+
+ tmp = prev1 ^ cur1;
+ cur1 = prev1 - cur1;
+ tmp = tmp ^ cur1; /* (^)^(-) last bit is one if carry */
+ tmp = sgn_msk & ((UInt)tmp >> 1); /* check the sign of each byte */
+ if (cur1 < 0) tmp = tmp | 0x80000000; /* corcurt sign of first byte */
+ tmp = (tmp << 8) - tmp; /* carry borrowed bytes are marked with 0x1FE */
+ cur1 = cur1 + (tmp >> 7); /* negative bytes is added with 0xFF, -1 */
+ cur1 = cur1 ^(tmp >> 7); /* take absolute by inverting bits (EOR) */
+
+ sum4 = sum4 + cur1;
+ cur1 = cur1 & (mask << 8); /* mask first and third bytes */
+ sum2 = sum2 + ((UInt)cur1 >> 8);
+ sum4 = sum4 + cur2;
+ cur2 = cur2 & (mask << 8); /* mask first and third bytes */
+ sum2 = sum2 + ((UInt)cur2 >> 8);
+ }
+ while ((UInt)curInt < (UInt)end);
+
+ cur1 = sum4 - (sum2 << 8); /* get even-sum */
+ cur1 = cur1 + sum2; /* add 16 bit even-sum and odd-sum*/
+ cur1 = cur1 + (cur1 << 16); /* add upper and lower 16 bit sum */
+ sad = ((UInt)cur1 >> 16); /* take upper 16 bit */
+ return sad;
+}
+
+/* ======================================================================== */
+/* Function : getBlockSum( ) */
+/* Date : 8/10/2000 */
+/* Purpose : Find summation of value within a block. */
+/* In/out : Pointer to current block in a frame and frame width */
+/* Return : */
+/* Modified : */
+/* 8/15/01, - SIMD 4 pixels at a time */
+/* ======================================================================== */
+
+Int getBlockSum(UChar *cur, Int width)
+{
+ Int sad = 0, sum4 = 0, sum2 = 0;
+ UChar *end = cur + (width << 3);
+ Int *curInt = (Int*)cur;
+ UInt mask = ~(0xFF00);
+ Int load1, load2;
+
+ do
+ {
+ load1 = curInt[1];
+ load2 = curInt[0];
+ curInt += (width >> 2);
+ sum4 += load1;
+ load1 = load1 & (mask << 8); /* even bytes */
+ sum2 += ((UInt)load1 >> 8); /* sum even bytes, 16 bit */
+ sum4 += load2;
+ load2 = load2 & (mask << 8); /* even bytes */
+ sum2 += ((UInt)load2 >> 8); /* sum even bytes, 16 bit */
+ }
+ while ((UInt)curInt < (UInt)end);
+ load1 = sum4 - (sum2 << 8); /* get even-sum */
+ load1 = load1 + sum2; /* add 16 bit even-sum and odd-sum*/
+ load1 = load1 + (load1 << 16); /* add upper and lower 16 bit sum */
+ sad = ((UInt)load1 >> 16); /* take upper 16 bit */
+
+ return sad;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h
new file mode 100644
index 0000000..686a66d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastcodemb.h
@@ -0,0 +1,103 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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: FastCodeMB.h */
+/* Description: This file contains structure and function prototypes used
+ in FastCodeMB() function. When it is decided to use FastCodeMB
+ instead of CodeMB, all of this prototypes should be migrated to
+ mp4enc_lib.h. */
+/* Rev: */
+/* Created: 8/14/01 */
+/* //////////////////////////////////////////////////////////////////////// */
+
+typedef struct struct_approxDCT approxDCT;
+struct struct_approxDCT
+{
+ const Int *scale;
+ Int(*DCT)(Int block[ ], Int coeff[ ], approxDCT *);
+
+ // Threshold value for H.263 Quantizer
+ Int th_app_all[8];
+ Int th_app_odd[8];
+ Int th_app_even[8];
+ Int th_app_even1[8];
+ Int th_app_even2[8];
+};
+
+struct QPstruct
+{
+ Int QPx2 ;
+ Int QP;
+ Int QPdiv2;
+ Int QPx2plus;
+ Int Addition;
+};
+
+/*---- FastCodeMB.c -----*/
+void initCodeMB(approxDCT *function, Int QP);
+PV_STATUS CodeMB_H263(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[], Int offset);
+PV_STATUS CodeMB_MPEG(VideoEncData *video, approxDCT *function, Int QP, Int ncoefblck[], Int offset);
+Int getBlockSAV(Int block[]);
+Int Sad8x8(UChar *rec, UChar *prev, Int lx);
+Int getBlockSum(UChar *rec, Int lx);
+
+/*---- AppVCA_dct.c -----*/
+Int AppVCA1_dct(Int block[], Int out[ ], approxDCT *function);
+Int AppVCA2_dct(Int block[], Int out[ ], approxDCT *function);
+Int AppVCA3_dct(Int block[], Int out[ ], approxDCT *function);
+Int AppVCA4_dct(Int block[], Int out[ ], approxDCT *function);
+Int AppVCA5_dct(Int block[], Int out[ ], approxDCT *function);
+
+/*---- FastQuant.c -----*/
+Int cal_dc_scalerENC(Int QP, Int type) ;
+Int BlockQuantDequantH263Inter(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dummy);
+
+Int BlockQuantDequantH263Intra(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dc_scaler);
+
+Int BlockQuantDequantH263DCInter(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+ UChar *bitmaprow, UInt *bitmapzz, Int dummy);
+
+Int BlockQuantDequantH263DCIntra(Int *rcoeff, Int *qcoeff, struct QPstruct *QuantParam,
+ UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler);
+
+Int BlockQuantDequantMPEGInter(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int DctMode, Int comp, Int dc_scaler);
+
+Int BlockQuantDequantMPEGIntra(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int DctMode, Int comp, Int dc_scaler);
+
+Int BlockQuantDequantMPEGDCInter(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dummy);
+
+Int BlockQuantDequantMPEGDCIntra(Int *rcoeff, Int *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler);
+
+/*---- FastIDCT.c -----*/
+void BlockIDCTMotionComp(Int *block, UChar *bitmapcol, UChar bitmaprow,
+ Int dctMode, UChar *rec, Int lx, Int intra);
+
+/*---- motion_comp.c -----*/
+void PutSkippedBlock(UChar *rec, UChar *prev, Int lx);
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp
new file mode 100644
index 0000000..21d7427
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastidct.cpp
@@ -0,0 +1,2020 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*
+
+------------------------------------------------------------------------------
+ REVISION HISTORY
+ Who: Date: July/2001
+ Description: 1. Optimized BlockIDCT bitmap checking.
+ 2. Rearranged functions.
+ 3. Do column IDCT first, then row IDCT.
+ 4. Combine motion comp and IDCT, require
+ two sets of row IDCTs one for INTRA
+ and one for INTER.
+ 5. Add AAN IDCT
+
+ Who: Date: 8/16/01
+ 1. Increase the input precision to 8 bits, i.e. change RDCTBITS
+ to 11, have to comment out all in-line assembly since 16 bit
+ multiplication doesn't work. Try to use diffent precision with
+ 32 bit mult. but hasn't finished. Turns out that without in-line
+ assembly the performance doesn't change much (only 1%).
+ Who: Date: 9/04/05
+ 1. Replace AAN IDCT with Chen's IDCT to accommodate 16 bit data type.
+
+*/
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "dct.h"
+
+#define ADD_CLIP { \
+ tmp = *rec + tmp; \
+ if((UInt)tmp > mask) tmp = mask&(~(tmp>>31)); \
+ *rec++ = tmp; \
+ }
+
+#define INTRA_CLIP { \
+ if((UInt)tmp > mask) tmp = mask&(~(tmp>>31)); \
+ *rec++ = tmp; \
+ }
+
+
+#define CLIP_RESULT(x) if((UInt)x > 0xFF){x = 0xFF & (~(x>>31));}
+#define ADD_AND_CLIP1(x) x += (pred_word&0xFF); CLIP_RESULT(x);
+#define ADD_AND_CLIP2(x) x += ((pred_word>>8)&0xFF); CLIP_RESULT(x);
+#define ADD_AND_CLIP3(x) x += ((pred_word>>16)&0xFF); CLIP_RESULT(x);
+#define ADD_AND_CLIP4(x) x += ((pred_word>>24)&0xFF); CLIP_RESULT(x);
+
+
+void idct_col0(Short *blk)
+{
+ OSCL_UNUSED_ARG(blk);
+
+ return;
+}
+
+void idct_col1(Short *blk)
+{
+ blk[0] = blk[8] = blk[16] = blk[24] = blk[32] = blk[40] = blk[48] = blk[56] =
+ blk[0] << 3;
+ return ;
+}
+
+void idct_col2(Short *blk)
+{
+ int32 x0, x1, x3, x5, x7;//, x8;
+
+ x1 = blk[8];
+ x0 = ((int32)blk[0] << 11) + 128;
+ /* both upper and lower*/
+
+ x7 = W7 * x1;
+ x1 = W1 * x1;
+
+ x3 = x7;
+ x5 = (181 * (x1 - x7) + 128) >> 8;
+ x7 = (181 * (x1 + x7) + 128) >> 8;
+
+ blk[0] = (x0 + x1) >> 8;
+ blk[8] = (x0 + x7) >> 8;
+ blk[16] = (x0 + x5) >> 8;
+ blk[24] = (x0 + x3) >> 8;
+ blk[56] = (x0 - x1) >> 8;
+ blk[48] = (x0 - x7) >> 8;
+ blk[40] = (x0 - x5) >> 8;
+ blk[32] = (x0 - x3) >> 8;
+ return ;
+}
+
+void idct_col3(Short *blk)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+ x2 = blk[16];
+ x1 = blk[8];
+ x0 = ((int32)blk[0] << 11) + 128;
+
+ x4 = x0;
+ x6 = W6 * x2;
+ x2 = W2 * x2;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = W7 * x1;
+ x1 = W1 * x1;
+ x3 = x7;
+ x5 = (181 * (x1 - x7) + 128) >> 8;
+ x7 = (181 * (x1 + x7) + 128) >> 8;
+
+ blk[0] = (x0 + x1) >> 8;
+ blk[8] = (x4 + x7) >> 8;
+ blk[16] = (x6 + x5) >> 8;
+ blk[24] = (x2 + x3) >> 8;
+ blk[56] = (x0 - x1) >> 8;
+ blk[48] = (x4 - x7) >> 8;
+ blk[40] = (x6 - x5) >> 8;
+ blk[32] = (x2 - x3) >> 8;
+ return ;
+}
+
+void idct_col4(Short *blk)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ x2 = blk[16];
+ x1 = blk[8];
+ x3 = blk[24];
+ x0 = ((int32)blk[0] << 11) + 128;
+
+ x4 = x0;
+ x6 = W6 * x2;
+ x2 = W2 * x2;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = W7 * x1;
+ x1 = W1 * x1;
+ x5 = W3 * x3;
+ x3 = -W5 * x3;
+ x8 = x1 - x5;
+ x1 += x5;
+ x5 = x8;
+ x8 = x7 - x3;
+ x3 += x7;
+ x7 = (181 * (x5 + x8) + 128) >> 8;
+ x5 = (181 * (x5 - x8) + 128) >> 8;
+
+
+ blk[0] = (x0 + x1) >> 8;
+ blk[8] = (x4 + x7) >> 8;
+ blk[16] = (x6 + x5) >> 8;
+ blk[24] = (x2 + x3) >> 8;
+ blk[56] = (x0 - x1) >> 8;
+ blk[48] = (x4 - x7) >> 8;
+ blk[40] = (x6 - x5) >> 8;
+ blk[32] = (x2 - x3) >> 8;
+ return ;
+}
+
+#ifndef SMALL_DCT
+void idct_col0x40(Short *blk)
+{
+ int32 x1, x3, x5, x7;//, x8;
+
+ x1 = blk[8];
+ /* both upper and lower*/
+
+ x7 = W7 * x1;
+ x1 = W1 * x1;
+
+ x3 = x7;
+ x5 = (181 * (x1 - x7) + 128) >> 8;
+ x7 = (181 * (x1 + x7) + 128) >> 8;
+
+ blk[0] = (128 + x1) >> 8;
+ blk[8] = (128 + x7) >> 8;
+ blk[16] = (128 + x5) >> 8;
+ blk[24] = (128 + x3) >> 8;
+ blk[56] = (128 - x1) >> 8;
+ blk[48] = (128 - x7) >> 8;
+ blk[40] = (128 - x5) >> 8;
+ blk[32] = (128 - x3) >> 8;
+
+ return ;
+}
+
+void idct_col0x20(Short *blk)
+{
+ int32 x0, x2, x4, x6;
+
+ x2 = blk[16];
+ x6 = W6 * x2;
+ x2 = W2 * x2;
+ x0 = 128 + x2;
+ x2 = 128 - x2;
+ x4 = 128 + x6;
+ x6 = 128 - x6;
+
+ blk[0] = (x0) >> 8;
+ blk[56] = (x0) >> 8;
+ blk[8] = (x4) >> 8;
+ blk[48] = (x4) >> 8;
+ blk[16] = (x6) >> 8;
+ blk[40] = (x6) >> 8;
+ blk[24] = (x2) >> 8;
+ blk[32] = (x2) >> 8;
+
+ return ;
+}
+
+void idct_col0x10(Short *blk)
+{
+ int32 x1, x3, x5, x7;
+
+ x3 = blk[24];
+ x1 = W3 * x3;
+ x3 = W5 * x3;
+
+ x7 = (181 * (x3 - x1) + 128) >> 8;
+ x5 = (-181 * (x1 + x3) + 128) >> 8;
+
+
+ blk[0] = (128 + x1) >> 8;
+ blk[8] = (128 + x7) >> 8;
+ blk[16] = (128 + x5) >> 8;
+ blk[24] = (128 - x3) >> 8;
+ blk[56] = (128 - x1) >> 8;
+ blk[48] = (128 - x7) >> 8;
+ blk[40] = (128 - x5) >> 8;
+ blk[32] = (128 + x3) >> 8;
+
+ return ;
+}
+
+#endif /* SMALL_DCT */
+
+void idct_col(Short *blk)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+
+ x1 = (int32)blk[32] << 11;
+ x2 = blk[48];
+ x3 = blk[16];
+ x4 = blk[8];
+ x5 = blk[56];
+ x6 = blk[40];
+ x7 = blk[24];
+ x0 = ((int32)blk[0] << 11) + 128;
+
+ /* first stage */
+ x8 = W7 * (x4 + x5);
+ x4 = x8 + (W1 - W7) * x4;
+ x5 = x8 - (W1 + W7) * x5;
+ x8 = W3 * (x6 + x7);
+ x6 = x8 - (W3 - W5) * x6;
+ x7 = x8 - (W3 + W5) * x7;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6 * (x3 + x2);
+ x2 = x1 - (W2 + W6) * x2;
+ x3 = x1 + (W2 - W6) * x3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x4 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ blk[0] = (x7 + x1) >> 8;
+ blk[8] = (x3 + x2) >> 8;
+ blk[16] = (x0 + x4) >> 8;
+ blk[24] = (x8 + x6) >> 8;
+ blk[32] = (x8 - x6) >> 8;
+ blk[40] = (x0 - x4) >> 8;
+ blk[48] = (x3 - x2) >> 8;
+ blk[56] = (x7 - x1) >> 8;
+
+ return ;
+}
+
+/* This function should not be called at all ****/
+void idct_row0Inter(Short *srce, UChar *rec, Int lx)
+{
+ OSCL_UNUSED_ARG(srce);
+
+ OSCL_UNUSED_ARG(rec);
+
+ OSCL_UNUSED_ARG(lx);
+
+ return;
+}
+
+void idct_row1Inter(Short *blk, UChar *rec, Int lx)
+{
+ int tmp;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ blk -= 8;
+
+ while (i--)
+ {
+ tmp = (*(blk += 8) + 32) >> 6;
+ *blk = 0;
+
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = tmp + (pred_word & 0xFF);
+ CLIP_RESULT(res);
+ res2 = tmp + ((pred_word >> 8) & 0xFF);
+ CLIP_RESULT(res2);
+ dst_word = (res2 << 8) | res;
+ res = tmp + ((pred_word >> 16) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 16);
+ res = tmp + ((pred_word >> 24) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = tmp + (pred_word & 0xFF);
+ CLIP_RESULT(res);
+ res2 = tmp + ((pred_word >> 8) & 0xFF);
+ CLIP_RESULT(res2);
+ dst_word = (res2 << 8) | res;
+ res = tmp + ((pred_word >> 16) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 16);
+ res = tmp + ((pred_word >> 24) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return;
+}
+
+void idct_row2Inter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x4, x5;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ blk -= 8;
+
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[9];
+ blk[9] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x5 = (W7 * x4 + 4) >> 3;
+ x4 = (W1 * x4 + 4) >> 3;
+
+ /* third stage */
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x1 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = (x0 + x4) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x0 + x2) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x0 + x1) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 + x5) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = (x0 - x5) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x0 - x1) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x0 - x2) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 - x4) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+void idct_row3Inter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ blk -= 8;
+
+ while (i--)
+ {
+ x2 = blk[10];
+ blk[10] = 0;
+ x1 = blk[9];
+ blk[9] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+ /* both upper and lower*/
+ /* both x2orx6 and x0orx4 */
+
+ x4 = x0;
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = (W7 * x1 + 4) >> 3;
+ x1 = (W1 * x1 + 4) >> 3;
+ x3 = x7;
+ x5 = (181 * (x1 - x7) + 128) >> 8;
+ x7 = (181 * (x1 + x7) + 128) >> 8;
+
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = (x0 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x4 + x7) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x6 + x5) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x2 + x3) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = (x2 - x3) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x6 - x5) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x4 - x7) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+
+ return ;
+}
+
+void idct_row4Inter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ blk -= 8;
+
+ while (i--)
+ {
+ x2 = blk[10];
+ blk[10] = 0;
+ x1 = blk[9];
+ blk[9] = 0;
+ x3 = blk[11];
+ blk[11] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ x4 = x0;
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = (W7 * x1 + 4) >> 3;
+ x1 = (W1 * x1 + 4) >> 3;
+ x5 = (W3 * x3 + 4) >> 3;
+ x3 = (- W5 * x3 + 4) >> 3;
+ x8 = x1 - x5;
+ x1 += x5;
+ x5 = x8;
+ x8 = x7 - x3;
+ x3 += x7;
+ x7 = (181 * (x5 + x8) + 128) >> 8;
+ x5 = (181 * (x5 - x8) + 128) >> 8;
+
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = (x0 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x4 + x7) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x6 + x5) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x2 + x3) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = (x2 - x3) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x6 - x5) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x4 - x7) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+#ifndef SMALL_DCT
+void idct_row0x40Inter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x1, x2, x4, x5;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[1];
+ blk[1] = 0;
+ blk += 8; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x5 = (W7 * x4 + 4) >> 3;
+ x4 = (W1 * x4 + 4) >> 3;
+
+ /* third stage */
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x1 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = (8192 + x4) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 + x2) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 + x1) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 + x5) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = (8192 - x5) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 - x1) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 - x2) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 - x4) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+void idct_row0x20Inter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x2, x4, x6;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+
+ while (i--)
+ {
+ x2 = blk[2];
+ blk[2] = 0;
+ blk += 8; /* for proper rounding in the fourth stage */
+ /* both upper and lower*/
+ /* both x2orx6 and x0orx4 */
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x0 = 8192 + x2;
+ x2 = 8192 - x2;
+ x4 = 8192 + x6;
+ x6 = 8192 - x6;
+
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = (x0) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x4) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x6) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x2) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = (x2) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x6) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x4) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+
+ return ;
+}
+
+void idct_row0x10Inter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x1, x3, x5, x7;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+
+ while (i--)
+ {
+ x3 = blk[3];
+ blk[3] = 0;
+ blk += 8;
+
+ x1 = (W3 * x3 + 4) >> 3;
+ x3 = (-W5 * x3 + 4) >> 3;
+
+ x7 = (-181 * (x3 + x1) + 128) >> 8;
+ x5 = (181 * (x3 - x1) + 128) >> 8;
+
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+ res = (8192 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 + x7) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 + x5) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 + x3) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+ res = (8192 - x3) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 - x5) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 - x7) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+#endif /* SMALL_DCT */
+
+void idct_rowInter(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ blk -= 8;
+
+ while (i--)
+ {
+ x1 = (int32)blk[12] << 8;
+ blk[12] = 0;
+ x2 = blk[14];
+ blk[14] = 0;
+ x3 = blk[10];
+ blk[10] = 0;
+ x4 = blk[9];
+ blk[9] = 0;
+ x5 = blk[15];
+ blk[15] = 0;
+ x6 = blk[13];
+ blk[13] = 0;
+ x7 = blk[11];
+ blk[11] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x8 = W7 * (x4 + x5) + 4;
+ x4 = (x8 + (W1 - W7) * x4) >> 3;
+ x5 = (x8 - (W1 + W7) * x5) >> 3;
+ x8 = W3 * (x6 + x7) + 4;
+ x6 = (x8 - (W3 - W5) * x6) >> 3;
+ x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6 * (x3 + x2) + 4;
+ x2 = (x1 - (W2 + W6) * x2) >> 3;
+ x3 = (x1 + (W2 - W6) * x3) >> 3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x4 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ pred_word = *((uint32*)(rec += lx)); /* read 4 bytes from pred */
+
+ res = (x7 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x3 + x2) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x0 + x4) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x8 + x6) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)rec) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(rec + 4)); /* read 4 bytes from pred */
+
+ res = (x8 - x6) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x0 - x4) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x3 - x2) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x7 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return;
+}
+
+void idct_row0Intra(Short *srce, UChar *rec, Int lx)
+{
+ OSCL_UNUSED_ARG(srce);
+
+ OSCL_UNUSED_ARG(rec);
+
+ OSCL_UNUSED_ARG(lx);
+
+ return;
+}
+
+void idct_row1Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 tmp;
+ int i = 8;
+
+ rec -= lx;
+ blk -= 8;
+ while (i--)
+ {
+ tmp = ((*(blk += 8) + 32) >> 6);
+ *blk = 0;
+ CLIP_RESULT(tmp)
+
+ tmp |= (tmp << 8);
+ tmp |= (tmp << 16);
+ *((uint32*)(rec += lx)) = tmp;
+ *((uint32*)(rec + 4)) = tmp;
+ }
+ return;
+}
+
+void idct_row2Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x4, x5;
+ int res, res2;
+ uint32 dst_word;
+ int i = 8;
+
+ rec -= lx;
+ blk -= 8;
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[9];
+ blk[9] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x5 = (W7 * x4 + 4) >> 3;
+ x4 = (W1 * x4 + 4) >> 3;
+
+ /* third stage */
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x1 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ res = ((x0 + x4) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x0 + x2) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x0 + x1) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x0 + x5) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((x0 - x5) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x0 - x1) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x0 - x2) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x0 - x4) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+ }
+ return ;
+}
+
+void idct_row3Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int res, res2;
+ uint32 dst_word;
+ int i = 8;
+
+ rec -= lx;
+ blk -= 8;
+ while (i--)
+ {
+ x2 = blk[10];
+ blk[10] = 0;
+ x1 = blk[9];
+ blk[9] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0;/* for proper rounding in the fourth stage */
+ /* both upper and lower*/
+ /* both x2orx6 and x0orx4 */
+
+ x4 = x0;
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = (W7 * x1 + 4) >> 3;
+ x1 = (W1 * x1 + 4) >> 3;
+ x3 = x7;
+ x5 = (181 * (x1 - x7) + 128) >> 8;
+ x7 = (181 * (x1 + x7) + 128) >> 8;
+
+ res = ((x0 + x1) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x4 + x7) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x6 + x5) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x2 + x3) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((x2 - x3) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x6 - x5) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x4 - x7) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x0 - x1) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+
+ }
+ return ;
+}
+
+void idct_row4Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int res, res2;
+ uint32 dst_word;
+ int i = 8;
+
+ rec -= lx;
+ blk -= 8;
+ while (i--)
+ {
+ x2 = blk[10];
+ blk[10] = 0;
+ x1 = blk[9];
+ blk[9] = 0;
+ x3 = blk[11];
+ blk[11] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ x4 = x0;
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = (W7 * x1 + 4) >> 3;
+ x1 = (W1 * x1 + 4) >> 3;
+ x5 = (W3 * x3 + 4) >> 3;
+ x3 = (- W5 * x3 + 4) >> 3;
+ x8 = x1 - x5;
+ x1 += x5;
+ x5 = x8;
+ x8 = x7 - x3;
+ x3 += x7;
+ x7 = (181 * (x5 + x8) + 128) >> 8;
+ x5 = (181 * (x5 - x8) + 128) >> 8;
+
+ res = ((x0 + x1) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x4 + x7) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x6 + x5) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x2 + x3) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((x2 - x3) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x6 - x5) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x4 - x7) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x0 - x1) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+ }
+
+ return ;
+}
+
+#ifndef SMALL_DCT
+void idct_row0x40Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x1, x2, x4, x5;
+ int res, res2;
+ uint32 dst_word;
+ int i = 8;
+
+ rec -= lx;
+
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[1];
+ blk[1] = 0;
+ blk += 8;
+
+ /* first stage */
+ x5 = (W7 * x4 + 4) >> 3;
+ x4 = (W1 * x4 + 4) >> 3;
+
+ /* third stage */
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x1 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ res = ((8192 + x4) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((8192 + x2) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((8192 + x1) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((8192 + x5) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((8192 - x5) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((8192 - x1) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((8192 - x2) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((8192 - x4) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+
+ }
+ return ;
+}
+
+void idct_row0x20Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x2, x4, x6;
+ int res, res2;
+ uint32 dst_word;
+ int i = 8;
+
+ rec -= lx;
+ while (i--)
+ {
+ x2 = blk[2];
+ blk[2] = 0;
+ blk += 8;
+
+ /* both upper and lower*/
+ /* both x2orx6 and x0orx4 */
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x0 = 8192 + x2;
+ x2 = 8192 - x2;
+ x4 = 8192 + x6;
+ x6 = 8192 - x6;
+
+ res = ((x0) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x4) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x6) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x2) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((x2) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x6) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((x4) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x0) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+
+ }
+ return ;
+}
+
+void idct_row0x10Intra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x1, x3, x5, x7;
+ int res, res2;
+ uint32 dst_word;
+ int i = 8;
+
+ rec -= lx;
+ while (i--)
+ {
+ x3 = blk[3];
+ blk[3] = 0 ;
+ blk += 8;
+
+ x1 = (W3 * x3 + 4) >> 3;
+ x3 = (W5 * x3 + 4) >> 3;
+
+ x7 = (181 * (x3 - x1) + 128) >> 8;
+ x5 = (-181 * (x1 + x3) + 128) >> 8;
+
+ res = ((8192 + x1) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((8192 + x7) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((8192 + x5) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((8192 - x3) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((8192 + x3) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((8192 - x5) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = (res2 << 8) | res;
+ res = ((8192 - x7) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((8192 - x1) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+
+ }
+
+ return ;
+}
+
+#endif /* SMALL_DCT */
+void idct_rowIntra(Short *blk, UChar *rec, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ int res, res2;
+ uint32 dst_word;
+
+ blk -= 8;
+ rec -= lx;
+
+ while (i--)
+ {
+ x1 = (int32)blk[12] << 8;
+ blk[12] = 0;
+ x2 = blk[14];
+ blk[14] = 0;
+ x3 = blk[10];
+ blk[10] = 0;
+ x4 = blk[9];
+ blk[9] = 0;
+ x5 = blk[15];
+ blk[15] = 0;
+ x6 = blk[13];
+ blk[13] = 0;
+ x7 = blk[11];
+ blk[11] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x8 = W7 * (x4 + x5) + 4;
+ x4 = (x8 + (W1 - W7) * x4) >> 3;
+ x5 = (x8 - (W1 + W7) * x5) >> 3;
+ x8 = W3 * (x6 + x7) + 4;
+ x6 = (x8 - (W3 - W5) * x6) >> 3;
+ x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6 * (x3 + x2) + 4;
+ x2 = (x1 - (W2 + W6) * x2) >> 3;
+ x3 = (x1 + (W2 - W6) * x3) >> 3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x4 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ res = ((x7 + x1) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x3 + x2) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = res | (res2 << 8);
+ res = ((x0 + x4) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x8 + x6) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word;
+
+ res = ((x8 - x6) >> 14);
+ CLIP_RESULT(res)
+ res2 = ((x0 - x4) >> 14);
+ CLIP_RESULT(res2)
+ dst_word = res | (res2 << 8);
+ res = ((x3 - x2) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 16);
+ res = ((x7 - x1) >> 14);
+ CLIP_RESULT(res)
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word;
+ }
+ return;
+}
+
+
+/* This function should not be called at all ****/
+void idct_row0zmv(Short *srce, UChar *rec, UChar *pred, Int lx)
+{
+ OSCL_UNUSED_ARG(srce);
+ OSCL_UNUSED_ARG(rec);
+ OSCL_UNUSED_ARG(pred);
+ OSCL_UNUSED_ARG(lx);
+
+ return;
+}
+
+void idct_row1zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int tmp;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ pred -= 16;
+ rec -= lx;
+ blk -= 8;
+
+ while (i--)
+ {
+ tmp = (*(blk += 8) + 32) >> 6;
+ *blk = 0;
+
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = tmp + (pred_word & 0xFF);
+ CLIP_RESULT(res);
+ res2 = tmp + ((pred_word >> 8) & 0xFF);
+ CLIP_RESULT(res2);
+ dst_word = (res2 << 8) | res;
+ res = tmp + ((pred_word >> 16) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 16);
+ res = tmp + ((pred_word >> 24) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = tmp + (pred_word & 0xFF);
+ CLIP_RESULT(res);
+ res2 = tmp + ((pred_word >> 8) & 0xFF);
+ CLIP_RESULT(res2);
+ dst_word = (res2 << 8) | res;
+ res = tmp + ((pred_word >> 16) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 16);
+ res = tmp + ((pred_word >> 24) & 0xFF);
+ CLIP_RESULT(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return;
+}
+
+void idct_row2zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x0, x1, x2, x4, x5;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+ blk -= 8;
+
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[9];
+ blk[9] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x5 = (W7 * x4 + 4) >> 3;
+ x4 = (W1 * x4 + 4) >> 3;
+
+ /* third stage */
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x1 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = (x0 + x4) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x0 + x2) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x0 + x1) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 + x5) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = (x0 - x5) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x0 - x1) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x0 - x2) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 - x4) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+void idct_row3zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+ blk -= 8;
+
+ while (i--)
+ {
+ x2 = blk[10];
+ blk[10] = 0;
+ x1 = blk[9];
+ blk[9] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+ /* both upper and lower*/
+ /* both x2orx6 and x0orx4 */
+
+ x4 = x0;
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = (W7 * x1 + 4) >> 3;
+ x1 = (W1 * x1 + 4) >> 3;
+ x3 = x7;
+ x5 = (181 * (x1 - x7) + 128) >> 8;
+ x7 = (181 * (x1 + x7) + 128) >> 8;
+
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = (x0 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x4 + x7) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x6 + x5) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x2 + x3) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = (x2 - x3) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x6 - x5) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x4 - x7) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+
+ return ;
+}
+
+void idct_row4zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+ blk -= 8;
+
+ while (i--)
+ {
+ x2 = blk[10];
+ blk[10] = 0;
+ x1 = blk[9];
+ blk[9] = 0;
+ x3 = blk[11];
+ blk[11] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ x4 = x0;
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x8 = x0 - x2;
+ x0 += x2;
+ x2 = x8;
+ x8 = x4 - x6;
+ x4 += x6;
+ x6 = x8;
+
+ x7 = (W7 * x1 + 4) >> 3;
+ x1 = (W1 * x1 + 4) >> 3;
+ x5 = (W3 * x3 + 4) >> 3;
+ x3 = (- W5 * x3 + 4) >> 3;
+ x8 = x1 - x5;
+ x1 += x5;
+ x5 = x8;
+ x8 = x7 - x3;
+ x3 += x7;
+ x7 = (181 * (x5 + x8) + 128) >> 8;
+ x5 = (181 * (x5 - x8) + 128) >> 8;
+
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = (x0 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x4 + x7) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x6 + x5) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x2 + x3) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = (x2 - x3) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x6 - x5) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x4 - x7) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+#ifndef SMALL_DCT
+void idct_row0x40zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x1, x2, x4, x5;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+
+ while (i--)
+ {
+ /* shortcut */
+ x4 = blk[1];
+ blk[1] = 0;
+ blk += 8; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x5 = (W7 * x4 + 4) >> 3;
+ x4 = (W1 * x4 + 4) >> 3;
+
+ /* third stage */
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x1 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = (8192 + x4) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 + x2) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 + x1) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 + x5) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = (8192 - x5) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 - x1) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 - x2) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 - x4) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+void idct_row0x20zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x0, x2, x4, x6;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+
+ while (i--)
+ {
+ x2 = blk[2];
+ blk[2] = 0;
+ blk += 8; /* for proper rounding in the fourth stage */
+ /* both upper and lower*/
+ /* both x2orx6 and x0orx4 */
+ x6 = (W6 * x2 + 4) >> 3;
+ x2 = (W2 * x2 + 4) >> 3;
+ x0 = 8192 + x2;
+ x2 = 8192 - x2;
+ x4 = 8192 + x6;
+ x6 = 8192 - x6;
+
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = (x0) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x4) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x6) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x2) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = (x2) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x6) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x4) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x0) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+
+ return ;
+}
+
+void idct_row0x10zmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x1, x3, x5, x7;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+
+ while (i--)
+ {
+ x3 = blk[3];
+ blk[3] = 0;
+ blk += 8;
+
+ x1 = (W3 * x3 + 4) >> 3;
+ x3 = (-W5 * x3 + 4) >> 3;
+
+ x7 = (-181 * (x3 + x1) + 128) >> 8;
+ x5 = (181 * (x3 - x1) + 128) >> 8;
+
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+ res = (8192 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 + x7) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 + x5) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 + x3) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+ res = (8192 - x3) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (8192 - x5) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (8192 - x7) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (8192 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return ;
+}
+
+#endif /* SMALL_DCT */
+
+void idct_rowzmv(Short *blk, UChar *rec, UChar *pred, Int lx)
+{
+ int32 x0, x1, x2, x3, x4, x5, x6, x7, x8;
+ int i = 8;
+ uint32 pred_word, dst_word;
+ int res, res2;
+
+ /* preset the offset, such that we can take advantage pre-offset addressing mode */
+ rec -= lx;
+ pred -= 16;
+ blk -= 8;
+
+ while (i--)
+ {
+ x1 = (int32)blk[12] << 8;
+ blk[12] = 0;
+ x2 = blk[14];
+ blk[14] = 0;
+ x3 = blk[10];
+ blk[10] = 0;
+ x4 = blk[9];
+ blk[9] = 0;
+ x5 = blk[15];
+ blk[15] = 0;
+ x6 = blk[13];
+ blk[13] = 0;
+ x7 = blk[11];
+ blk[11] = 0;
+ x0 = ((*(blk += 8)) << 8) + 8192;
+ *blk = 0; /* for proper rounding in the fourth stage */
+
+ /* first stage */
+ x8 = W7 * (x4 + x5) + 4;
+ x4 = (x8 + (W1 - W7) * x4) >> 3;
+ x5 = (x8 - (W1 + W7) * x5) >> 3;
+ x8 = W3 * (x6 + x7) + 4;
+ x6 = (x8 - (W3 - W5) * x6) >> 3;
+ x7 = (x8 - (W3 + W5) * x7) >> 3;
+
+ /* second stage */
+ x8 = x0 + x1;
+ x0 -= x1;
+ x1 = W6 * (x3 + x2) + 4;
+ x2 = (x1 - (W2 + W6) * x2) >> 3;
+ x3 = (x1 + (W2 - W6) * x3) >> 3;
+ x1 = x4 + x6;
+ x4 -= x6;
+ x6 = x5 + x7;
+ x5 -= x7;
+
+ /* third stage */
+ x7 = x8 + x3;
+ x8 -= x3;
+ x3 = x0 + x2;
+ x0 -= x2;
+ x2 = (181 * (x4 + x5) + 128) >> 8;
+ x4 = (181 * (x4 - x5) + 128) >> 8;
+
+ /* fourth stage */
+ pred_word = *((uint32*)(pred += 16)); /* read 4 bytes from pred */
+
+ res = (x7 + x1) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x3 + x2) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x0 + x4) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x8 + x6) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec += lx)) = dst_word; /* save 4 bytes to dst */
+
+ pred_word = *((uint32*)(pred + 4)); /* read 4 bytes from pred */
+
+ res = (x8 - x6) >> 14;
+ ADD_AND_CLIP1(res);
+ res2 = (x0 - x4) >> 14;
+ ADD_AND_CLIP2(res2);
+ dst_word = (res2 << 8) | res;
+ res = (x3 - x2) >> 14;
+ ADD_AND_CLIP3(res);
+ dst_word |= (res << 16);
+ res = (x7 - x1) >> 14;
+ ADD_AND_CLIP4(res);
+ dst_word |= (res << 24);
+ *((uint32*)(rec + 4)) = dst_word; /* save 4 bytes to dst */
+ }
+ return;
+}
+
+/*----------------------------------------------------------------------------
+; End Function: idctcol
+----------------------------------------------------------------------------*/
+/* ======================================================================== */
+/* Function : BlockIDCTMotionComp */
+/* Date : 10/16/2000 */
+/* Purpose : fast IDCT routine */
+/* In/out : */
+/* Int* coeff_in Dequantized coefficient
+ Int block_out output IDCT coefficient
+ Int maxval clip value */
+/* Modified : 7/31/01, add checking for all-zero and DC-only block. */
+/* do 8 columns at a time */
+/* 8/2/01, do column first then row-IDCT. */
+/* 8/2/01, remove clipping (included in motion comp). */
+/* 8/7/01, combine with motion comp. */
+/* 8/8/01, use AAN IDCT */
+/* 9/4/05, use Chen's IDCT and 16 bit block */
+/* ======================================================================== */
+void BlockIDCTMotionComp(Short *block, UChar *bitmapcol, UChar bitmaprow,
+ Int dctMode, UChar *rec, UChar *pred, Int lx_intra)
+{
+ Int i;
+ Int tmp, tmp2;
+ ULong tmp4;
+ Int bmap;
+ Short *ptr = block;
+ UChar *endcol;
+ UInt mask = 0xFF;
+ Int lx = lx_intra >> 1;
+ Int intra = (lx_intra & 1);
+
+ /* all-zero block */
+ if (dctMode == 0 || bitmaprow == 0)
+ {
+ if (intra)
+ {
+ *((ULong*)rec) = *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ *((ULong*)(rec += lx)) = 0;
+ *((ULong*)(rec + 4)) = 0;
+ return ;
+ }
+ else /* copy from previous frame */
+ {
+ *((ULong*)rec) = *((ULong*)pred);
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ *((ULong*)(rec += lx)) = *((ULong*)(pred += 16));
+ *((ULong*)(rec + 4)) = *((ULong*)(pred + 4));
+ return ;
+ }
+ }
+
+ /* Test for DC only block */
+ if (dctMode == 1 || (bitmaprow == 0x80 && bitmapcol[0] == 0x80))
+ {
+ i = ((block[0] << 3) + 32) >> 6;
+ block[0] = 0;
+ if (intra)
+ {
+ if ((UInt)i > mask) i = mask & (~(i >> 31));
+
+ tmp = i | (i << 8);
+ tmp |= (tmp << 16);
+
+ *((ULong*)rec) = *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+ *((ULong*)(rec += lx)) = tmp;
+ *((ULong*)(rec + 4)) = tmp;
+
+ return ;
+ }
+ else
+ {
+ endcol = rec + (lx << 3);
+ do
+ {
+ tmp4 = *((ULong*)pred);
+ tmp2 = tmp4 & 0xFF;
+ tmp2 += i;
+ if ((UInt)tmp2 > mask) tmp2 = mask & (~(tmp2 >> 31));
+ tmp = (tmp4 >> 8) & 0xFF;
+ tmp += i;
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ tmp2 |= (tmp << 8);
+ tmp = (tmp4 >> 16) & 0xFF;
+ tmp += i;
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ tmp2 |= (tmp << 16);
+ tmp = (tmp4 >> 24) & 0xFF;
+ tmp += i;
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ tmp2 |= (tmp << 24);
+ *((ULong*)rec) = tmp2;
+
+ tmp4 = *((ULong*)(pred + 4));
+ tmp2 = tmp4 & 0xFF;
+ tmp2 += i;
+ if ((UInt)tmp2 > mask) tmp2 = mask & (~(tmp2 >> 31));
+ tmp = (tmp4 >> 8) & 0xFF;
+ tmp += i;
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ tmp2 |= (tmp << 8);
+ tmp = (tmp4 >> 16) & 0xFF;
+ tmp += i;
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ tmp2 |= (tmp << 16);
+ tmp = (tmp4 >> 24) & 0xFF;
+ tmp += i;
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ tmp2 |= (tmp << 24);
+ *((ULong*)(rec + 4)) = tmp2;
+
+ rec += lx;
+ pred += 16;
+ }
+ while (rec < endcol);
+ return ;
+ }
+ }
+
+ for (i = 0; i < dctMode; i++)
+ {
+ bmap = (Int)bitmapcol[i];
+ if (bmap)
+ {
+ if ((bmap&0xf) == 0)
+ (*(idctcolVCA[bmap>>4]))(ptr);
+ else
+ idct_col(ptr);
+ }
+ ptr++;
+ }
+
+ if ((bitmaprow&0xf) == 0)
+ {
+ if (intra)
+ (*(idctrowVCAIntra[(Int)(bitmaprow>>4)]))(block, rec, lx);
+ else
+ (*(idctrowVCAzmv[(Int)(bitmaprow>>4)]))(block, rec, pred, lx);
+ }
+ else
+ {
+ if (intra)
+ idct_rowIntra(block, rec, lx);
+ else
+ idct_rowzmv(block, rec, pred, lx);
+ }
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp
new file mode 100644
index 0000000..466ce47
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant.cpp
@@ -0,0 +1,967 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4enc_lib.h"
+#include "fastquant_inline.h"
+
+#define siz 63
+#define LSL 18
+
+
+const static UChar imask[8] = {128, 64, 32, 16, 8, 4, 2, 1};
+#define SIGN0(a) ( ((a)<0) ? -1 : (((a)>0) ? 1 : 0) )
+
+/* variable bit precision quantization scale */
+/* used to avoid using 32-bit multiplication */
+const static Short scaleArrayV[32] = {0, 16384, 8192, 5462, /* 15 */
+ 4096, 3277, 2731, 2341,
+ 4096, 3641, 3277, 2979, /* 16 */
+ 2731, 2521, 2341, 2185,
+ 4096, 3856, 3641, 3450, /* 17 */
+ 3277, 3121, 2979, 2850,
+ 5462, 5243, 5042, 4855, /* 18 */
+ 4682, 4520, 4370, 4229
+ };
+
+/* scale for dc_scaler and qmat, note, no value smaller than 8 */
+const static Short scaleArrayV2[47] = {0, 0, 0, 0, 0, 0, 0, 0, /* 15 */
+ 4096, 3641, 3277, 2979, 2731, 2521, 2341, 2185,
+ 4096, 3856, 3641, 3450, 3277, 3121, 2979, 2850, /* 16 */
+ 2731, 2622, 2521, 2428, 2341, 2260, 2185, 2115,
+ 4096, 3972, 3856, 3745, 3641, 3543, 3450, 3361, /* 17 */
+ 3277, 3197, 3121, 3049, 2979, 2913, 2850
+ };
+
+/* AAN scale and zigzag */
+const static Short AANScale[64] =
+{
+ /* 0 */ 0x1000, 0x0B89, 0x0C3E, 0x0D9B, 0x1000, 0x0A2E, 0x0EC8, 0x0E7F,
+ /* 1 */ 0x0B89, 0x0851, 0x08D4, 0x09CF, 0x0B89, 0x0757, 0x0AA8, 0x0A73,
+ /* 2 */ 0x0C3E, 0x08D4, 0x095F, 0x0A6A, 0x0C3E, 0x07CB, 0x0B50, 0x0B18,
+ /* 3 */ 0x0D9B, 0x09CF, 0x0A6A, 0x0B92, 0x0D9B, 0x08A8, 0x0C92, 0x0C54,
+ /* 4 */ 0x1000, 0x0B89, 0x0C3E, 0x0D9B, 0x1000, 0x0A2E, 0x0EC8, 0x0E7F,
+ /* 5 */ 0x0A2E, 0x0757, 0x07CB, 0x08A8, 0x0A2E, 0x067A, 0x0968, 0x0939,
+ /* 6 */ 0x0EC8, 0x0AA8, 0x0B50, 0x0C92, 0x0EC8, 0x0968, 0x0DA8, 0x0D64,
+ /* 7 */ 0x0E7F, 0x0A73, 0x0B18, 0x0C54, 0x0E7F, 0x0939, 0x0D64, 0x0D23
+};
+
+const static UShort ZZTab[64] =
+{
+ /* 0 */ 0x0, 0x2, 0xA, 0xC, 0x1C, 0x1E, 0x36, 0x38,
+ /* 1 */ 0x4, 0x8, 0xE, 0x1A, 0x20, 0x34, 0x3A, 0x54,
+ /* 2 */ 0x6, 0x10, 0x18, 0x22, 0x32, 0x3C, 0x52, 0x56,
+ /* 3 */ 0x12, 0x16, 0x24, 0x30, 0x3E, 0x50, 0x58, 0x6A,
+ /* 4 */ 0x14, 0x26, 0x2E, 0x40, 0x4E, 0x5A, 0x68, 0x6C,
+ /* 5 */ 0x28, 0x2C, 0x42, 0x4C, 0x5C, 0x66, 0x6E, 0x78,
+ /* 6 */ 0x2A, 0x44, 0x4A, 0x5E, 0x64, 0x70, 0x76, 0x7A,
+ /* 7 */ 0x46, 0x48, 0x60, 0x62, 0x72, 0x74, 0x7C, 0x7E
+};
+
+
+//Tao need to remove, write another version of abs
+//#include <math.h>
+
+/* ======================================================================== */
+/* Function : cal_dc_scalerENC */
+/* Date : 01/25/2000 */
+/* Purpose : calculation of DC quantization scale according to the
+ incoming Q and type; */
+/* In/out : */
+/* Int Qp Quantizer */
+/* Return : */
+/* DC Scaler */
+/* Modified : */
+/* ======================================================================== */
+/* ======================================================================== */
+Int cal_dc_scalerENC(Int QP, Int type)
+{
+
+ Int dc_scaler;
+ if (type == 1)
+ {
+ if (QP > 0 && QP < 5)
+ dc_scaler = 8;
+ else if (QP > 4 && QP < 9)
+ dc_scaler = 2 * QP;
+ else if (QP > 8 && QP < 25)
+ dc_scaler = QP + 8;
+ else
+ dc_scaler = 2 * QP - 16;
+ }
+ else
+ {
+ if (QP > 0 && QP < 5)
+ dc_scaler = 8;
+ else if (QP > 4 && QP < 25)
+ dc_scaler = (QP + 13) / 2;
+ else
+ dc_scaler = QP - 6;
+ }
+ return dc_scaler;
+}
+
+
+/***********************************************************************
+ Function: BlckQuantDequantH263
+ Date: June 15, 1999
+ Purpose: Combine BlockQuantH263 and BlockDequantH263ENC
+ Input: coeff=> DCT coefficient
+ Output: qcoeff=> quantized coefficient
+ rcoeff=> reconstructed coefficient
+ return CBP for this block
+ 4/2/01, correct dc_scaler for short_header mode.
+ 5/14/01,
+ changed the division into LUT multiplication/shift and other
+ modifications to speed up fastQuant/DeQuant (check for zero 1st, rowq LUT,
+ fast bitmaprow mask and borrowed Addition method instead of ifs from , ).
+ 6/25/01,
+ Further optimization (~100K/QCIF), need more testing/comment before integration.
+
+ 7/4/01, break up Inter / Intra function and merge for different cases.
+ 7/22/01, combine AAN scaling here and reordering.
+ 7/24/01, , reorder already done in FDCT, the input here is in the next block and
+ it's the
+ transpose of the raster scan. Output the same order (for proof of concenpt).
+ 8/1/01, , change FDCT to do row/column FDCT without reordering, input is still
+ in the next block. The reconstructed DCT output is current block in normal
+ order. The quantized output is in zigzag scan order for INTER, row/column for
+ INTRA. Use bitmapzz for zigzag RunLevel for INTER. The quantization is done
+ in column/row scanning order.
+ 8/2/01, , change IDCT to do column/row, change bitmaprow/col to the opposite.
+ 8/3/01, , add clipping to the reconstructed coefficient [-2047,2047]
+ 9/4/05, , removed scaling for AAN IDCT, use Chen IDCT instead.
+ ********************************************************************/
+
+Int BlockQuantDequantH263Inter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dummy, UChar shortHeader)
+{
+ Int i, zz;
+ Int tmp, coeff, q_value;
+ Int QPdiv2 = QuantParam->QPdiv2;
+ Int QPx2 = QuantParam->QPx2;
+ Int Addition = QuantParam->Addition;
+ Int QPx2plus = QuantParam->QPx2plus;
+ Int round = 1 << 15;
+ Int q_scale = scaleArrayV[QuantParam->QP];
+ Int shift = 15 + (QPx2 >> 4);
+ Int *temp;
+ UChar *bcolptr = bitmapcol;
+ Int ac_clip; /* quantized coeff bound */
+
+ OSCL_UNUSED_ARG(comp);
+ OSCL_UNUSED_ARG(dummy);
+
+
+ if (shortHeader) ac_clip = 126; /* clip between [-127,126] (standard allows 127!) */
+ else ac_clip = 2047; /* clip between [-2048,2047] */
+
+ /* reset all bitmap to zero */
+ temp = (Int*) bitmapcol;
+ temp[0] = temp[1] = 0;
+ bitmapzz[0] = bitmapzz[1] = 0;
+ *bitmaprow = 0;
+ QPx2plus <<= 4;
+ QPx2plus -= 8;
+
+ rcoeff += 64; /* actual data is 64 item ahead */
+ //end = rcoeff + dctMode - 1;
+ //rcoeff--;
+ bcolptr--;
+ i = 0;
+
+ do
+ {
+ bcolptr++;
+ //rcoeff++;
+ //i=0;
+ coeff = rcoeff[i];
+ if (coeff == 0x7fff) /* all zero column */
+ {
+ i++;
+ continue;
+ }
+
+ do
+ {
+ if (coeff >= -QPx2plus && coeff < QPx2plus) /* quantize to zero */
+ {
+ i += 8;
+ if (i < (dctMode << 3))
+ {
+ coeff = rcoeff[i];
+ if (coeff > -QPx2plus && coeff < QPx2plus) /* quantize to zero */
+ {
+ i += 8;
+ coeff = rcoeff[i];
+ continue;
+ }
+ else
+ goto NONZERO1;
+ }
+ }
+ else
+ {
+NONZERO1:
+ /* scaling */
+ q_value = AANScale[i]; /* load scale AAN */
+ zz = ZZTab[i]; /* zigzag order */
+
+ coeff = aan_scale(q_value, coeff, round, QPdiv2);
+ q_value = coeff_quant(coeff, q_scale, shift);
+
+ /* dequantization */
+ if (q_value)
+ {
+
+ //coeff = PV_MIN(ac_clip,PV_MAX(-ac_clip-1, q_value));
+ q_value = coeff_clip(q_value, ac_clip);
+ qcoeff[zz>>1] = q_value;
+
+ // dequant and clip
+ //coeff = PV_MIN(2047,PV_MAX(-2048, q_value));
+ tmp = 2047;
+ coeff = coeff_dequant(q_value, QPx2, Addition, tmp);
+ rcoeff[i-64] = coeff;
+
+ (*bcolptr) |= imask[i>>3];
+ if ((zz >> 1) > 31) bitmapzz[1] |= (1 << (63 - (zz >> 1)));
+ else bitmapzz[0] |= (1 << (31 - (zz >> 1)));
+ }
+ i += 8;
+ coeff = rcoeff[i];
+ }
+ }
+ while (i < (dctMode << 3));
+
+ i += (1 - (dctMode << 3));
+ }
+ while (i < dctMode) ;
+
+ i = dctMode;
+ tmp = 1 << (8 - i);
+ while (i--)
+ {
+ if (bitmapcol[i])(*bitmaprow) |= tmp;
+ tmp <<= 1;
+ }
+
+ if (*bitmaprow)
+ return 1;
+ else
+ return 0;
+}
+
+Int BlockQuantDequantH263Intra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dc_scaler, UChar shortHeader)
+{
+ Int i;
+ Int tmp, coeff, q_value;
+ Int QPx2 = QuantParam->QPx2;
+ Int Addition = QuantParam->Addition;
+ Int QPx2plus = QuantParam->QPx2plus;
+ Int round = 1 << 15;
+ Int q_scale = scaleArrayV[QuantParam->QP];
+ Int shift = 15 + (QPx2 >> 4);
+ UChar *bmcolptr = bitmapcol;
+ Int ac_clip; /* quantized coeff bound */
+
+ OSCL_UNUSED_ARG(bitmapzz);
+ OSCL_UNUSED_ARG(comp);
+
+
+ if (shortHeader) ac_clip = 126; /* clip between [-127,126] (standard allows 127!) */
+ else ac_clip = 2047; /* clip between [-2048,2047] */
+
+ *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+
+ QPx2plus = QPx2 << 4;
+ QPx2plus -= 8;
+
+ rcoeff += 64; /* actual data is 64 element ahead */
+ i = 0;
+
+ /* DC value */
+ coeff = *rcoeff;
+ /* scaling */
+ if (coeff == 0x7fff && !shortHeader) /* all zero column */
+ {
+ bmcolptr++;
+ i++;
+ }
+ else
+ {
+ if (coeff == 0x7fff) /* shortHeader on */
+ {
+ coeff = 1; /* can't be zero */
+ qcoeff[0] = coeff;
+ coeff = coeff * dc_scaler;
+ coeff = PV_MAX(-2048, PV_MIN(2047, coeff));
+ rcoeff[-64] = coeff;
+ bitmapcol[0] |= 128;
+ bmcolptr++;
+ //qcoeff++;
+ //rcoeff++;
+ //i=0;
+ i++;
+ }
+ else
+ {
+ q_value = round + (coeff << 12);
+ coeff = q_value >> 16;
+ if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+ else coeff -= (dc_scaler >> 1) ;
+ q_value = scaleArrayV2[dc_scaler];
+ coeff = coeff * q_value;
+ coeff >>= (15 + (dc_scaler >> 4));
+ coeff += ((UInt)coeff >> 31);
+
+ if (shortHeader)
+ coeff = PV_MAX(1, PV_MIN(254, coeff));
+
+ if (coeff)
+ {
+ qcoeff[0] = coeff;
+ coeff = coeff * dc_scaler;
+ coeff = PV_MAX(-2048, PV_MIN(2047, coeff));
+ rcoeff[-64] = coeff;
+ bitmapcol[0] |= 128;
+ }
+ i += 8;
+ }
+ }
+ /* AC values */
+ do
+ {
+ coeff = rcoeff[i];
+ if (coeff == 0x7fff) /* all zero row */
+ {
+ bmcolptr++;
+ i++;
+ continue;
+ }
+ do
+ {
+ if (coeff >= -QPx2plus && coeff < QPx2plus) /* quantize to zero */
+ {
+ i += 8;
+ if (i < dctMode << 3)
+ {
+ coeff = rcoeff[i];
+ if (coeff > -QPx2plus && coeff < QPx2plus) /* quantize to zero */
+ {
+ i += 8;
+ coeff = rcoeff[i];
+ continue;
+ }
+ else
+ goto NONZERO2;
+ }
+ }
+ else
+ {
+NONZERO2: /* scaling */
+ q_value = AANScale[i]; /* 09/02/05 */
+
+ /* scale aan */
+ q_value = smlabb(q_value, coeff, round);
+ coeff = q_value >> 16;
+ /* quant */
+ q_value = smulbb(q_scale, coeff); /*mov q_value, coeff, lsl #14 */
+ /*smull tmp, coeff, q_value, q_scale*/
+ q_value >>= shift;
+ q_value += ((UInt)q_value >> 31); /* add 1 if negative */
+
+ if (q_value)
+ {
+ //coeff = PV_MIN(ac_clip,PV_MAX(-ac_clip-1, q_value));
+ q_value = coeff_clip(q_value, ac_clip);
+ qcoeff[i] = q_value;
+
+ // dequant and clip
+ //coeff = PV_MIN(2047,PV_MAX(-2048, q_value));
+ tmp = 2047;
+ coeff = coeff_dequant(q_value, QPx2, Addition, tmp);
+ rcoeff[i-64] = coeff;
+
+ (*bmcolptr) |= imask[i>>3];
+ }
+ i += 8;
+ coeff = rcoeff[i];
+ }
+ }
+ while (i < (dctMode << 3)) ;
+
+ //qcoeff++; /* next column */
+ bmcolptr++;
+ //rcoeff++;
+ i += (1 - (dctMode << 3)); //i = 0;
+ }
+ while (i < dctMode);//while(rcoeff < end) ;
+
+ i = dctMode;
+ tmp = 1 << (8 - i);
+ while (i--)
+ {
+ if (bitmapcol[i])(*bitmaprow) |= tmp;
+ tmp <<= 1;
+ }
+
+ if (((*bitmaprow)&127) || (bitmapcol[0]&127)) /* exclude DC */
+ return 1;
+ else
+ return 0;
+}
+
+
+/***********************************************************************
+ Function: BlckQuantDequantH263DC
+ Date: 5/3/2001
+ Purpose: H.263 quantization mode, only for DC component
+ 6/25/01,
+ Further optimization (~100K/QCIF), need more testing/comment before integration.
+
+ ********************************************************************/
+Int BlockQuantDequantH263DCInter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar *bitmaprow, UInt *bitmapzz, Int dummy, UChar shortHeader)
+{
+ Int coeff, scale_q;
+ Int CBP = 0;
+ Int QP = QuantParam->QP;
+ Int QPx2plus = QuantParam->QPx2plus;
+ Int Addition = QuantParam->Addition;
+ Int shift = 15 + (QP >> 3);
+ Int ac_clip; /* quantized coeff bound */
+ Int tmp;
+
+ OSCL_UNUSED_ARG(dummy);
+
+ if (shortHeader) ac_clip = 126; /* clip between [-127,126] (standard allows 127!) */
+ else ac_clip = 2047; /* clip between [-2048,2047] */
+
+ *bitmaprow = 0;
+ bitmapzz[0] = bitmapzz[1] = 0;
+ coeff = rcoeff[0];
+
+ if (coeff >= -QPx2plus && coeff < QPx2plus)
+ {
+ rcoeff[0] = 0;
+ return CBP;//rcoeff[0] = 0; not needed since CBP will be zero
+ }
+ else
+ {
+ scale_q = scaleArrayV[QP];
+
+ coeff = aan_dc_scale(coeff, QP);
+
+ scale_q = coeff_quant(coeff, scale_q, shift);
+
+ //coeff = PV_MIN(ac_clip,PV_MAX(-ac_clip-1, tmp));
+ scale_q = coeff_clip(scale_q, ac_clip);
+
+ qcoeff[0] = scale_q;
+
+ QP <<= 1;
+ //coeff = PV_MIN(2047,PV_MAX(-2048, tmp));
+ tmp = 2047;
+ coeff = coeff_dequant(scale_q, QP, Addition, tmp);
+
+ rcoeff[0] = coeff;
+
+ (*bitmaprow) = 128;
+ bitmapzz[0] = (ULong)1 << 31;
+ CBP = 1;
+ }
+ return CBP;
+}
+
+
+Int BlockQuantDequantH263DCIntra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler, UChar shortHeader)
+{
+ Int tmp, coeff;
+
+ OSCL_UNUSED_ARG(QuantParam);
+
+ *bitmaprow = 0;
+ coeff = rcoeff[0];
+
+ if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+ else coeff -= (dc_scaler >> 1) ;
+ tmp = scaleArrayV2[dc_scaler];
+ tmp = coeff * tmp;
+ tmp >>= (15 + (dc_scaler >> 4));
+ tmp += ((UInt)tmp >> 31);
+
+ if (shortHeader)
+ tmp = PV_MAX(1, PV_MIN(254, tmp));
+
+ if (tmp)
+ {
+ qcoeff[0] = tmp;
+ coeff = tmp * dc_scaler;
+ coeff = PV_MAX(-2048, PV_MIN(2047, coeff));
+ rcoeff[0] = coeff;
+ *bitmaprow = 128;
+ bitmapzz[0] = (ULong)1 << 31;
+ }
+
+ return 0;
+}
+
+#ifndef NO_MPEG_QUANT
+/***********************************************************************
+ Function: BlckQuantDequantMPEG
+ Date: June 15, 1999
+ Purpose: Combine BlockQuantMPEG and BlockDequantMPEGENC
+ Input: coeff=> DCT coefficient
+ Output: qcoeff=> quantized coefficient
+ rcoeff=> reconstructed coefficient
+ Modified: 7/5/01, break up function for Intra/Inter
+ 8/3/01, update with changes from H263 quant mode.
+ 8/3/01, add clipping to the reconstructed coefficient [-2048,2047]
+ 8/6/01, optimize using multiplicative lookup-table.
+ can be further optimized using ARM assembly, e.g.,
+ clipping, 16-bit mult., etc !!!!!!!!!!!!!
+ ********************************************************************/
+
+Int BlockQuantDequantMPEGInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dc_scaler)
+{
+ Int i, zz;
+ Int tmp, coeff, q_value = 0;
+ Int sum = 0;
+ Int stepsize, QPx2 = QP << 1;
+ Int CBP = 0;
+ Int round = 1 << 15;
+ Int q_scale = scaleArrayV[QP];
+ Int shift = 15 + (QP >> 3);
+ UChar *bcolptr = bitmapcol;
+
+ OSCL_UNUSED_ARG(dc_scaler);
+ OSCL_UNUSED_ARG(comp);
+
+
+ *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+ bitmapzz[0] = bitmapzz[1] = 0;
+ *bitmaprow = 0;
+
+ rcoeff += 64;
+ i = 0;
+ bcolptr--;
+
+ do
+ {
+ bcolptr++;
+ coeff = rcoeff[i];
+ if (coeff == 0x7fff) /* all zero column */
+ {
+ i++;
+ continue;
+ }
+ do
+ {
+ q_value = AANScale[i]; /* 09/02/05 scaling for AAN*/
+ /* aan scaling */
+ q_value = smlabb(q_value, coeff, round);
+
+ coeff = q_value >> 16;
+
+ stepsize = qmat[i];
+// if(coeff>0) coeff = (16*coeff + (stepsize/2)) / stepsize;
+// else coeff = (16*coeff - (stepsize/2)) / stepsize;
+ coeff <<= 4;
+ if (coeff >= 0) coeff += (stepsize >> 1) ;
+ else coeff -= (stepsize >> 1) ;
+ q_value = scaleArrayV2[stepsize];
+ /* mpeg quant table scale */
+ coeff = smulbb(coeff, q_value);
+
+ coeff >>= (15 + (stepsize >> 4));
+ coeff += ((UInt)coeff >> 31);
+
+ /* QP scale */
+ if (coeff >= -QPx2 && coeff < QPx2) /* quantized to zero*/
+ {
+ i += 8;
+ }
+ else
+ {
+// q_value = coeff/(QPx2);
+ q_value = coeff_quant(coeff, q_scale, shift);
+
+ if (q_value) /* dequant */
+ {
+
+ zz = ZZTab[i]; /* zigzag order */
+
+ tmp = 2047;
+
+ q_value = clip_2047(q_value, tmp);
+
+ qcoeff[zz>>1] = q_value;
+
+ //q_value=(((coeff*2)+SIGN0(coeff))*stepsize*QP)/16;
+ /* no need for SIGN0, no zero coming in this {} */
+ q_value = coeff_dequant_mpeg(q_value, stepsize, QP, tmp);
+
+ rcoeff[i-64] = q_value;
+
+ sum += q_value;
+ (*bcolptr) |= imask[i>>3];
+ if ((zz >> 1) > 31) bitmapzz[1] |= (1 << (63 - (zz >> 1)));
+ else bitmapzz[0] |= (1 << (31 - (zz >> 1)));
+ }
+ i += 8;
+ }
+ coeff = rcoeff[i];
+ }
+ while (i < (dctMode << 3)) ;
+
+ i += (1 - (dctMode << 3));
+ }
+ while (i < dctMode) ;
+
+ i = dctMode;
+ tmp = 1 << (8 - i);
+ while (i--)
+ {
+ if (bitmapcol[i])(*bitmaprow) |= tmp;
+ tmp <<= 1;
+ }
+
+ if (*bitmaprow)
+ CBP = 1; /* check CBP before mismatch control, 7/5/01 */
+
+ /* Mismatch control, 5/3/01 */
+ if (CBP)
+ {
+ if ((sum&0x1) == 0)
+ {
+ rcoeff--; /* rcoeff[63] */
+ coeff = *rcoeff;
+ coeff ^= 0x1;
+ *rcoeff = coeff;
+ if (coeff)
+ {
+ bitmapcol[7] |= 1;
+ (*bitmaprow) |= 1;
+ }
+ }
+ }
+
+ return CBP;
+}
+
+Int BlockQuantDequantMPEGIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dc_scaler)
+{
+ Int i;
+ Int tmp, coeff, q_value = 0;
+ Int sum = 0;
+ Int stepsize;
+ Int CBP = 0;
+ Int round = 1 << 15;
+ Int q_scale = scaleArrayV[QP];
+ Int shift = 15 + (QP >> 3);
+ Int round2 = (3 * QP + 2) >> 2;
+ Int QPx2plus = (QP << 1) - round2;
+ UChar *bmcolptr = bitmapcol;
+
+ OSCL_UNUSED_ARG(bitmapzz);
+ OSCL_UNUSED_ARG(comp);
+
+ *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+
+ rcoeff += 64;
+ i = 0;
+
+ /* DC value */
+ coeff = *rcoeff;
+
+ if (coeff == 0x7fff) /* all zero column */
+ {
+ bmcolptr++;
+ i++;
+ }
+ else
+ {
+ q_value = round + (coeff << 12);
+ coeff = q_value >> 16;
+ /*if (coeff >= 0) coeff = (coeff + (dc_scaler/2)) / dc_scaler;
+ else coeff = (coeff - (dc_scaler/2)) / dc_scaler;*/
+ if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+ else coeff -= (dc_scaler >> 1) ;
+ q_value = scaleArrayV2[dc_scaler];
+
+ /* mpeg quant table scale */
+ coeff = smulbb(coeff, q_value);
+
+ coeff >>= (15 + (dc_scaler >> 4));
+ coeff += ((UInt)coeff >> 31);
+
+ if (coeff)
+ {
+ coeff = PV_MAX(1, PV_MIN(254, coeff));
+ qcoeff[0] = coeff;
+
+ coeff = smulbb(coeff, dc_scaler);
+
+ q_value = clip_2047(coeff, 2047);
+
+ sum = q_value;
+
+ rcoeff[-64] = q_value;
+
+ bitmapcol[0] |= 128;
+ }
+ i += 8;
+ }
+ /* AC values */
+ do
+ {
+ coeff = rcoeff[i];
+ if (coeff == 0x7fff) /* all zero row */
+ {
+ bmcolptr++;
+ i++;
+ continue;
+ }
+ do
+ {
+ /* scaling */
+ q_value = AANScale[i]; /* 09/02/05 */
+
+ /* q_value = coeff*q_value + round */
+ q_value = smlabb(coeff, q_value, round);
+ coeff = q_value >> 16;
+
+ stepsize = qmat[i];
+ /*if(coeff>0) coeff = (16*coeff + (stepsize/2)) / stepsize;
+ else coeff = (16*coeff - (stepsize/2)) / stepsize;*/
+ coeff <<= 4;
+ if (coeff >= 0) coeff += (stepsize >> 1) ;
+ else coeff -= (stepsize >> 1) ;
+ q_value = scaleArrayV2[stepsize];
+
+ /* scale mpeg quant */
+ coeff = smulbb(coeff, q_value);
+
+ coeff >>= (15 + (stepsize >> 4));
+ coeff += ((UInt)coeff >> 31);
+
+ if (coeff >= -QPx2plus && coeff < QPx2plus)
+ {
+ i += 8;
+ }
+ else
+ {
+ //q_value = ( coeff + SIGN0(coeff)*((3*QP+2)/4))/(2*QP);
+ if (coeff > 0) coeff += round2;
+ else if (coeff < 0) coeff -= round2;
+
+ q_value = smulbb(coeff, q_scale);
+ q_value >>= shift;
+ q_value += ((UInt)q_value >> 31);
+
+ if (q_value)
+ {
+ tmp = 2047;
+ q_value = clip_2047(q_value, tmp);
+
+ qcoeff[i] = q_value;
+
+ stepsize = smulbb(stepsize, QP);
+ q_value = smulbb(q_value, stepsize);
+
+ q_value = coeff_dequant_mpeg_intra(q_value, tmp);
+ //q_value = (coeff*stepsize*QP*2)/16;
+
+ rcoeff[i-64] = q_value;
+
+ sum += q_value;
+ (*bmcolptr) |= imask[i>>3];
+ }
+ i += 8;
+ }
+ coeff = rcoeff[i];
+ }
+ while (i < (dctMode << 3)) ;
+
+ bmcolptr++;
+ i += (1 - (dctMode << 3));
+ }
+ while (i < dctMode) ;
+
+ i = dctMode;
+ tmp = 1 << (8 - i);
+ while (i--)
+ {
+ if (bitmapcol[i])(*bitmaprow) |= tmp;
+ tmp <<= 1;
+ }
+
+ if (((*bitmaprow) &127) || (bitmapcol[0]&127))
+ CBP = 1; /* check CBP before mismatch control, 7/5/01 */
+
+ /* Mismatch control, 5/3/01 */
+ if (CBP || bitmapcol[0])
+ {
+ if ((sum&0x1) == 0)
+ {
+ rcoeff--; /* rcoeff[63] */
+ coeff = *rcoeff;
+ coeff ^= 0x1;
+ *rcoeff = coeff;
+ if (coeff)
+ {
+ bitmapcol[7] |= 1;
+ (*bitmaprow) |= 1;
+ }
+ }
+ }
+
+ return CBP;
+}
+
+
+/***********************************************************************
+ Function: BlckQuantDequantMPEGDC
+ Date: 5/3/2001
+ Purpose: MPEG Quant/Dequant for DC only block.
+ ********************************************************************/
+Int BlockQuantDequantMPEGDCInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dummy)
+{
+ Int q_value, coeff, stepsize;
+ Int CBP = 0;
+ Int q_scale = scaleArrayV[QP];
+ Int shift = 15 + (QP >> 3);
+ Int QPx2 = QP << 1;
+
+ OSCL_UNUSED_ARG(dummy);
+
+ *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+ bitmapzz[0] = bitmapzz[1] = 0;
+ coeff = rcoeff[0];
+ stepsize = qmat[0];
+
+ /*if(coeff>0) coeff = (16*coeff + (stepsize/2)) / stepsize;
+ else coeff = (16*coeff - (stepsize/2)) / stepsize;*/
+ coeff <<= 4;
+ if (coeff >= 0) coeff += (stepsize >> 1) ;
+ else coeff -= (stepsize >> 1) ;
+ q_value = scaleArrayV2[stepsize];
+
+ coeff = smulbb(coeff, q_value);
+
+ coeff >>= (15 + (stepsize >> 4));
+ coeff += ((UInt)coeff >> 31);
+
+ if (coeff >= -QPx2 && coeff < QPx2)
+ {
+ rcoeff[0] = 0;
+ return CBP;
+ }
+ else
+ {
+// q_value = coeff/(QPx2);
+ q_value = coeff_quant(coeff, q_scale, shift);
+
+ if (q_value)
+ {
+
+ //PV_MIN(2047,PV_MAX(-2048, q_value));
+ q_value = clip_2047(q_value, 2047);
+ qcoeff[0] = q_value;
+ q_value = coeff_dequant_mpeg(q_value, stepsize, QP, 2047);
+ //q_value=(((coeff*2)+SIGN0(coeff))*stepsize*QP)/16;
+ rcoeff[0] = q_value;
+
+ bitmapcol[0] = 128;
+ (*bitmaprow) = 128;
+ bitmapzz[0] = (UInt)1 << 31;
+ CBP = 1;
+
+ /* Mismatch control, 5/3/01 */
+ if ((q_value&0x1) == 0)
+ {
+ rcoeff[63] = 1; /* after scaling it remains the same */
+ bitmapcol[7] |= 1;
+ (*bitmaprow) |= 1;
+ }
+ }
+ }
+ return CBP;
+}
+
+
+Int BlockQuantDequantMPEGDCIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dc_scaler)
+{
+ Int tmp, coeff, q_value;
+
+ OSCL_UNUSED_ARG(QP);
+ OSCL_UNUSED_ARG(qmat);
+
+
+ *((Int*)bitmapcol) = *((Int*)(bitmapcol + 4)) = 0;
+ *bitmaprow = 0;
+ coeff = rcoeff[0];
+
+ /*if (coeff >= 0) tmp = (coeff + dc_scaler/2) / dc_scaler;
+ else tmp = (coeff - dc_scaler/2) / dc_scaler;*/
+ if (coeff >= 0) coeff += (dc_scaler >> 1) ;
+ else coeff -= (dc_scaler >> 1) ;
+ tmp = scaleArrayV2[dc_scaler];
+
+ tmp = smulbb(tmp, coeff);
+ tmp >>= (15 + (dc_scaler >> 4));
+ tmp += ((UInt)tmp >> 31);
+
+ if (tmp)
+ {
+ coeff = PV_MAX(1, PV_MIN(254, tmp));
+ qcoeff[0] = coeff;
+
+ q_value = smulbb(coeff, dc_scaler);
+ q_value = clip_2047(q_value, 2047);
+ rcoeff[0] = q_value;
+ bitmapcol[0] = 128;
+ *bitmaprow = 128;
+ bitmapzz[0] = (UInt)1 << 31;
+
+ /* Mismatch control, 5/3/01 */
+ if ((q_value&0x1) == 0)
+ {
+ rcoeff[63] = 1; /* after scaling it remains the same */
+ bitmapcol[7] |= 1;
+ (*bitmaprow) |= 1;
+ }
+ }
+
+ return 0;
+}
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h
new file mode 100644
index 0000000..79d0ebf
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/fastquant_inline.h
@@ -0,0 +1,625 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/* Filename: fastquant_inline.h */
+/* Description: Implementation for in-line functions used in dct.cpp */
+/* Modified: */
+/*********************************************************************************/
+#ifndef _FASTQUANT_INLINE_H_
+#define _FASTQUANT_INLINE_H_
+
+#include "mp4def.h"
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER */
+
+__inline int32 aan_scale(int32 q_value, int32 coeff, int32 round, int32 QPdiv2)
+{
+ q_value = coeff * q_value + round;
+ coeff = q_value >> 16;
+ if (coeff < 0) coeff += QPdiv2;
+ else coeff -= QPdiv2;
+
+ return coeff;
+}
+
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+ int32 q_value;
+
+ q_value = coeff * q_scale; //q_value = -((-(coeff + QPdiv2)*q_scale)>>LSL);
+ q_value >>= shift; //q_value = (((coeff - QPdiv2)*q_scale)>>LSL );
+ q_value += ((UInt)q_value >> 31); /* add one if negative */
+
+ return q_value;
+}
+
+__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
+{
+ int32 coeff = q_value + ac_clip;
+
+ if ((UInt)coeff > (UInt)(ac_clip << 1))
+ q_value = ac_clip ^(q_value >> 31);
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+ int32 coeff;
+
+ OSCL_UNUSED_ARG(tmp);
+
+ if (q_value < 0)
+ {
+ coeff = q_value * QPx2 - Addition;
+ if (coeff < -2048)
+ coeff = -2048;
+ }
+ else
+ {
+ coeff = q_value * QPx2 + Addition;
+ if (coeff > 2047)
+ coeff = 2047;
+ }
+ return coeff;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+ q_value = coeff * q_value + round;
+
+ return q_value;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+ int32 q_value;
+
+ q_value = coeff * q_scale;
+
+ return q_value;
+}
+
+__inline int32 aan_dc_scale(int32 coeff, int32 QP)
+{
+
+ if (coeff < 0) coeff += (QP >> 1);
+ else coeff -= (QP >> 1);
+
+ return coeff;
+}
+
+__inline int32 clip_2047(int32 q_value, int32 tmp)
+{
+ OSCL_UNUSED_ARG(tmp);
+
+ if (q_value < -2048)
+ {
+ q_value = -2048;
+ }
+ else if (q_value > 2047)
+ {
+ q_value = 2047;
+ }
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+ int32 coeff;
+
+ OSCL_UNUSED_ARG(tmp);
+
+ coeff = q_value << 1;
+ stepsize *= QP;
+ if (coeff > 0)
+ {
+ q_value = (coeff + 1) * stepsize;
+ q_value >>= 4;
+ if (q_value > 2047) q_value = 2047;
+ }
+ else
+ {
+ q_value = (coeff - 1) * stepsize;
+ q_value += 15;
+ q_value >>= 4;
+ if (q_value < -2048) q_value = -2048;
+ }
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
+{
+ OSCL_UNUSED_ARG(tmp);
+
+ q_value <<= 1;
+ if (q_value > 0)
+ {
+ q_value >>= 4;
+ if (q_value > 2047) q_value = 2047;
+ }
+ else
+ {
+ q_value += 15;
+ q_value >>= 4;
+ if (q_value < -2048) q_value = -2048;
+ }
+
+ return q_value;
+}
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+#if defined(__TARGET_ARCH_5TE)
+
+__inline int32 aan_scale(int32 q_value, int32 coeff,
+ int32 round, int32 QPdiv2)
+{
+ __asm
+ {
+ smlabb q_value, coeff, q_value, round
+ movs coeff, q_value, asr #16
+ addle coeff, coeff, QPdiv2
+ subgt coeff, coeff, QPdiv2
+ }
+
+ return coeff;
+}
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+ int32 q_value;
+
+ __asm
+ {
+ smulbb q_value, q_scale, coeff /*mov coeff, coeff, lsl #14*/
+ mov coeff, q_value, asr shift /*smull tmp, coeff, q_scale, coeff*/
+ add q_value, coeff, coeff, lsr #31
+ }
+
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+ int32 coeff;
+
+ __asm
+ {
+ cmp q_value, #0
+ smulbb coeff, q_value, QPx2
+ sublt coeff, coeff, Addition
+ addge coeff, coeff, Addition
+ add q_value, coeff, tmp
+ subs q_value, q_value, #3840
+ subcss q_value, q_value, #254
+ eorhi coeff, tmp, coeff, asr #31
+ }
+
+ return coeff;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+ __asm
+ {
+ smlabb q_value, coeff, q_value, round
+ }
+
+ return q_value;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+ int32 q_value;
+
+ __asm
+ {
+ smulbb q_value, q_scale, coeff
+ }
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+ /* tmp must have value of 2047 */
+ int32 coeff;
+ __asm
+ {
+ movs coeff, q_value, lsl #1
+ smulbb stepsize, stepsize, QP
+ addgt coeff, coeff, #1
+ sublt coeff, coeff, #1
+ smulbb q_value, coeff, stepsize
+ addlt q_value, q_value, #15
+ mov q_value, q_value, asr #4
+ add coeff, q_value, tmp
+ subs coeff, coeff, #0xf00
+ subcss coeff, coeff, #0xfe
+ eorhi q_value, tmp, q_value, asr #31
+ }
+
+ return q_value;
+}
+
+
+#else // not ARMV5TE
+
+__inline int32 aan_scale(int32 q_value, int32 coeff,
+ int32 round, int32 QPdiv2)
+{
+ __asm
+ {
+ mla q_value, coeff, q_value, round
+ movs coeff, q_value, asr #16
+ addle coeff, coeff, QPdiv2
+ subgt coeff, coeff, QPdiv2
+ }
+
+ return coeff;
+}
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+ int32 q_value;
+
+ __asm
+ {
+ mul q_value, q_scale, coeff /*mov coeff, coeff, lsl #14*/
+ mov coeff, q_value, asr shift /*smull tmp, coeff, q_scale, coeff*/
+ add q_value, coeff, coeff, lsr #31
+ }
+
+
+ return q_value;
+}
+
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+ int32 coeff;
+
+ __asm
+ {
+ cmp q_value, #0
+ mul coeff, q_value, QPx2
+ sublt coeff, coeff, Addition
+ addge coeff, coeff, Addition
+ add q_value, coeff, tmp
+ subs q_value, q_value, #3840
+ subcss q_value, q_value, #254
+ eorhi coeff, tmp, coeff, asr #31
+ }
+
+ return coeff;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+ __asm
+ {
+ mla q_value, coeff, q_value, round
+ }
+
+ return q_value;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+ int32 q_value;
+
+ __asm
+ {
+ mul q_value, q_scale, coeff
+ }
+
+ return q_value;
+}
+
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+ /* tmp must have value of 2047 */
+ int32 coeff;
+ __asm
+ {
+ movs coeff, q_value, lsl #1
+ mul stepsize, stepsize, QP
+ addgt coeff, coeff, #1
+ sublt coeff, coeff, #1
+ mul q_value, coeff, stepsize
+ addlt q_value, q_value, #15
+ mov q_value, q_value, asr #4
+ add coeff, q_value, tmp
+ subs coeff, coeff, #0xf00
+ subcss coeff, coeff, #0xfe
+ eorhi q_value, tmp, q_value, asr #31
+ }
+
+ return q_value;
+}
+
+
+#endif
+
+__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
+{
+ int32 coeff;
+
+ __asm
+ {
+ add coeff, q_value, ac_clip
+ subs coeff, coeff, ac_clip, lsl #1
+ eorhi q_value, ac_clip, q_value, asr #31
+ }
+
+ return q_value;
+}
+
+__inline int32 aan_dc_scale(int32 coeff, int32 QP)
+{
+
+ __asm
+ {
+ cmp coeff, #0
+ addle coeff, coeff, QP, asr #1
+ subgt coeff, coeff, QP, asr #1
+ }
+
+ return coeff;
+}
+
+__inline int32 clip_2047(int32 q_value, int32 tmp)
+{
+ /* tmp must have value of 2047 */
+ int32 coeff;
+
+ __asm
+ {
+ add coeff, q_value, tmp
+ subs coeff, coeff, #0xf00
+ subcss coeff, coeff, #0xfe
+ eorhi q_value, tmp, q_value, asr #31
+ }
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
+{
+ int32 coeff;
+
+ __asm
+ {
+ movs q_value, q_value, lsl #1
+ addlt q_value, q_value, #15
+ mov q_value, q_value, asr #4
+ add coeff, q_value, tmp
+ subs coeff, coeff, #0xf00
+ subcss coeff, coeff, #0xfe
+ eorhi q_value, tmp, q_value, asr #31
+ }
+
+ return q_value;
+}
+
+#elif ( defined(PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5) ) /* ARM GNU COMPILER */
+
+__inline int32 aan_scale(int32 q_value, int32 coeff,
+ int32 round, int32 QPdiv2)
+{
+ register int32 out;
+ register int32 qv = q_value;
+ register int32 cf = coeff;
+ register int32 rr = round;
+ register int32 qp = QPdiv2;
+
+ asm volatile("smlabb %0, %2, %1, %3\n\t"
+ "movs %0, %0, asr #16\n\t"
+ "addle %0, %0, %4\n\t"
+ "subgt %0, %0, %4"
+ : "=&r"(out)
+ : "r"(qv),
+ "r"(cf),
+ "r"(rr),
+ "r"(qp));
+ return out;
+}
+
+__inline int32 coeff_quant(int32 coeff, int32 q_scale, int32 shift)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 cc = coeff;
+ register int32 qs = q_scale;
+ register int32 ss = shift;
+
+ asm volatile("smulbb %0, %3, %2\n\t"
+ "mov %1, %0, asr %4\n\t"
+ "add %0, %1, %1, lsr #31"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(cc),
+ "r"(qs),
+ "r"(ss));
+
+ return out;
+}
+
+__inline int32 coeff_clip(int32 q_value, int32 ac_clip)
+{
+ register int32 coeff;
+
+ asm volatile("add %1, %0, %2\n\t"
+ "subs %1, %1, %2, lsl #1\n\t"
+ "eorhi %0, %2, %0, asr #31"
+ : "+r"(q_value),
+ "=&r"(coeff)
+ : "r"(ac_clip));
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant(int32 q_value, int32 QPx2, int32 Addition, int32 tmp)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 qv = q_value;
+ register int32 qp = QPx2;
+ register int32 aa = Addition;
+ register int32 tt = tmp;
+
+ asm volatile("cmp %2, #0\n\t"
+ "mul %0, %2, %3\n\t"
+ "sublt %0, %0, %4\n\t"
+ "addge %0, %0, %4\n\t"
+ "add %1, %0, %5\n\t"
+ "subs %1, %1, #3840\n\t"
+ "subcss %1, %1, #254\n\t"
+ "eorhi %0, %5, %0, asr #31"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(qv),
+ "r"(qp),
+ "r"(aa),
+ "r"(tt));
+
+ return out;
+}
+
+__inline int32 smlabb(int32 q_value, int32 coeff, int32 round)
+{
+ register int32 out;
+ register int32 aa = (int32)q_value;
+ register int32 bb = (int32)coeff;
+ register int32 cc = (int32)round;
+
+ asm volatile("smlabb %0, %1, %2, %3"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb),
+ "r"(cc));
+ return out;
+}
+
+__inline int32 smulbb(int32 q_scale, int32 coeff)
+{
+ register int32 out;
+ register int32 aa = (int32)q_scale;
+ register int32 bb = (int32)coeff;
+
+ asm volatile("smulbb %0, %1, %2"
+ : "=&r"(out)
+ : "r"(aa),
+ "r"(bb));
+ return out;
+}
+
+__inline int32 aan_dc_scale(int32 coeff, int32 QP)
+{
+ register int32 out;
+ register int32 cc = coeff;
+ register int32 qp = QP;
+
+ asm volatile("cmp %1, #0\n\t"
+ "addle %0, %1, %2, asr #1\n\t"
+ "subgt %0, %1, %2, asr #1"
+ : "=&r"(out)
+ : "r"(cc),
+ "r"(qp));
+ return out;
+}
+
+__inline int32 clip_2047(int32 q_value, int32 tmp)
+{
+ register int32 coeff;
+ asm volatile("add %1, %0, %2\n\t"
+ "subs %1, %1, #0xF00\n\t"
+ "subcss %1, %1, #0xFE\n\t"
+ "eorhi %0, %2, %0, asr #31"
+ : "+r"(q_value),
+ "=&r"(coeff)
+ : "r"(tmp));
+
+ return q_value;
+}
+
+__inline int32 coeff_dequant_mpeg(int32 q_value, int32 stepsize, int32 QP, int32 tmp)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 qv = q_value;
+ register int32 ss = stepsize;
+ register int32 qp = QP;
+ register int32 tt = tmp;
+
+ asm volatile("movs %1, %2, lsl #1\n\t"
+ "mul %0, %3, %4\n\t"
+ "addgt %1, %1, #1\n\t"
+ "sublt %1, %1, #1\n\t"
+ "mul %0, %1, %0\n\t"
+ "addlt %0, %0, #15\n\t"
+ "mov %0, %0, asr #4\n\t"
+ "add %1, %0, %5\n\t"
+ "subs %1, %1, #0xF00\n\t"
+ "subcss %1, %1, #0xFE\n\t"
+ "eorhi %0, %5, %0, asr #31"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(qv),
+ "r"(ss),
+ "r"(qp),
+ "r"(tt));
+
+ return out;
+
+}
+
+__inline int32 coeff_dequant_mpeg_intra(int32 q_value, int32 tmp)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 qv = q_value;
+ register int32 tt = tmp;
+
+ asm volatile("movs %1, %2, lsl #1\n\t"
+ "addlt %1, %1, #15\n\t"
+ "mov %0, %1, asr #4\n\t"
+ "add %1, %0, %3\n\t"
+ "subs %1, %1, #0xF00\n\t"
+ "subcss %1, %1, #0xFE\n\t"
+ "eorhi %0, %3, %0, asr #31"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(qv),
+ "r"(tt));
+ return out;
+}
+
+
+#endif // Platform
+
+
+#endif //_FASTQUANT_INLINE_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp
new file mode 100644
index 0000000..319c76f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/findhalfpel.cpp
@@ -0,0 +1,287 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "m4venc_oscl.h"
+
+/* 3/29/01 fast half-pel search based on neighboring guess */
+/* value ranging from 0 to 4, high complexity (more accurate) to
+ low complexity (less accurate) */
+#define HP_DISTANCE_TH 2 /* half-pel distance threshold */
+
+#define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void GenerateSearchRegion(UChar *searchPadding, UChar *ref, Int width, Int height,
+ Int ilow, Int ihigh, Int jlow, Int jhigh);
+
+ void InterpDiag(UChar *prev, Int lx, UChar *pred_block);
+ void InterpHorz(UChar *prev, Int lx, UChar *pred_block);
+ void InterpVert(UChar *prev, Int lx, UChar *pred_block);
+#ifdef __cplusplus
+}
+#endif
+
+
+const static Int distance_tab[9][9] = /* [hp_guess][k] */
+{
+ {0, 1, 1, 1, 1, 1, 1, 1, 1},
+ {1, 0, 1, 2, 3, 4, 3, 2, 1},
+ {1, 0, 0, 0, 1, 2, 3, 2, 1},
+ {1, 2, 1, 0, 1, 2, 3, 4, 3},
+ {1, 2, 1, 0, 0, 0, 1, 2, 3},
+ {1, 4, 3, 2, 1, 0, 1, 2, 3},
+ {1, 2, 3, 2, 1, 0, 0, 0, 1},
+ {1, 2, 3, 4, 3, 2, 1, 0, 1},
+ {1, 0, 1, 2, 3, 2, 1, 0, 0}
+};
+
+
+/*=====================================================================
+ Function: FindHalfPelMB
+ Date: 10/7/2000
+ Purpose: Find half pel resolution MV surrounding the full-pel MV
+=====================================================================*/
+
+void FindHalfPelMB(VideoEncData *video, UChar *cur, MOT *mot, UChar *ncand,
+ Int xpos, Int ypos, Int *xhmin, Int *yhmin, Int hp_guess)
+{
+// hp_mem = ULong *vertArray; /* 20x17 */
+// ULong *horzArray; /* 20x16 */
+// ULong *diagArray; /* 20x17 */
+ Int dmin, d;
+
+ Int xh, yh;
+ Int k, kmin = 0;
+ Int imin, jmin, ilow, jlow;
+ Int h263_mode = video->encParams->H263_Enabled; /* 3/29/01 */
+ Int in_range[9] = {0, 1, 1, 1, 1, 1, 1, 1, 1}; /* 3/29/01 */
+ Int range = video->encParams->SearchRange;
+ Int lx = video->currVop->pitch;
+ Int width = video->currVop->width; /* padding */
+ Int height = video->vol[video->currLayer]->height;
+ Int(**SAD_MB_HalfPel)(UChar*, UChar*, Int, void*) =
+ video->functionPointer->SAD_MB_HalfPel;
+ void *extra_info = video->sad_extra_info;
+
+ Int next_hp_pos[9][2] = {{0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}, {0, -1}};
+ Int next_ncand[9] = {0, 1 , lx, lx, 0, -1, -1, -lx, -lx};
+
+ cur = video->currYMB;
+
+ /**************** check range ***************************/
+ /* 3/29/01 */
+ imin = xpos + (mot[0].x >> 1);
+ jmin = ypos + (mot[0].y >> 1);
+ ilow = xpos - range;
+ jlow = ypos - range;
+
+ if (!h263_mode)
+ {
+ if (imin <= -15 || imin == ilow)
+ in_range[1] = in_range[7] = in_range[8] = 0;
+ else if (imin >= width - 1)
+ in_range[3] = in_range[4] = in_range[5] = 0;
+ if (jmin <= -15 || jmin == jlow)
+ in_range[1] = in_range[2] = in_range[3] = 0;
+ else if (jmin >= height - 1)
+ in_range[5] = in_range[6] = in_range[7] = 0;
+ }
+ else
+ {
+ if (imin <= 0 || imin == ilow)
+ in_range[1] = in_range[7] = in_range[8] = 0;
+ else if (imin >= width - 16)
+ in_range[3] = in_range[4] = in_range[5] = 0;
+ if (jmin <= 0 || jmin == jlow)
+ in_range[1] = in_range[2] = in_range[3] = 0;
+ else if (jmin >= height - 16)
+ in_range[5] = in_range[6] = in_range[7] = 0;
+ }
+
+ xhmin[0] = 0;
+ yhmin[0] = 0;
+ dmin = mot[0].sad;
+
+ xh = 0;
+ yh = -1;
+ ncand -= lx; /* initial position */
+
+ for (k = 2; k <= 8; k += 2)
+ {
+ if (distance_tab[hp_guess][k] < HP_DISTANCE_TH)
+ {
+ if (in_range[k])
+ {
+ d = (*(SAD_MB_HalfPel[((yh&1)<<1)+(xh&1)]))(ncand, cur, (dmin << 16) | lx, extra_info);
+
+ if (d < dmin)
+ {
+ dmin = d;
+ xhmin[0] = xh;
+ yhmin[0] = yh;
+ kmin = k;
+ }
+ else if (d == dmin &&
+ PV_ABS(mot[0].x + xh) + PV_ABS(mot[0].y + yh) < PV_ABS(mot[0].x + xhmin[0]) + PV_ABS(mot[0].y + yhmin[0]))
+ {
+ xhmin[0] = xh;
+ yhmin[0] = yh;
+ kmin = k;
+ }
+
+ }
+ }
+ xh += next_hp_pos[k][0];
+ yh += next_hp_pos[k][1];
+ ncand += next_ncand[k];
+
+ if (k == 8)
+ {
+ if (xhmin[0] != 0 || yhmin[0] != 0)
+ {
+ k = -1;
+ hp_guess = kmin;
+ }
+ }
+ }
+
+ mot[0].sad = dmin;
+ mot[0].x += xhmin[0];
+ mot[0].y += yhmin[0];
+
+ return ;
+}
+
+#ifndef NO_INTER4V
+/*=====================================================================
+ Function: FindHalfPelBlk
+ Date: 10/7/2000
+ Purpose: Find half pel resolution MV surrounding the full-pel MV
+ And decide between 1MV or 4MV mode
+=====================================================================*/
+///// THIS FUNCTION IS NOT WORKING!!! NEED TO BE RIVISITED
+
+Int FindHalfPelBlk(VideoEncData *video, UChar *cur, MOT *mot, Int sad16, UChar *ncand8[],
+ UChar *mode, Int xpos, Int ypos, Int *xhmin, Int *yhmin, UChar *hp_mem)
+{
+ Int k, comp;
+ Int xh, yh;//, xhmin, yhmin;
+ Int imin, jmin, ilow, jlow;
+ Int height;
+ UChar *cand, *cur8;
+ UChar *hmem;//[17*17]; /* half-pel memory */
+ Int d, dmin, sad8;
+ Int lx = video->currVop->pitch;
+ Int width = video->currVop->width; /* , padding */
+ Int(*SAD_Blk_HalfPel)(UChar*, UChar*, Int, Int, Int, Int, Int, void*) = video->functionPointer->SAD_Blk_HalfPel;
+ void *extra_info = video->sad_extra_info;
+ Int in_range[8]; /* 3/29/01 */
+ Int range = video->encParams->SearchRange;
+ Int swidth;
+ Int next_hp_pos[8][2] = {{1, 0}, {1, 0}, {0, 1}, {0, 1}, { -1, 0}, { -1, 0}, {0, -1}, {0, -1}};
+
+ height = video->vol[video->currLayer]->height;
+
+ hmem = hp_mem;
+ sad8 = 0;
+ for (comp = 0; comp < 4; comp++)
+ {
+#ifdef _SAD_STAT
+ num_HP_Blk++;
+#endif
+ /**************** check range ***************************/
+ /* 3/29/01 */
+ M4VENC_MEMSET(in_range, 1, sizeof(Int) << 3);
+ imin = xpos + ((comp & 1) << 3) + (mot[comp+1].x >> 1);
+ jmin = ypos + ((comp & 2) << 2) + (mot[comp+1].y >> 1);
+ ilow = xpos + ((comp & 1) << 3) - range;
+ jlow = ypos + ((comp & 2) << 2) - range;
+
+ if (imin <= -15 || imin == ilow)
+ in_range[0] = in_range[6] = in_range[7] = 0;
+ else if (imin >= width - 1)
+ in_range[2] = in_range[3] = in_range[4] = 0;
+
+ if (jmin <= -15 || jmin == jlow)
+ in_range[0] = in_range[1] = in_range[2] = 0;
+ else if (jmin >= height - 1)
+ in_range[4] = in_range[5] = in_range[6] = 0;
+
+ /**************** half-pel search ***********************/
+ cur8 = cur + ((comp & 1) << 3) + ((comp & 2) << 2) * width ;
+
+ /* generate half-pel search region */
+ {
+ cand = ncand8[comp+1];
+ swidth = lx;
+ }
+
+ xhmin[comp+1] = 0;
+ yhmin[comp+1] = 0;
+ dmin = mot[comp+1].sad;
+
+ xh = -1;
+ yh = -1;
+ for (k = 0; k < 8; k++)
+ {
+ if (in_range[k])
+ {
+ d = (*SAD_Blk_HalfPel)(cand, cur8, dmin, lx, swidth, xh, yh, extra_info);
+
+ if (d < dmin)
+ {
+ dmin = d;
+ xhmin[comp+1] = xh;
+ yhmin[comp+1] = yh;
+ }
+ }
+ xh += next_hp_pos[k][0];
+ yh += next_hp_pos[k][1];
+ }
+ /********************************************/
+ mot[comp+1].x += xhmin[comp+1];
+ mot[comp+1].y += yhmin[comp+1];
+ mot[comp+1].sad = dmin;
+ sad8 += dmin;
+
+ if (sad8 >= sad16 - PREF_16_VEC)
+ {
+ *mode = MODE_INTER;
+ for (k = 1; k <= 4; k++)
+ {
+ mot[k].sad = (mot[0].sad + 2) >> 2;
+ mot[k].x = mot[0].x;
+ mot[k].y = mot[0].y;
+ }
+ return sad8;
+ }
+
+ hmem += (10 * 10);
+ }
+
+ *mode = MODE_INTER4V;
+
+ return sad8;
+}
+#endif /* NO_INTER4V */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h b/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h
new file mode 100644
index 0000000..c9e18d5
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/m4venc_oscl.h
@@ -0,0 +1,43 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/* Revision History */
+/* Date: 11/04/05 */
+/* Description: Created for abstracting out OSCL such that the code can be used */
+/* by both V3 and V4 OSCL library. This file is for V4. */
+/*********************************************************************************/
+
+#ifndef _M4VENC_OSCL_H_
+#define _M4VENC_OSCL_H_
+
+#include <stdlib.h>
+#include <math.h>
+
+#define M4VENC_MALLOC(size) malloc(size)
+#define M4VENC_FREE(ptr) free(ptr)
+
+#define M4VENC_MEMSET(ptr,val,size) memset(ptr,val,size)
+#define M4VENC_MEMCPY(dst,src,size) memcpy(dst,src,size)
+
+#define M4VENC_LOG(x) log(x)
+#define M4VENC_SQRT(x) sqrt(x)
+#define M4VENC_POW(x,y) pow(x,y)
+
+#define M4VENC_HAS_SYMBIAN_SUPPORT OSCL_HAS_SYMBIAN_SUPPORT
+
+#endif //_M4VENC_OSCL_H_
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp
new file mode 100644
index 0000000..6dab31a
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/me_utils.cpp
@@ -0,0 +1,386 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "m4venc_oscl.h"
+
+#define VOP_OFFSET ((lx<<4)+16) /* for offset to image area */
+#define CVOP_OFFSET ((lx<<2)+8)
+
+#define PREF_INTRA 512 /* bias for INTRA coding */
+
+/*===============================================================
+ Function: ChooseMode
+ Date: 09/21/2000
+ Purpose: Choosing between INTRA or INTER
+ Input/Output: Pointer to the starting point of the macroblock.
+ Note:
+===============================================================*/
+void ChooseMode_C(UChar *Mode, UChar *cur, Int lx, Int min_SAD)
+{
+ Int i, j;
+ Int MB_mean, A, tmp, Th;
+ Int offset = (lx >> 2) - 4;
+ UChar *p = cur;
+ Int *pint = (Int *) cur, temp = 0;
+ MB_mean = 0;
+ A = 0;
+ Th = (min_SAD - PREF_INTRA) >> 1;
+
+ for (j = 0; j < 8; j++)
+ {
+
+ /* Odd Rows */
+ temp += (*pint++) & 0x00FF00FF;
+ temp += (*pint++) & 0x00FF00FF;
+ temp += (*pint++) & 0x00FF00FF;
+ temp += (*pint++) & 0x00FF00FF;
+ pint += offset;
+
+ /* Even Rows */
+ temp += (*pint++ >> 8) & 0x00FF00FF;
+ temp += (*pint++ >> 8) & 0x00FF00FF;
+ temp += (*pint++ >> 8) & 0x00FF00FF;
+ temp += (*pint++ >> 8) & 0x00FF00FF;
+ pint += offset;
+
+ }
+
+ MB_mean = (((temp & 0x0000FFFF)) + ((temp & 0xFFFF0000) >> 16)) >> 7;
+
+ p = cur;
+ offset = lx - 16;
+ for (j = 0; j < 16; j++)
+ {
+ temp = (j & 1);
+ p += temp;
+ i = 8;
+ while (i--)
+ {
+ tmp = *p - MB_mean;
+ p += 2;
+ if (tmp > 0) A += tmp;
+ else A -= tmp;
+ }
+
+ if (A >= Th)
+ {
+ *Mode = MODE_INTER;
+ return ;
+ }
+ p += (offset - temp);
+ }
+
+ if (A < Th)
+ *Mode = MODE_INTRA;
+ else
+ *Mode = MODE_INTER;
+
+ return ;
+}
+
+
+/*===============================================================
+ Function: GetHalfPelMBRegion
+ Date: 09/17/2000
+ Purpose: Interpolate the search region for half-pel search
+ Input/Output: Center of the search, Half-pel memory, width
+ Note: rounding type should be parameterized.
+ Now fixed it to zero!!!!!!
+
+===============================================================*/
+
+
+void GetHalfPelMBRegion_C(UChar *cand, UChar *hmem, Int lx)
+{
+ Int i, j;
+ UChar *p1, *p2, *p3, *p4;
+ UChar *hmem1 = hmem;
+ UChar *hmem2 = hmem1 + 33;
+ Int offset = lx - 17;
+
+ p1 = cand - lx - 1;
+ p2 = cand - lx;
+ p3 = cand - 1;
+ p4 = cand;
+
+ for (j = 0; j < 16; j++)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ *hmem1++ = ((*p1++) + *p2 + *p3 + *p4 + 2) >> 2;
+ *hmem1++ = ((*p2++) + *p4 + 1) >> 1;
+ *hmem2++ = ((*p3++) + *p4 + 1) >> 1;
+ *hmem2++ = *p4++;
+ }
+ /* last pixel */
+ *hmem1++ = ((*p1++) + (*p2++) + *p3 + *p4 + 2) >> 2;
+ *hmem2++ = ((*p3++) + (*p4++) + 1) >> 1;
+ hmem1 += 33;
+ hmem2 += 33;
+ p1 += offset;
+ p2 += offset;
+ p3 += offset;
+ p4 += offset;
+ }
+ /* last row */
+ for (i = 0; i < 16; i++)
+ {
+ *hmem1++ = ((*p1++) + *p2 + (*p3++) + *p4 + 2) >> 2;
+ *hmem1++ = ((*p2++) + (*p4++) + 1) >> 1;
+
+ }
+ *hmem1 = (*p1 + *p2 + *p3 + *p4 + 2) >> 2;
+
+ return ;
+}
+
+/*===============================================================
+ Function: GetHalfPelBlkRegion
+ Date: 09/20/2000
+ Purpose: Interpolate the search region for half-pel search
+ in 4MV mode.
+ Input/Output: Center of the search, Half-pel memory, width
+ Note: rounding type should be parameterized.
+ Now fixed it to zero!!!!!!
+
+===============================================================*/
+
+
+void GetHalfPelBlkRegion(UChar *cand, UChar *hmem, Int lx)
+{
+ Int i, j;
+ UChar *p1, *p2, *p3, *p4;
+ UChar *hmem1 = hmem;
+ UChar *hmem2 = hmem1 + 17;
+ Int offset = lx - 9;
+
+ p1 = cand - lx - 1;
+ p2 = cand - lx;
+ p3 = cand - 1;
+ p4 = cand;
+
+ for (j = 0; j < 8; j++)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ *hmem1++ = ((*p1++) + *p2 + *p3 + *p4 + 2) >> 2;
+ *hmem1++ = ((*p2++) + *p4 + 1) >> 1;
+ *hmem2++ = ((*p3++) + *p4 + 1) >> 1;
+ *hmem2++ = *p4++;
+ }
+ /* last pixel */
+ *hmem1++ = ((*p1++) + (*p2++) + *p3 + *p4 + 2) >> 2;
+ *hmem2++ = ((*p3++) + (*p4++) + 1) >> 1;
+ hmem1 += 17;
+ hmem2 += 17;
+ p1 += offset;
+ p2 += offset;
+ p3 += offset;
+ p4 += offset;
+ }
+ /* last row */
+ for (i = 0; i < 8; i++)
+ {
+ *hmem1++ = ((*p1++) + *p2 + (*p3++) + *p4 + 2) >> 2;
+ *hmem1++ = ((*p2++) + (*p4++) + 1) >> 1;
+
+ }
+ *hmem1 = (*p1 + *p2 + *p3 + *p4 + 2) >> 2;
+
+ return ;
+}
+
+
+/*=====================================================================
+ Function: PaddingEdge
+ Date: 09/16/2000
+ Purpose: Pad edge of a Vop
+ Modification: 09/20/05.
+=====================================================================*/
+
+void PaddingEdge(Vop *refVop)
+{
+ UChar *src, *dst;
+ Int i;
+ Int pitch, width, height;
+ ULong temp1, temp2;
+
+ width = refVop->width;
+ height = refVop->height;
+ pitch = refVop->pitch;
+
+ /* pad top */
+ src = refVop->yChan;
+
+ temp1 = *src; /* top-left corner */
+ temp2 = src[width-1]; /* top-right corner */
+ temp1 |= (temp1 << 8);
+ temp1 |= (temp1 << 16);
+ temp2 |= (temp2 << 8);
+ temp2 |= (temp2 << 16);
+
+ dst = src - (pitch << 4);
+
+ *((ULong*)(dst - 16)) = temp1;
+ *((ULong*)(dst - 12)) = temp1;
+ *((ULong*)(dst - 8)) = temp1;
+ *((ULong*)(dst - 4)) = temp1;
+
+ M4VENC_MEMCPY(dst, src, width);
+
+ *((ULong*)(dst += width)) = temp2;
+ *((ULong*)(dst + 4)) = temp2;
+ *((ULong*)(dst + 8)) = temp2;
+ *((ULong*)(dst + 12)) = temp2;
+
+ dst = dst - width - 16;
+
+ i = 15;
+ while (i--)
+ {
+ M4VENC_MEMCPY(dst + pitch, dst, pitch);
+ dst += pitch;
+ }
+
+ /* pad sides */
+ dst += (pitch + 16);
+ src = dst;
+ i = height;
+ while (i--)
+ {
+ temp1 = *src;
+ temp2 = src[width-1];
+ temp1 |= (temp1 << 8);
+ temp1 |= (temp1 << 16);
+ temp2 |= (temp2 << 8);
+ temp2 |= (temp2 << 16);
+
+ *((ULong*)(dst - 16)) = temp1;
+ *((ULong*)(dst - 12)) = temp1;
+ *((ULong*)(dst - 8)) = temp1;
+ *((ULong*)(dst - 4)) = temp1;
+
+ *((ULong*)(dst += width)) = temp2;
+ *((ULong*)(dst + 4)) = temp2;
+ *((ULong*)(dst + 8)) = temp2;
+ *((ULong*)(dst + 12)) = temp2;
+
+ src += pitch;
+ dst = src;
+ }
+
+ /* pad bottom */
+ dst -= 16;
+ i = 16;
+ while (i--)
+ {
+ M4VENC_MEMCPY(dst, dst - pitch, pitch);
+ dst += pitch;
+ }
+
+
+ return ;
+}
+
+/*===================================================================
+ Function: ComputeMBSum
+ Date: 10/28/2000
+ Purpose: Compute sum of absolute value (SAV) of blocks in a macroblock
+ in INTRA mode needed for rate control. Thus, instead of
+ computing the SAV, we can compute first order moment or
+ variance .
+
+ 11/28/00: add MMX
+ 9/3/01: do parallel comp for C function.
+===================================================================*/
+void ComputeMBSum_C(UChar *cur, Int lx, MOT *mot_mb)
+{
+ Int j;
+ Int *cInt, *cInt2;
+ Int sad1 = 0, sad2 = 0, sad3 = 0, sad4 = 0;
+ Int tmp, tmp2, mask = 0x00FF00FF;
+
+ cInt = (Int*)cur; /* make sure this is word-align */
+ cInt2 = (Int*)(cur + (lx << 3));
+ j = 8;
+ while (j--)
+ {
+ tmp = cInt[3]; /* load 4 pixels at a time */
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad2 += tmp;
+ tmp = cInt[2];
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad2 += tmp;
+ tmp = cInt[1];
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad1 += tmp;
+ tmp = *cInt;
+ cInt += (lx >> 2);
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad1 += tmp;
+
+ tmp = cInt2[3];
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad4 += tmp;
+ tmp = cInt2[2];
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad4 += tmp;
+ tmp = cInt2[1];
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad3 += tmp;
+ tmp = *cInt2;
+ cInt2 += (lx >> 2);
+ tmp2 = tmp & mask;
+ tmp = (tmp >> 8) & mask;
+ tmp += tmp2;
+ sad3 += tmp;
+ }
+ sad1 += (sad1 << 16);
+ sad2 += (sad2 << 16);
+ sad3 += (sad3 << 16);
+ sad4 += (sad4 << 16);
+ sad1 >>= 16;
+ sad2 >>= 16;
+ sad3 >>= 16;
+ sad4 >>= 16;
+
+ mot_mb[1].sad = sad1;
+ mot_mb[2].sad = sad2;
+ mot_mb[3].sad = sad3;
+ mot_mb[4].sad = sad4;
+ mot_mb[0].sad = sad1 + sad2 + sad3 + sad4;
+
+ return ;
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp
new file mode 100644
index 0000000..b81d278
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_comp.cpp
@@ -0,0 +1,1965 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+
+//const static Int roundtab4[] = {0,1,1,1};
+//const static Int roundtab8[] = {0,0,1,1,1,1,1,2};
+//const static Int roundtab12[] = {0,0,0,1,1,1,1,1,1,1,2,2};
+const static Int roundtab16[] = {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2};
+
+#define FORWARD_MODE 1
+#define BACKWARD_MODE 2
+#define BIDIRECTION_MODE 3
+#define DIRECT_MODE 4
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /*Function Prototype */
+ /* no-edge padding */
+ Int EncGetPredOutside(Int xpos, Int ypos, UChar *c_prev, UChar *rec,
+ Int width, Int height, Int rnd1);
+
+ void Copy_MB_from_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int width);
+ void Copy_B_from_Vop(UChar *comp, Int cChan[], Int width);
+ void Copy_MB_into_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int width);
+ void Copy_B_into_Vop(UChar *comp, Int cChan[], Int width);
+ void get_MB(UChar *c_prev, UChar *c_prev_u , UChar *c_prev_v,
+ Short mb[6][64], Int lx, Int lx_uv);
+
+ Int GetPredAdvBy0x0(
+ UChar *c_prev, /* i */
+ UChar *pred_block, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+ );
+
+ Int GetPredAdvBy0x1(
+ UChar *c_prev, /* i */
+ UChar *pred_block, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+ );
+
+ Int GetPredAdvBy1x0(
+ UChar *c_prev, /* i */
+ UChar *pred_block, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+ );
+
+ Int GetPredAdvBy1x1(
+ UChar *c_prev, /* i */
+ UChar *pred_block, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+ );
+
+ static Int(*const GetPredAdvBTable[2][2])(UChar*, UChar*, Int, Int) =
+ {
+ {&GetPredAdvBy0x0, &GetPredAdvBy0x1},
+ {&GetPredAdvBy1x0, &GetPredAdvBy1x1}
+ };
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* ======================================================================== */
+/* Function : getMotionCompensatedMB( ) */
+/* Date : 4/17/2001 */
+/* Purpose : Get the motion compensate block into video->predictionMB */
+/* and generate video->predictionErrorMB */
+/* modified from MBMotionComp() function in the decoder */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+void getMotionCompensatedMB(VideoEncData *video, Int ind_x, Int ind_y, Int offset)
+{
+ Vop *prevVop = video->forwardRefVop; //reference frame
+ Vop *currVop = video->currVop;
+ Int mbnum = video->mbnum; //mb index
+ MOT *mot = video->mot[mbnum];
+ Int ypos, xpos;
+ UChar *c_prev, *cu_prev, *cv_prev;
+ UChar *c_rec, *cu_rec, *cv_rec;
+ Int height, pitch, pitch_uv, height_uv;
+ Int mode = video->headerInfo.Mode[mbnum]; /* get mode */
+ Int dx, dy;
+ Int xpred, ypred;
+ Int xsum, ysum;
+ Int round1;
+
+ OSCL_UNUSED_ARG(offset);
+
+ round1 = (Int)(1 - video->currVop->roundingType);
+
+ pitch = currVop->pitch;
+ height = currVop->height;
+ pitch_uv = pitch >> 1;
+ height_uv = height >> 1;
+
+ ypos = ind_y << 4 ;
+ xpos = ind_x << 4 ;
+
+ c_rec = video->predictedMB;
+ cu_rec = video->predictedMB + 256;
+ cv_rec = video->predictedMB + 264;
+
+ if (mode == MODE_INTER || mode == MODE_INTER_Q)
+ {
+ /* Motion vector in x direction */
+ dx = mot[0].x;
+ dy = mot[0].y;
+
+ c_prev = prevVop->yChan;
+
+ xpred = (xpos << 1) + dx ;
+ ypred = (ypos << 1) + dy ;
+
+ /* Call function that performs luminance prediction */
+ EncPrediction_INTER(xpred, ypred, c_prev, c_rec,
+ pitch, round1);
+
+ if ((dx & 3) == 0) dx = dx >> 1;
+ else dx = (dx >> 1) | 1;
+
+ if ((dy & 3) == 0) dy = dy >> 1;
+ else dy = (dy >> 1) | 1;
+
+ xpred = xpos + dx;
+ ypred = ypos + dy;
+
+ cu_prev = prevVop->uChan;
+ cv_prev = prevVop->vChan;
+
+ EncPrediction_Chrom(xpred, ypred, cu_prev, cv_prev, cu_rec, cv_rec,
+ pitch_uv, (currVop->width) >> 1, height_uv, round1);
+ }
+#ifndef NO_INTER4V
+ else if (mode == MODE_INTER4V)
+ {
+ c_prev = prevVop->yChan;
+ cu_prev = prevVop->uChan;
+ cv_prev = prevVop->vChan;
+
+ EncPrediction_INTER4V(xpos, ypos, mot, c_prev, c_rec,
+ pitch, round1);
+
+ xsum = mot[1].x + mot[2].x + mot[3].x + mot[4].x;
+ ysum = mot[1].y + mot[2].y + mot[3].y + mot[4].y;
+
+ dx = PV_SIGN(xsum) * (roundtab16[(PV_ABS(xsum)) & 0xF] +
+ (((PV_ABS(xsum)) >> 4) << 1));
+ dy = PV_SIGN(ysum) * (roundtab16[(PV_ABS(ysum)) & 0xF] +
+ (((PV_ABS(ysum)) >> 4) << 1));
+
+ ypred = ypos + dy;
+ xpred = xpos + dx;
+
+ EncPrediction_Chrom(xpred, ypred, cu_prev, cv_prev, cu_rec, cv_rec,
+ pitch_uv, (currVop->width) >> 1, height_uv, round1);
+ }
+#endif
+ else
+ {
+ ;//printf("Error, MODE_SKIPPED is not decided yet!\n");
+ }
+
+ return ;
+}
+
+/***************************************************************************
+ Function: EncPrediction_INTER
+ Date: 04/17/2001
+ Purpose: Get predicted area for luminance and compensate with the residue.
+ Modified from luminance_pred_mode_inter() in decoder.
+***************************************************************************/
+
+void EncPrediction_INTER(
+ Int xpred, /* i */
+ Int ypred, /* i */
+ UChar *c_prev, /* i */
+ UChar *c_rec, /* i */
+ Int lx, /* i */
+ Int round1 /* i */
+)
+{
+ c_prev += (xpred >> 1) + ((ypred >> 1) * lx);
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+ c_prev += B_SIZE;
+ c_rec += B_SIZE;
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+ c_prev += (lx << 3) - B_SIZE;
+ c_rec += (16 << 3) - B_SIZE; /* padding */
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+ c_prev += B_SIZE;
+ c_rec += B_SIZE;
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev, c_rec, lx, round1);
+
+ return;
+}
+
+#ifndef NO_INTER4V
+/***************************************************************************
+ Function: EncPrediction_INTER4V
+ Date: 04/17/2001
+ Purpose: Get predicted area for luminance and compensate with the residue.
+ Modified from luminance_pred_mode_inter4v() in decoder.
+***************************************************************************/
+
+void EncPrediction_INTER4V(
+ Int xpos, /* i */
+ Int ypos, /* i */
+ MOT *mot, /* i */
+ UChar *c_prev, /* i */
+ UChar *c_rec, /* i */
+ Int lx, /* i */
+ Int round1 /* i */
+)
+{
+ Int ypred, xpred;
+
+ xpred = (Int)((xpos << 1) + mot[1].x);
+ ypred = (Int)((ypos << 1) + mot[1].y);
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+ c_rec, lx, round1);
+
+ c_rec += B_SIZE;
+
+ xpred = (Int)(((xpos + B_SIZE) << 1) + mot[2].x);
+ ypred = (Int)((ypos << 1) + mot[2].y);
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+ c_rec, lx, round1);
+
+ c_rec += (16 << 3) - B_SIZE; /* padding */
+
+ xpred = (Int)((xpos << 1) + mot[3].x);
+ ypred = (Int)(((ypos + B_SIZE) << 1) + mot[3].y);
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+ c_rec, lx, round1);
+
+ c_rec += B_SIZE;
+
+ xpred = (Int)(((xpos + B_SIZE) << 1) + mot[4].x);
+ ypred = (Int)(((ypos + B_SIZE) << 1) + mot[4].y);
+
+ GetPredAdvBTable[ypred&1][xpred&1](c_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+ c_rec, lx, round1);
+
+ return;
+}
+#endif /* NO_INTER4V */
+
+/***************************************************************************
+ Function: EncPrediction_Chrom
+ Date: 04/17/2001
+ Purpose: Get predicted area for chrominance and compensate with the residue.
+ Modified from chrominance_pred() in decoder.
+***************************************************************************/
+
+void EncPrediction_Chrom(
+ Int xpred, /* i */
+ Int ypred, /* i */
+ UChar *cu_prev, /* i */
+ UChar *cv_prev, /* i */
+ UChar *cu_rec,
+ UChar *cv_rec,
+ Int lx,
+ Int width_uv, /* i */
+ Int height_uv, /* i */
+ Int round1 /* i */
+)
+{
+ /* check whether the MV points outside the frame */
+ /* Compute prediction for Chrominance b block (block[4]) */
+ if (xpred >= 0 && xpred <= ((width_uv << 1) - (2*B_SIZE)) && ypred >= 0 &&
+ ypred <= ((height_uv << 1) - (2*B_SIZE)))
+ {
+ /*****************************/
+ /* (x,y) is inside the frame */
+ /*****************************/
+
+ /* Compute prediction for Chrominance b (block[4]) */
+ GetPredAdvBTable[ypred&1][xpred&1](cu_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+ cu_rec, lx, round1);
+
+ /* Compute prediction for Chrominance r (block[5]) */
+ GetPredAdvBTable[ypred&1][xpred&1](cv_prev + (xpred >> 1) + ((ypred >> 1)*lx),
+ cv_rec, lx, round1);
+ }
+ else
+ {
+ /******************************/
+ /* (x,y) is outside the frame */
+ /******************************/
+
+ /* Compute prediction for Chrominance b (block[4]) */
+ EncGetPredOutside(xpred, ypred,
+ cu_prev, cu_rec,
+ width_uv, height_uv, round1);
+
+ /* Compute prediction for Chrominance r (block[5]) */
+ EncGetPredOutside(xpred, ypred,
+ cv_prev, cv_rec,
+ width_uv, height_uv, round1);
+ }
+
+ return;
+}
+/***************************************************************************
+ Function: GetPredAdvancedB
+ Date: 04/17/2001
+ Purpose: Get predicted area (block) and compensate with the residue.
+ - modified from GetPredAdvancedBAdd in decoder.
+ Intput/Output:
+ Modified:
+***************************************************************************/
+
+Int GetPredAdvBy0x0(
+ UChar *prev, /* i */
+ UChar *rec, /* i */
+ Int lx, /* i */
+ Int rnd /* i */
+)
+{
+ Int i; /* loop variable */
+ ULong pred_word, word1, word2;
+ Int tmp;
+
+ OSCL_UNUSED_ARG(rnd);
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+
+ tmp = (ULong)prev & 0x3;
+
+ if (tmp == 0) /* word-aligned */
+ {
+ rec -= 16; /* preset */
+ prev -= lx;
+
+ for (i = 8; i > 0; i--)
+ {
+ *((ULong*)(rec += 16)) = *((ULong*)(prev += lx));
+ *((ULong*)(rec + 4)) = *((ULong*)(prev + 4));
+ }
+ return 1;
+ }
+ else if (tmp == 1) /* first position */
+ {
+ prev--; /* word-aligned */
+ rec -= 16; /* preset */
+ prev -= lx;
+
+ for (i = 8; i > 0; i--)
+ {
+ word1 = *((ULong*)(prev += lx)); /* read 4 bytes, b4 b3 b2 b1 */
+ word2 = *((ULong*)(prev + 4)); /* read 4 bytes, b8 b7 b6 b5 */
+ word1 >>= 8; /* 0 b4 b3 b2 */
+ pred_word = word1 | (word2 << 24); /* b5 b4 b3 b2 */
+ *((ULong*)(rec += 16)) = pred_word;
+
+ word1 = *((ULong*)(prev + 8)); /* b12 b11 b10 b9 */
+ word2 >>= 8; /* 0 b8 b7 b6 */
+ pred_word = word2 | (word1 << 24); /* b9 b8 b7 b6 */
+ *((ULong*)(rec + 4)) = pred_word;
+ }
+
+ return 1;
+ }
+ else if (tmp == 2) /* second position */
+ {
+ prev -= 2; /* word1-aligned */
+ rec -= 16; /* preset */
+ prev -= lx;
+
+ for (i = 8; i > 0; i--)
+ {
+ word1 = *((ULong*)(prev += lx)); /* read 4 bytes, b4 b3 b2 b1 */
+ word2 = *((ULong*)(prev + 4)); /* read 4 bytes, b8 b7 b6 b5 */
+ word1 >>= 16; /* 0 0 b4 b3 */
+ pred_word = word1 | (word2 << 16); /* b6 b5 b4 b3 */
+ *((ULong*)(rec += 16)) = pred_word;
+
+ word1 = *((ULong*)(prev + 8)); /* b12 b11 b10 b9 */
+ word2 >>= 16; /* 0 0 b8 b7 */
+ pred_word = word2 | (word1 << 16); /* b10 b9 b8 b7 */
+ *((ULong*)(rec + 4)) = pred_word;
+ }
+
+ return 1;
+ }
+ else /* third position */
+ {
+ prev -= 3; /* word1-aligned */
+ rec -= 16; /* preset */
+ prev -= lx;
+
+ for (i = 8; i > 0; i--)
+ {
+ word1 = *((ULong*)(prev += lx)); /* read 4 bytes, b4 b3 b2 b1 */
+ word2 = *((ULong*)(prev + 4)); /* read 4 bytes, b8 b7 b6 b5 */
+ word1 >>= 24; /* 0 0 0 b4 */
+ pred_word = word1 | (word2 << 8); /* b7 b6 b5 b4 */
+ *((ULong*)(rec += 16)) = pred_word;
+
+ word1 = *((ULong*)(prev + 8)); /* b12 b11 b10 b9 */
+ word2 >>= 24; /* 0 0 0 b8 */
+ pred_word = word2 | (word1 << 8); /* b11 b10 b9 b8 */
+ *((ULong*)(rec + 4)) = pred_word;
+
+ }
+
+ return 1;
+ }
+}
+/**************************************************************************/
+Int GetPredAdvBy0x1(
+ UChar *prev, /* i */
+ UChar *rec, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+)
+{
+ Int i; /* loop variable */
+ Int offset;
+ ULong word1, word2, word3, word12;
+ Int tmp;
+ ULong mask;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = lx - B_SIZE; /* offset for prev */
+
+ /* Branch based on pixel location (half-pel or full-pel) for x and y */
+ rec -= 12; /* preset */
+
+ tmp = (ULong)prev & 3;
+ mask = 254;
+ mask |= (mask << 8);
+ mask |= (mask << 16); /* 0xFEFEFEFE */
+
+ if (tmp == 0) /* word-aligned */
+ {
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b4 b3 b2 b1 */
+ word2 = *((ULong*)(prev += 4)); /* b8 b7 b6 b5 */
+ word12 = (word1 >> 8); /* 0 b4 b3 b2 */
+ word12 |= (word2 << 24); /* b5 b4 b3 b2 */
+ word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b12 b11 b10 b9 */
+ word12 = (word2 >> 8); /* 0 b8 b7 b6 */
+ word12 |= (word1 << 24); /* b9 b8 b7 b6 */
+ word3 = word2 | word12;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 == 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b4 b3 b2 b1 */
+
+ word2 = *((ULong*)(prev += 4)); /* b8 b7 b6 b5 */
+ word12 = (word1 >> 8); /* 0 b4 b3 b2 */
+ word12 |= (word2 << 24); /* b5 b4 b3 b2 */
+ word3 = word1 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b12 b11 b10 b9 */
+ word12 = (word2 >> 8); /* 0 b8 b7 b6 */
+ word12 |= (word1 << 24); /* b9 b8 b7 b6 */
+ word3 = word2 & word12;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+ prev += offset;
+ }
+ return 1;
+ } /* rnd1 */
+ }
+ else if (tmp == 1)
+ {
+ prev--; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b3 b2 b1 b0 */
+ word2 = *((ULong*)(prev += 4)); /* b7 b6 b5 b4 */
+ word12 = (word1 >> 8); /* 0 b3 b2 b1 */
+ word1 >>= 16; /* 0 0 b3 b2 */
+ word12 |= (word2 << 24); /* b4 b3 b2 b1 */
+ word1 |= (word2 << 16); /* b5 b4 b3 b2 */
+ word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b11 b10 b9 b8 */
+ word12 = (word2 >> 8); /* 0 b7 b6 b5 */
+ word2 >>= 16; /* 0 0 b7 b6 */
+ word12 |= (word1 << 24); /* b8 b7 b6 b5 */
+ word2 |= (word1 << 16); /* b9 b8 b7 b6 */
+ word3 = word2 | word12; // rnd1 = 1; otherwise word3 = word2&word12
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b3 b2 b1 b0 */
+
+ word2 = *((ULong*)(prev += 4)); /* b7 b6 b5 b4 */
+ word12 = (word1 >> 8); /* 0 b3 b2 b1 */
+ word1 >>= 16; /* 0 0 b3 b2 */
+ word12 |= (word2 << 24); /* b4 b3 b2 b1 */
+ word1 |= (word2 << 16); /* b5 b4 b3 b2 */
+ word3 = word1 & word12;
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b11 b10 b9 b8 */
+ word12 = (word2 >> 8); /* 0 b7 b6 b5 */
+ word2 >>= 16; /* 0 0 b7 b6 */
+ word12 |= (word1 << 24); /* b8 b7 b6 b5 */
+ word2 |= (word1 << 16); /* b9 b8 b7 b6 */
+ word3 = word2 & word12;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+
+ prev += offset;
+ }
+ return 1;
+ } /* rnd1 */
+ }
+ else if (tmp == 2)
+ {
+ prev -= 2; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b2 b1 b0 bN1 */
+ word2 = *((ULong*)(prev += 4)); /* b6 b5 b4 b3 */
+ word12 = (word1 >> 16); /* 0 0 b2 b1 */
+ word1 >>= 24; /* 0 0 0 b2 */
+ word12 |= (word2 << 16); /* b4 b3 b2 b1 */
+ word1 |= (word2 << 8); /* b5 b4 b3 b2 */
+ word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b10 b9 b8 b7 */
+ word12 = (word2 >> 16); /* 0 0 b6 b5 */
+ word2 >>= 24; /* 0 0 0 b6 */
+ word12 |= (word1 << 16); /* b8 b7 b6 b5 */
+ word2 |= (word1 << 8); /* b9 b8 b7 b6 */
+ word3 = word2 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 == 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b2 b1 b0 bN1 */
+ word2 = *((ULong*)(prev += 4)); /* b6 b5 b4 b3 */
+ word12 = (word1 >> 16); /* 0 0 b2 b1 */
+ word1 >>= 24; /* 0 0 0 b2 */
+ word12 |= (word2 << 16); /* b4 b3 b2 b1 */
+ word1 |= (word2 << 8); /* b5 b4 b3 b2 */
+ word3 = word1 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b10 b9 b8 b7 */
+ word12 = (word2 >> 16); /* 0 0 b6 b5 */
+ word2 >>= 24; /* 0 0 0 b6 */
+ word12 |= (word1 << 16); /* b8 b7 b6 b5 */
+ word2 |= (word1 << 8); /* b9 b8 b7 b6 */
+ word3 = word2 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ }
+ else /* tmp = 3 */
+ {
+ prev -= 3; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b1 b0 bN1 bN2 */
+ word2 = *((ULong*)(prev += 4)); /* b5 b4 b3 b2 */
+ word12 = (word1 >> 24); /* 0 0 0 b1 */
+ word12 |= (word2 << 8); /* b4 b3 b2 b1 */
+ word1 = word2;
+ word3 = word1 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b9 b8 b7 b6 */
+ word12 = (word2 >> 24); /* 0 0 0 b5 */
+ word12 |= (word1 << 8); /* b8 b7 b6 b5 */
+ word2 = word1; /* b9 b8 b7 b6 */
+ word3 = word2 | word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ else
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)prev); /* b1 b0 bN1 bN2 */
+ word2 = *((ULong*)(prev += 4)); /* b5 b4 b3 b2 */
+ word12 = (word1 >> 24); /* 0 0 0 b1 */
+ word12 |= (word2 << 8); /* b4 b3 b2 b1 */
+ word1 = word2;
+ word3 = word1 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word12 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1; /* write 4 pixels */
+
+ word1 = *((ULong*)(prev += 4)); /* b9 b8 b7 b6 */
+ word12 = (word2 >> 24); /* 0 0 0 b5 */
+ word12 |= (word1 << 8); /* b8 b7 b6 b5 */
+ word2 = word1; /* b9 b8 b7 b6 */
+ word3 = word2 & word12; // rnd1 = 1; otherwise word3 = word1&word12
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 &= mask;
+ word2 >>= 1;
+ word2 = word2 + (word12 >> 1);
+ word2 += word3;
+ *((ULong*)(rec += 4)) = word2; /* write 4 pixels */
+ prev += offset;
+ }
+ return 1;
+ }
+ }
+}
+
+/**************************************************************************/
+Int GetPredAdvBy1x0(
+ UChar *prev, /* i */
+ UChar *rec, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+)
+{
+ Int i; /* loop variable */
+ Int offset;
+ ULong word1, word2, word3, word12, word22;
+ Int tmp;
+ ULong mask;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = lx - B_SIZE; /* offset for prev */
+
+ /* Branch based on pixel location (half-pel or full-pel) for x and y */
+ rec -= 12; /* preset */
+
+ tmp = (ULong)prev & 3;
+ mask = 254;
+ mask |= (mask << 8);
+ mask |= (mask << 16); /* 0xFEFEFEFE */
+
+ if (tmp == 0) /* word-aligned */
+ {
+ prev -= 4;
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)(prev += 4));
+ word2 = *((ULong*)(prev + lx));
+ word3 = word1 | word2; // rnd1 = 1; otherwise word3 = word1&word2
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word2 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1;
+ word1 = *((ULong*)(prev += 4));
+ word2 = *((ULong*)(prev + lx));
+ word3 = word1 | word2; // rnd1 = 1; otherwise word3 = word1&word2
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word2 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word1 = *((ULong*)(prev += 4));
+ word2 = *((ULong*)(prev + lx));
+ word3 = word1 & word2; /* rnd1 = 0; */
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word2 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 12)) = word1;
+ word1 = *((ULong*)(prev += 4));
+ word2 = *((ULong*)(prev + lx));
+ word3 = word1 & word2; /* rnd1 = 0; */
+ word1 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word2 &= mask;
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+
+ prev += offset;
+ }
+ return 1;
+ }
+ }
+ else if (tmp == 1)
+ {
+ prev--; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((ULong*)(prev + lx));
+
+ word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((ULong*)(prev + lx));
+ word12 >>= 8; /* 0 b4 b3 b2 */
+ word22 >>= 8;
+ word12 = word12 | (word1 << 24); /* b5 b4 b3 b2 */
+ word22 = word22 | (word2 << 24);
+ word3 = word12 | word22;
+ word12 &= mask;
+ word22 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 >>= 1;
+ word12 = word12 + (word22 >> 1);
+ word12 += word3;
+ *((ULong*)(rec += 12)) = word12;
+
+ word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((ULong*)(prev + lx));
+ word1 >>= 8; /* 0 b8 b7 b6 */
+ word2 >>= 8;
+ word1 = word1 | (word12 << 24); /* b9 b8 b7 b6 */
+ word2 = word2 | (word22 << 24);
+ word3 = word1 | word2;
+ word1 &= mask;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((ULong*)(prev + lx));
+
+ word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((ULong*)(prev + lx));
+ word12 >>= 8; /* 0 b4 b3 b2 */
+ word22 >>= 8;
+ word12 = word12 | (word1 << 24); /* b5 b4 b3 b2 */
+ word22 = word22 | (word2 << 24);
+ word3 = word12 & word22;
+ word12 &= mask;
+ word22 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 >>= 1;
+ word12 = word12 + (word22 >> 1);
+ word12 += word3;
+ *((ULong*)(rec += 12)) = word12;
+
+ word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((ULong*)(prev + lx));
+ word1 >>= 8; /* 0 b8 b7 b6 */
+ word2 >>= 8;
+ word1 = word1 | (word12 << 24); /* b9 b8 b7 b6 */
+ word2 = word2 | (word22 << 24);
+ word3 = word1 & word2;
+ word1 &= mask;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ }
+ else if (tmp == 2)
+ {
+ prev -= 2; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((ULong*)(prev + lx));
+
+ word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((ULong*)(prev + lx));
+ word12 >>= 16; /* 0 0 b4 b3 */
+ word22 >>= 16;
+ word12 = word12 | (word1 << 16); /* b6 b5 b4 b3 */
+ word22 = word22 | (word2 << 16);
+ word3 = word12 | word22;
+ word12 &= mask;
+ word22 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 >>= 1;
+ word12 = word12 + (word22 >> 1);
+ word12 += word3;
+ *((ULong*)(rec += 12)) = word12;
+
+ word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((ULong*)(prev + lx));
+ word1 >>= 16; /* 0 0 b8 b7 */
+ word2 >>= 16;
+ word1 = word1 | (word12 << 16); /* b10 b9 b8 b7 */
+ word2 = word2 | (word22 << 16);
+ word3 = word1 | word2;
+ word1 &= mask;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((ULong*)(prev + lx));
+
+ word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((ULong*)(prev + lx));
+ word12 >>= 16; /* 0 0 b4 b3 */
+ word22 >>= 16;
+ word12 = word12 | (word1 << 16); /* b6 b5 b4 b3 */
+ word22 = word22 | (word2 << 16);
+ word3 = word12 & word22;
+ word12 &= mask;
+ word22 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 >>= 1;
+ word12 = word12 + (word22 >> 1);
+ word12 += word3;
+ *((ULong*)(rec += 12)) = word12;
+
+ word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((ULong*)(prev + lx));
+ word1 >>= 16; /* 0 0 b8 b7 */
+ word2 >>= 16;
+ word1 = word1 | (word12 << 16); /* b10 b9 b8 b7 */
+ word2 = word2 | (word22 << 16);
+ word3 = word1 & word2;
+ word1 &= mask;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+ prev += offset;
+ }
+
+ return 1;
+ }
+ }
+ else /* tmp == 3 */
+ {
+ prev -= 3; /* word-aligned */
+ if (rnd1 == 1)
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((ULong*)(prev + lx));
+
+ word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((ULong*)(prev + lx));
+ word12 >>= 24; /* 0 0 0 b4 */
+ word22 >>= 24;
+ word12 = word12 | (word1 << 8); /* b7 b6 b5 b4 */
+ word22 = word22 | (word2 << 8);
+ word3 = word12 | word22;
+ word12 &= mask;
+ word22 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 >>= 1;
+ word12 = word12 + (word22 >> 1);
+ word12 += word3;
+ *((ULong*)(rec += 12)) = word12;
+
+ word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((ULong*)(prev + lx));
+ word1 >>= 24; /* 0 0 0 b8 */
+ word2 >>= 24;
+ word1 = word1 | (word12 << 8); /* b11 b10 b9 b8 */
+ word2 = word2 | (word22 << 8);
+ word3 = word1 | word2;
+ word1 &= mask;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* rnd1 = 0 */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ word12 = *((ULong*)prev); /* read b4 b3 b2 b1 */
+ word22 = *((ULong*)(prev + lx));
+
+ word1 = *((ULong*)(prev += 4)); /* read b8 b7 b6 b5 */
+ word2 = *((ULong*)(prev + lx));
+ word12 >>= 24; /* 0 0 0 b4 */
+ word22 >>= 24;
+ word12 = word12 | (word1 << 8); /* b7 b6 b5 b4 */
+ word22 = word22 | (word2 << 8);
+ word3 = word12 & word22;
+ word12 &= mask;
+ word22 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word12 >>= 1;
+ word12 = word12 + (word22 >> 1);
+ word12 += word3;
+ *((ULong*)(rec += 12)) = word12;
+
+ word12 = *((ULong*)(prev += 4)); /* read b12 b11 b10 b9 */
+ word22 = *((ULong*)(prev + lx));
+ word1 >>= 24; /* 0 0 0 b8 */
+ word2 >>= 24;
+ word1 = word1 | (word12 << 8); /* b11 b10 b9 b8 */
+ word2 = word2 | (word22 << 8);
+ word3 = word1 & word2;
+ word1 &= mask;
+ word2 &= mask;
+ word3 &= (~mask); /* 0x1010101, check last bit */
+ word1 >>= 1;
+ word1 = word1 + (word2 >> 1);
+ word1 += word3;
+ *((ULong*)(rec += 4)) = word1;
+ prev += offset;
+ }
+ return 1;
+ } /* rnd */
+ } /* tmp */
+}
+
+/**********************************************************************************/
+Int GetPredAdvBy1x1(
+ UChar *prev, /* i */
+ UChar *rec, /* i */
+ Int lx, /* i */
+ Int rnd1 /* i */
+)
+{
+ Int i; /* loop variable */
+ Int offset;
+ ULong x1, x2, x1m, x2m, y1, y2, y1m, y2m; /* new way */
+ Int tmp;
+ Int rnd2;
+ ULong mask;
+
+ /* initialize offset to adjust pixel counter */
+ /* the next row; full-pel resolution */
+ offset = lx - B_SIZE; /* offset for prev */
+
+ rnd2 = rnd1 + 1;
+ rnd2 |= (rnd2 << 8);
+ rnd2 |= (rnd2 << 16);
+
+ mask = 0x3F;
+ mask |= (mask << 8);
+ mask |= (mask << 16); /* 0x3f3f3f3f */
+
+ tmp = (ULong)prev & 3;
+
+ rec -= 4; /* preset */
+
+ if (tmp == 0) /* word-aligned */
+ {
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+ y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+ x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+ x2m = (x2 >> 2) & mask;
+ x1 = x1 ^(x1m << 2);
+ x2 = x2 ^(x2m << 2);
+ x1m += x2m;
+ x1 += x2;
+
+ /* x2m, x2 free */
+ y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+ y2m = (y2 >> 2) & mask;
+ y1 = y1 ^(y1m << 2);
+ y2 = y2 ^(y2m << 2);
+ y1m += y2m;
+ y1 += y2;
+
+ /* y2m, y2 free */
+ /* x2m, x2 free */
+ x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+ x2m = (x2 >> 2) & mask;
+ y2m = (y2 >> 2) & mask;
+ x2 = x2 ^(x2m << 2);
+ y2 = y2 ^(y2m << 2);
+ x2m += y2m;
+ x2 += y2;
+ /* y2m, y2 free */
+
+ /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+ /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+ /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+ /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+ /* x1, y1, x2 */
+
+ y2m = x1m >> 8;
+ y2 = x1 >> 8;
+ y2m |= (y1m << 24); /* a4+b4, a3+b3, a2+b2, a1+b1 */
+ y2 |= (y1 << 24);
+ x1m += y2m; /* a3+b3+a4+b4, ....., a0+b0+a1+b1 */
+ x1 += y2;
+ x1 += rnd2;
+ x1 &= (mask << 2);
+ x1m += (x1 >> 2);
+ *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+ y2m = y1m >> 8;
+ y2 = y1 >> 8;
+ y2m |= (x2m << 24); /* a8+b8, a7+b7, a6+b6, a5+b5 */
+ y2 |= (x2 << 24);
+ y1m += y2m; /* a7+b7+a8+b8, ....., a4+b4+a5+b5 */
+ y1 += y2;
+ y1 += rnd2;
+ y1 &= (mask << 2);
+ y1m += (y1 >> 2);
+ *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+ rec += 8;
+ prev += offset;
+ }
+
+ return 1;
+ }
+ else if (tmp == 1)
+ {
+ prev--; /* to word-aligned */
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+ y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+ x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+ x2m = (x2 >> 2) & mask;
+ x1 = x1 ^(x1m << 2);
+ x2 = x2 ^(x2m << 2);
+ x1m += x2m;
+ x1 += x2;
+
+ /* x2m, x2 free */
+ y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+ y2m = (y2 >> 2) & mask;
+ y1 = y1 ^(y1m << 2);
+ y2 = y2 ^(y2m << 2);
+ y1m += y2m;
+ y1 += y2;
+
+ /* y2m, y2 free */
+ /* x2m, x2 free */
+ x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+ x2m = (x2 >> 2) & mask;
+ y2m = (y2 >> 2) & mask;
+ x2 = x2 ^(x2m << 2);
+ y2 = y2 ^(y2m << 2);
+ x2m += y2m;
+ x2 += y2;
+ /* y2m, y2 free */
+
+ /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+ /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+ /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+ /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+ /* x1, y1, x2 */
+
+ x1m >>= 8 ;
+ x1 >>= 8;
+ x1m |= (y1m << 24); /* a4+b4, a3+b3, a2+b2, a1+b1 */
+ x1 |= (y1 << 24);
+ y2m = (y1m << 16);
+ y2 = (y1 << 16);
+ y2m |= (x1m >> 8); /* a5+b5, a4+b4, a3+b3, a2+b2 */
+ y2 |= (x1 >> 8);
+ x1 += rnd2;
+ x1m += y2m; /* a4+b4+a5+b5, ....., a1+b1+a2+b2 */
+ x1 += y2;
+ x1 &= (mask << 2);
+ x1m += (x1 >> 2);
+ *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+ y1m >>= 8;
+ y1 >>= 8;
+ y1m |= (x2m << 24); /* a8+b8, a7+b7, a6+b6, a5+b5 */
+ y1 |= (x2 << 24);
+ y2m = (x2m << 16);
+ y2 = (x2 << 16);
+ y2m |= (y1m >> 8); /* a9+b9, a8+b8, a7+b7, a6+b6,*/
+ y2 |= (y1 >> 8);
+ y1 += rnd2;
+ y1m += y2m; /* a8+b8+a9+b9, ....., a5+b5+a6+b6 */
+ y1 += y2;
+ y1 &= (mask << 2);
+ y1m += (y1 >> 2);
+ *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+ rec += 8;
+ prev += offset;
+ }
+ return 1;
+ }
+ else if (tmp == 2)
+ {
+ prev -= 2; /* to word-aligned */
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+ y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+ x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+ x2m = (x2 >> 2) & mask;
+ x1 = x1 ^(x1m << 2);
+ x2 = x2 ^(x2m << 2);
+ x1m += x2m;
+ x1 += x2;
+
+ /* x2m, x2 free */
+ y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+ y2m = (y2 >> 2) & mask;
+ y1 = y1 ^(y1m << 2);
+ y2 = y2 ^(y2m << 2);
+ y1m += y2m;
+ y1 += y2;
+
+ /* y2m, y2 free */
+ /* x2m, x2 free */
+ x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+ x2m = (x2 >> 2) & mask;
+ y2m = (y2 >> 2) & mask;
+ x2 = x2 ^(x2m << 2);
+ y2 = y2 ^(y2m << 2);
+ x2m += y2m;
+ x2 += y2;
+ /* y2m, y2 free */
+
+ /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+ /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+ /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+ /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+ /* x1, y1, x2 */
+
+ x1m >>= 16 ;
+ x1 >>= 16;
+ x1m |= (y1m << 16); /* a5+b5, a4+b4, a3+b3, a2+b2 */
+ x1 |= (y1 << 16);
+ y2m = (y1m << 8);
+ y2 = (y1 << 8);
+ y2m |= (x1m >> 8); /* a6+b6, a5+b5, a4+b4, a3+b3 */
+ y2 |= (x1 >> 8);
+ x1 += rnd2;
+ x1m += y2m; /* a5+b5+a6+b6, ....., a2+b2+a3+b3 */
+ x1 += y2;
+ x1 &= (mask << 2);
+ x1m += (x1 >> 2);
+ *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+ y1m >>= 16;
+ y1 >>= 16;
+ y1m |= (x2m << 16); /* a9+b9, a8+b8, a7+b7, a6+b6 */
+ y1 |= (x2 << 16);
+ y2m = (x2m << 8);
+ y2 = (x2 << 8);
+ y2m |= (y1m >> 8); /* a10+b10, a9+b9, a8+b8, a7+b7,*/
+ y2 |= (y1 >> 8);
+ y1 += rnd2;
+ y1m += y2m; /* a9+b9+a10+b10, ....., a6+b6+a7+b7 */
+ y1 += y2;
+ y1 &= (mask << 2);
+ y1m += (y1 >> 2);
+ *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+ rec += 8;
+ prev += offset;
+ }
+ return 1;
+ }
+ else /* tmp == 3 */
+ {
+ prev -= 3; /* to word-aligned */
+ for (i = B_SIZE; i > 0; i--)
+ {
+ x1 = *((ULong*)prev); /* load a3 a2 a1 a0 */
+ x2 = *((ULong*)(prev + lx)); /* load b3 b2 b1 b0, another line */
+ y1 = *((ULong*)(prev += 4)); /* a7 a6 a5 a4 */
+ y2 = *((ULong*)(prev + lx)); /* b7 b6 b5 b4 */
+
+ x1m = (x1 >> 2) & mask; /* zero out last 2 bits */
+ x2m = (x2 >> 2) & mask;
+ x1 = x1 ^(x1m << 2);
+ x2 = x2 ^(x2m << 2);
+ x1m += x2m;
+ x1 += x2;
+
+ /* x2m, x2 free */
+ y1m = (y1 >> 2) & mask; /* zero out last 2 bits */
+ y2m = (y2 >> 2) & mask;
+ y1 = y1 ^(y1m << 2);
+ y2 = y2 ^(y2m << 2);
+ y1m += y2m;
+ y1 += y2;
+
+ /* y2m, y2 free */
+ /* x2m, x2 free */
+ x2 = *((ULong*)(prev += 4)); /* a11 a10 a9 a8 */
+ y2 = *((ULong*)(prev + lx)); /* b11 b10 b9 b8 */
+ x2m = (x2 >> 2) & mask;
+ y2m = (y2 >> 2) & mask;
+ x2 = x2 ^(x2m << 2);
+ y2 = y2 ^(y2m << 2);
+ x2m += y2m;
+ x2 += y2;
+ /* y2m, y2 free */
+
+ /* now operate on x1m, x1, y1m, y1, x2m, x2 */
+ /* x1m = a3+b3, a2+b2, a1+b1, a0+b0 */
+ /* y1m = a7+b7, a6+b6, a5+b5, a4+b4 */
+ /* x2m = a11+b11, a10+b10, a9+b9, a8+b8 */
+ /* x1, y1, x2 */
+
+ x1m >>= 24 ;
+ x1 >>= 24;
+ x1m |= (y1m << 8); /* a6+b6, a5+b5, a4+b4, a3+b3 */
+ x1 |= (y1 << 8);
+
+ x1m += y1m; /* a6+b6+a7+b7, ....., a3+b3+a4+b4 */
+ x1 += y1;
+ x1 += rnd2;
+ x1 &= (mask << 2);
+ x1m += (x1 >> 2);
+ *((ULong*)(rec += 4)) = x1m; /* save x1m */
+
+ y1m >>= 24;
+ y1 >>= 24;
+ y1m |= (x2m << 8); /* a10+b10, a9+b9, a8+b8, a7+b7 */
+ y1 |= (x2 << 8);
+ y1m += x2m; /* a10+b10+a11+b11, ....., a7+b7+a8+b8 */
+ y1 += x2;
+ y1 += rnd2;
+ y1 &= (mask << 2);
+ y1m += (y1 >> 2);
+ *((ULong*)(rec += 4)) = y1m; /* save y1m */
+
+ rec += 8;
+ prev += offset;
+ }
+ return 1;
+ }
+}
+
+
+/*=============================================================================
+ Function: EncGetPredOutside
+ Date: 04/17/2001
+ Purpose: - modified from GetPredOutside in the decoder.
+ Modified: 09/24/05
+ use the existing non-initialized padded region
+=============================================================================*/
+// not really needed since padding is included
+#define PAD_CORNER { temp = *src; \
+ temp |= (temp<<8); \
+ temp |= (temp<<16); \
+ *((ULong*)dst) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; }
+
+#define PAD_ROW { temp = *((ULong*)src); \
+ temp2 = *((ULong*)(src+4)); \
+ *((ULong*)dst) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp2; }
+
+#define PAD_COL { temp = *src; temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)dst) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; \
+ temp = *(src+=lx); temp |= (temp<<8); temp |= (temp<<16); \
+ *((ULong*)(dst+=lx)) = temp; \
+ *((ULong*)(dst+4)) = temp; }
+
+
+Int EncGetPredOutside(Int xpos, Int ypos, UChar *c_prev, UChar *rec,
+ Int width, Int height, Int rnd1)
+{
+ Int lx;
+ UChar *src, *dst;
+ ULong temp, temp2;
+ Int xoffset;
+
+ lx = width + 16; /* only works for chroma */
+
+ if (xpos < 0)
+ {
+ if (ypos < 0) /* pad top-left */
+ {
+ /* pad corner */
+ src = c_prev;
+ dst = c_prev - (lx << 3) - 8;
+ PAD_CORNER
+
+ /* pad top */
+ dst = c_prev - (lx << 3);
+ PAD_ROW
+
+ /* pad left */
+ dst = c_prev - 8;
+ PAD_COL
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ else if ((ypos >> 1) < (height - 8)) /* pad left of frame */
+ {
+ /* pad left */
+ src = c_prev + (ypos >> 1) * lx;
+ dst = src - 8;
+ PAD_COL
+ /* pad extra row */
+ temp = *(src += lx);
+ temp |= (temp << 8);
+ temp |= (temp << 16);
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst + 4)) = temp;
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ else /* pad bottom-left */
+ {
+ /* pad corner */
+ src = c_prev + (height - 1) * lx;
+ dst = src + lx - 8;
+ PAD_CORNER
+
+ /* pad bottom */
+ dst = src + lx;
+ PAD_ROW
+
+ /* pad left */
+ src -= (lx << 3);
+ src += lx;
+ dst = src - 8;
+ PAD_COL
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ }
+ else if ((xpos >> 1) < (width - 8))
+ {
+ if (ypos < 0) /* pad top of frame */
+ {
+ xoffset = (xpos >> 1) & 0x3;
+ src = c_prev + (xpos >> 1) - xoffset;
+ dst = src - (lx << 3);
+ PAD_ROW
+ if (xoffset || (xpos&1))
+ {
+ temp = *((ULong*)(src + 8));
+ dst = src - (lx << 3) + 8;
+ *((ULong*)dst) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ }
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ else /* pad bottom of frame */
+ {
+ xoffset = (xpos >> 1) & 0x3;
+ src = c_prev + (xpos >> 1) - xoffset + (height - 1) * lx;
+ dst = src + lx;
+ PAD_ROW
+ if (xoffset || (xpos&1))
+ {
+ temp = *((ULong*)(src + 8));
+ dst = src + lx + 8;
+ *((ULong*)dst) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst += lx)) = temp;
+ }
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ }
+ else
+ {
+ if (ypos < 0) /* pad top-right */
+ {
+ /* pad corner */
+ src = c_prev + width - 1;
+ dst = src - (lx << 3) + 1;
+ PAD_CORNER
+
+ /* pad top */
+ src -= 7;
+ dst = src - (lx << 3);
+ PAD_ROW
+
+ /* pad left */
+ src += 7;
+ dst = src + 1;
+ PAD_COL
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ else if ((ypos >> 1) < (height - B_SIZE)) /* pad right of frame */
+ {
+ /* pad left */
+ src = c_prev + (ypos >> 1) * lx + width - 1;
+ dst = src + 1;
+ PAD_COL
+ /* pad extra row */
+ temp = *(src += lx);
+ temp |= (temp << 8);
+ temp |= (temp << 16);
+ *((ULong*)(dst += lx)) = temp;
+ *((ULong*)(dst + 4)) = temp;
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ else /* pad bottom-right */
+ {
+ /* pad left */
+ src = c_prev + (height - 8) * lx + width - 1;
+ dst = src + 1;
+ PAD_COL
+
+ /* pad corner */
+ dst = src + lx + 1;
+ PAD_CORNER
+
+ /* pad bottom */
+ src -= 7;
+ dst = src + lx;
+ PAD_ROW
+
+ GetPredAdvBTable[ypos&1][xpos&1](c_prev + (xpos >> 1) + ((ypos >> 1)*lx),
+ rec, lx, rnd1);
+
+ return 1;
+ }
+ }
+}
+
+/* ====================================================================== /
+ Function : Copy_MB_from_Vop()
+ Date : 04/17/2001
+ ====================================================================== */
+
+void Copy_MB_from_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int pitch)
+{
+ Int row, col, i;
+ Int *src1, *src2;
+ Int offset = pitch - MB_SIZE;
+ ULong temp;
+
+ for (i = 0; i < 4; i += 2)
+ {
+ src1 = yChan[i];
+ src2 = yChan[i+1];
+
+ row = B_SIZE;
+ while (row--)
+ {
+ col = B_SIZE;
+ while (col)
+ {
+ temp = *((ULong*)comp);
+ *src1++ = (Int)(temp & 0xFF);
+ *src1++ = (Int)((temp >> 8) & 0xFF);
+ *src1++ = (Int)((temp >> 16) & 0xFF);
+ *src1++ = (Int)((temp >> 24) & 0xFF);
+ comp += 4;
+ col -= 4;
+ }
+ col = B_SIZE;
+ while (col)
+ {
+ temp = *((ULong*)comp);
+ *src2++ = (Int)(temp & 0xFF);
+ *src2++ = (Int)((temp >> 8) & 0xFF);
+ *src2++ = (Int)((temp >> 16) & 0xFF);
+ *src2++ = (Int)((temp >> 24) & 0xFF);
+ comp += 4;
+ col -= 4;
+ }
+ comp += offset;
+ }
+ }
+ return ;
+}
+
+/* ====================================================================== /
+ Function : Copy_B_from_Vop()
+ Date : 04/17/2001
+/ ====================================================================== */
+
+void Copy_B_from_Vop(UChar *comp, Int cChan[], Int pitch)
+{
+ Int row, col;
+ Int offset = pitch - B_SIZE;
+ ULong temp;
+
+ row = B_SIZE;
+ while (row--)
+ {
+ col = B_SIZE;
+ while (col)
+ {
+ temp = *((ULong*)comp);
+ *cChan++ = (Int)(temp & 0xFF);
+ *cChan++ = (Int)((temp >> 8) & 0xFF);
+ *cChan++ = (Int)((temp >> 16) & 0xFF);
+ *cChan++ = (Int)((temp >> 24) & 0xFF);
+ comp += 4;
+ col -= 4;
+ }
+ comp += offset;
+ }
+}
+
+/* ====================================================================== /
+ Function : Copy_MB_into_Vop()
+ Date : 04/17/2001
+ History : From decoder
+/ ====================================================================== */
+
+void Copy_MB_into_Vop(UChar *comp, Int yChan[][NCOEFF_BLOCK], Int pitch)
+{
+ Int row, col, i;
+ Int *src1, *src2;
+ Int offset = pitch - MB_SIZE;
+ UChar mask = 0xFF;
+ Int tmp;
+ ULong temp;
+
+ for (i = 0; i < 4; i += 2)
+ {
+ src1 = yChan[i];
+ src2 = yChan[i+1];
+
+ row = B_SIZE;
+ while (row--)
+ {
+ col = B_SIZE;
+ while (col)
+ {
+ tmp = (*src1++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp = tmp << 24;
+ tmp = (*src1++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= (tmp << 16);
+ tmp = (*src1++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= (tmp << 8);
+ tmp = (*src1++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= tmp;
+ *((ULong*)comp) = temp;
+ comp += 4;
+ col -= 4;
+ }
+ col = B_SIZE;
+ while (col)
+ {
+ tmp = (*src2++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp = tmp << 24;
+ tmp = (*src2++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= (tmp << 16);
+ tmp = (*src2++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= (tmp << 8);
+ tmp = (*src2++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= tmp;
+ *((ULong*)comp) = temp;
+ comp += 4;
+ col -= 4;
+ }
+ comp += offset;
+ }
+ }
+ return ;
+}
+
+
+/* ====================================================================== /
+ Function : Copy_B_into_Vop()
+ Date : 04/17/2001
+ History : From decoder
+/ ====================================================================== */
+
+void Copy_B_into_Vop(UChar *comp, Int cChan[], Int pitch)
+{
+ Int row, col;
+ Int offset = pitch - B_SIZE;
+ Int tmp;
+ UChar mask = 0xFF;
+ ULong temp;
+
+ row = B_SIZE;
+ while (row--)
+ {
+ col = B_SIZE;
+ while (col)
+ {
+ tmp = (*cChan++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp = tmp << 24;
+ tmp = (*cChan++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= (tmp << 16);
+ tmp = (*cChan++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= (tmp << 8);
+ tmp = (*cChan++);
+ if ((UInt)tmp > mask) tmp = mask & (~(tmp >> 31));
+ temp |= tmp;
+ *((ULong*)comp) = temp;
+ comp += 4;
+ col -= 4;
+ }
+ comp += offset;
+ }
+}
+
+/* ======================================================================== */
+/* Function : get_MB( ) */
+/* Date : 10/03/2000 */
+/* Purpose : Copy 4 Y to reference frame */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+void get_MB(UChar *c_prev, UChar *c_prev_u , UChar *c_prev_v,
+ Short mb[6][64], Int lx, Int lx_uv)
+
+{
+ Int i, j, count = 0, count1 = 0;
+ Int k1 = lx - MB_SIZE, k2 = lx_uv - B_SIZE;
+
+ for (i = 0; i < B_SIZE; i++)
+ {
+ for (j = 0; j < B_SIZE; j++)
+ {
+ mb[0][count] = (Int)(*c_prev++);
+ mb[4][count] = (Int)(*c_prev_u++);
+ mb[5][count++] = (Int)(*c_prev_v++);
+ }
+
+ for (j = 0; j < B_SIZE; j++)
+ mb[1][count1++] = (Int)(*c_prev++);
+
+ c_prev += k1;
+ c_prev_u += k2;
+ c_prev_v += k2;
+
+
+ }
+
+ count = count1 = 0;
+ for (i = 0; i < B_SIZE; i++)
+ {
+ for (j = 0; j < B_SIZE; j++)
+ mb[2][count++] = (Int)(*c_prev++);
+
+ for (j = 0; j < B_SIZE; j++)
+ mb[3][count1++] = (Int)(*c_prev++);
+
+ c_prev += k1;
+ }
+}
+
+void PutSkippedBlock(UChar *rec, UChar *prev, Int lx)
+{
+ UChar *end;
+ Int offset = (lx - 8) >> 2;
+ Int *src, *dst;
+
+ dst = (Int*)rec;
+ src = (Int*)prev;
+
+ end = prev + (lx << 3);
+
+ do
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ dst += offset;
+ src += offset;
+ }
+ while ((UInt)src < (UInt)end);
+
+ return ;
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
new file mode 100644
index 0000000..997b78d
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/motion_est.cpp
@@ -0,0 +1,1741 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4enc_lib.h"
+#include "mp4lib_int.h"
+#include "m4venc_oscl.h"
+
+//#define PRINT_MV
+#define MIN_GOP 1 /* minimum size of GOP, 1/23/01, need to be tested */
+
+#define CANDIDATE_DISTANCE 0 /* distance candidate from one another to consider as a distinct one */
+/* shouldn't be more than 3 */
+
+#define ZERO_MV_PREF 0 /* 0: bias (0,0)MV before full-pel search, lowest complexity*/
+/* 1: bias (0,0)MV after full-pel search, before half-pel, highest comp */
+/* 2: bias (0,0)MV after half-pel, high comp, better PSNR */
+
+#define RASTER_REFRESH /* instead of random INTRA refresh, do raster scan, 2/26/01 */
+
+#ifdef RASTER_REFRESH
+#define TARGET_REFRESH_PER_REGION 4 /* , no. MB per frame to be INTRA refreshed */
+#else
+#define TARGET_REFRESH_PER_REGION 1 /* , no. MB per region to be INTRA refreshed */
+#endif
+
+#define ALL_CAND_EQUAL 10 /* any number greater than 5 will work */
+
+#define NumPixelMB 256 /* number of pixels used in SAD calculation */
+
+#define DEF_8X8_WIN 3 /* search region for 8x8 MVs around the 16x16 MV */
+#define MB_Nb 256
+
+#define PREF_NULL_VEC 129 /* for zero vector bias */
+#define PREF_16_VEC 129 /* 1MV bias versus 4MVs*/
+#define PREF_INTRA 512 /* bias for INTRA coding */
+
+const static Int tab_exclude[9][9] = // [last_loc][curr_loc]
+{
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 1, 1, 1, 0, 0},
+ {0, 0, 0, 0, 1, 1, 1, 1, 1},
+ {0, 0, 0, 0, 0, 0, 1, 1, 1},
+ {0, 1, 1, 0, 0, 0, 1, 1, 1},
+ {0, 1, 1, 0, 0, 0, 0, 0, 1},
+ {0, 1, 1, 1, 1, 0, 0, 0, 1},
+ {0, 0, 1, 1, 1, 0, 0, 0, 0},
+ {0, 0, 1, 1, 1, 1, 1, 0, 0}
+}; //to decide whether to continue or compute
+
+const static Int refine_next[8][2] = /* [curr_k][increment] */
+{
+ {0, 0}, {2, 0}, {1, 1}, {0, 2}, { -1, 1}, { -2, 0}, { -1, -1}, {0, -2}
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ void MBMotionSearch(VideoEncData *video, UChar *cur, UChar *best_cand[],
+ Int i0, Int j0, Int type_pred, Int fullsearch, Int *hp_guess);
+
+ Int fullsearch(VideoEncData *video, Vol *currVol, UChar *ref, UChar *cur,
+ Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh);
+ Int fullsearchBlk(VideoEncData *video, Vol *currVol, UChar *cent, UChar *cur,
+ Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh, Int range);
+ void CandidateSelection(Int *mvx, Int *mvy, Int *num_can, Int imb, Int jmb,
+ VideoEncData *video, Int type_pred);
+ void RasterIntraUpdate(UChar *intraArray, UChar *Mode, Int totalMB, Int numRefresh);
+ void ResetIntraUpdate(UChar *intraArray, Int totalMB);
+ void ResetIntraUpdateRegion(UChar *intraArray, Int start_i, Int rwidth,
+ Int start_j, Int rheight, Int mbwidth, Int mbheight);
+
+ void MoveNeighborSAD(Int dn[], Int new_loc);
+ Int FindMin(Int dn[]);
+ void PrepareCurMB(VideoEncData *video, UChar *cur);
+
+#ifdef __cplusplus
+}
+#endif
+
+/***************************************/
+/* 2/28/01, for HYPOTHESIS TESTING */
+#ifdef HTFM /* defined in mp4def.h */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void CalcThreshold(double pf, double exp_lamda[], Int nrmlz_th[]);
+ void HTFMPrepareCurMB(VideoEncData *video, HTFM_Stat *htfm_stat, UChar *cur);
+#ifdef __cplusplus
+}
+#endif
+
+
+#define HTFM_Pf 0.25 /* 3/2/1, probability of false alarm, can be varied from 0 to 0.5 */
+/***************************************/
+#endif
+
+#ifdef _SAD_STAT
+ULong num_MB = 0;
+ULong num_HP_MB = 0;
+ULong num_Blk = 0;
+ULong num_HP_Blk = 0;
+ULong num_cand = 0;
+ULong num_better_hp = 0;
+ULong i_dist_from_guess = 0;
+ULong j_dist_from_guess = 0;
+ULong num_hp_not_zero = 0;
+#endif
+
+
+
+/*==================================================================
+ Function: MotionEstimation
+ Date: 10/3/2000
+ Purpose: Go through all macroblock for motion search and
+ determine scene change detection.
+====================================================================*/
+
+void MotionEstimation(VideoEncData *video)
+{
+ UChar use_4mv = video->encParams->MV8x8_Enabled;
+ Vol *currVol = video->vol[video->currLayer];
+ Vop *currVop = video->currVop;
+ VideoEncFrameIO *currFrame = video->input;
+ Int i, j, comp;
+ Int mbwidth = currVol->nMBPerRow;
+ Int mbheight = currVol->nMBPerCol;
+ Int totalMB = currVol->nTotalMB;
+ Int width = currFrame->pitch;
+ UChar *mode_mb, *Mode = video->headerInfo.Mode;
+ MOT *mot_mb, **mot = video->mot;
+ UChar *intraArray = video->intraArray;
+ Int FS_en = video->encParams->FullSearch_Enabled;
+ void (*ComputeMBSum)(UChar *, Int, MOT *) = video->functionPointer->ComputeMBSum;
+ void (*ChooseMode)(UChar*, UChar*, Int, Int) = video->functionPointer->ChooseMode;
+
+ Int numIntra, start_i, numLoop, incr_i;
+ Int mbnum, offset;
+ UChar *cur, *best_cand[5];
+ Int sad8 = 0, sad16 = 0;
+ Int totalSAD = 0; /* average SAD for rate control */
+ Int skip_halfpel_4mv;
+ Int f_code_p, f_code_n, max_mag = 0, min_mag = 0;
+ Int type_pred;
+ Int xh[5] = {0, 0, 0, 0, 0};
+ Int yh[5] = {0, 0, 0, 0, 0}; /* half-pel */
+ UChar hp_mem4MV[17*17*4];
+
+#ifdef HTFM
+ /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
+ Int collect = 0;
+ HTFM_Stat htfm_stat;
+ double newvar[16];
+ double exp_lamda[15];
+ /*********************************/
+#endif
+ Int hp_guess = 0;
+#ifdef PRINT_MV
+ FILE *fp_debug;
+#endif
+
+// FILE *fstat;
+// static int frame_num = 0;
+
+ offset = 0;
+
+ if (video->currVop->predictionType == I_VOP)
+ { /* compute the SAV */
+ mbnum = 0;
+ cur = currFrame->yChan;
+
+ for (j = 0; j < mbheight; j++)
+ {
+ for (i = 0; i < mbwidth; i++)
+ {
+ video->mbnum = mbnum;
+ mot_mb = mot[mbnum];
+
+ (*ComputeMBSum)(cur + (i << 4), width, mot_mb);
+
+ totalSAD += mot_mb[0].sad;
+
+ mbnum++;
+ }
+ cur += (width << 4);
+ }
+
+ video->sumMAD = (float)totalSAD / (float)NumPixelMB;
+
+ ResetIntraUpdate(intraArray, totalMB);
+
+ return ;
+ }
+
+ /* 09/20/05 */
+ if (video->prevBaseVop->padded == 0 && !video->encParams->H263_Enabled)
+ {
+ PaddingEdge(video->prevBaseVop);
+ video->prevBaseVop->padded = 1;
+ }
+
+ /* Random INTRA update */
+ /* suggest to do it in CodeMB */
+ /* 2/21/2001 */
+ //if(video->encParams->RC_Type == CBR_1 || video->encParams->RC_Type == CBR_2)
+ if (video->currLayer == 0 && video->encParams->Refresh)
+ {
+ RasterIntraUpdate(intraArray, Mode, totalMB, video->encParams->Refresh);
+ }
+
+ video->sad_extra_info = NULL;
+
+#ifdef HTFM
+ /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
+ InitHTFM(video, &htfm_stat, newvar, &collect);
+ /*********************************/
+#endif
+
+ if ((video->encParams->SceneChange_Det == 1) /*&& video->currLayer==0 */
+ && ((video->encParams->LayerFrameRate[0] < 5.0) || (video->numVopsInGOP > MIN_GOP)))
+ /* do not try to detect a new scene if low frame rate and too close to previous I-frame */
+ {
+ incr_i = 2;
+ numLoop = 2;
+ start_i = 1;
+ type_pred = 0; /* for initial candidate selection */
+ }
+ else
+ {
+ incr_i = 1;
+ numLoop = 1;
+ start_i = 0;
+ type_pred = 2;
+ }
+
+ /* First pass, loop thru half the macroblock */
+ /* determine scene change */
+ /* Second pass, for the rest of macroblocks */
+ numIntra = 0;
+ while (numLoop--)
+ {
+ for (j = 0; j < mbheight; j++)
+ {
+ if (incr_i > 1)
+ start_i = (start_i == 0 ? 1 : 0) ; /* toggle 0 and 1 */
+
+ offset = width * (j << 4) + (start_i << 4);
+
+ mbnum = j * mbwidth + start_i;
+
+ for (i = start_i; i < mbwidth; i += incr_i)
+ {
+ video->mbnum = mbnum;
+ mot_mb = mot[mbnum];
+ mode_mb = Mode + mbnum;
+
+ cur = currFrame->yChan + offset;
+
+
+ if (*mode_mb != MODE_INTRA)
+ {
+#if defined(HTFM)
+ HTFMPrepareCurMB(video, &htfm_stat, cur);
+#else
+ PrepareCurMB(video, cur);
+#endif
+ /************************************************************/
+ /******** full-pel 1MV and 4MVs search **********************/
+
+#ifdef _SAD_STAT
+ num_MB++;
+#endif
+ MBMotionSearch(video, cur, best_cand, i << 4, j << 4, type_pred,
+ FS_en, &hp_guess);
+
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, "#%d (%d,%d,%d) : ", mbnum, mot_mb[0].x, mot_mb[0].y, mot_mb[0].sad);
+ fprintf(fp_debug, "(%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : ==>\n",
+ mot_mb[1].x, mot_mb[1].y, mot_mb[1].sad,
+ mot_mb[2].x, mot_mb[2].y, mot_mb[2].sad,
+ mot_mb[3].x, mot_mb[3].y, mot_mb[3].sad,
+ mot_mb[4].x, mot_mb[4].y, mot_mb[4].sad);
+ fclose(fp_debug);
+#endif
+ sad16 = mot_mb[0].sad;
+#ifdef NO_INTER4V
+ sad8 = sad16;
+#else
+ sad8 = mot_mb[1].sad + mot_mb[2].sad + mot_mb[3].sad + mot_mb[4].sad;
+#endif
+
+ /* choose between INTRA or INTER */
+ (*ChooseMode)(mode_mb, cur, width, ((sad8 < sad16) ? sad8 : sad16));
+ }
+ else /* INTRA update, use for prediction 3/23/01 */
+ {
+ mot_mb[0].x = mot_mb[0].y = 0;
+ }
+
+ if (*mode_mb == MODE_INTRA)
+ {
+ numIntra++ ;
+
+ /* compute SAV for rate control and fast DCT, 11/28/00 */
+ (*ComputeMBSum)(cur, width, mot_mb);
+
+ /* leave mot_mb[0] as it is for fast motion search */
+ /* set the 4 MVs to zeros */
+ for (comp = 1; comp <= 4; comp++)
+ {
+ mot_mb[comp].x = 0;
+ mot_mb[comp].y = 0;
+ }
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, "\n");
+ fclose(fp_debug);
+#endif
+ }
+ else /* *mode_mb = MODE_INTER;*/
+ {
+ if (video->encParams->HalfPel_Enabled)
+ {
+#ifdef _SAD_STAT
+ num_HP_MB++;
+#endif
+ /* find half-pel resolution motion vector */
+ FindHalfPelMB(video, cur, mot_mb, best_cand[0],
+ i << 4, j << 4, xh, yh, hp_guess);
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, "(%d,%d), %d\n", mot_mb[0].x, mot_mb[0].y, mot_mb[0].sad);
+ fclose(fp_debug);
+#endif
+ skip_halfpel_4mv = ((sad16 - mot_mb[0].sad) <= (MB_Nb >> 1) + 1);
+ sad16 = mot_mb[0].sad;
+
+#ifndef NO_INTER4V
+ if (use_4mv && !skip_halfpel_4mv)
+ {
+ /* Also decide 1MV or 4MV !!!!!!!!*/
+ sad8 = FindHalfPelBlk(video, cur, mot_mb, sad16,
+ best_cand, mode_mb, i << 4, j << 4, xh, yh, hp_mem4MV);
+
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, " (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) : (%d,%d,%d) \n",
+ mot_mb[1].x, mot_mb[1].y, mot_mb[1].sad,
+ mot_mb[2].x, mot_mb[2].y, mot_mb[2].sad,
+ mot_mb[3].x, mot_mb[3].y, mot_mb[3].sad,
+ mot_mb[4].x, mot_mb[4].y, mot_mb[4].sad);
+ fclose(fp_debug);
+#endif
+ }
+#endif /* NO_INTER4V */
+ }
+ else /* HalfPel_Enabled ==0 */
+ {
+#ifndef NO_INTER4V
+ //if(sad16 < sad8-PREF_16_VEC)
+ if (sad16 - PREF_16_VEC > sad8)
+ {
+ *mode_mb = MODE_INTER4V;
+ }
+#endif
+ }
+#if (ZERO_MV_PREF==2) /* use mot_mb[7].sad as d0 computed in MBMotionSearch*/
+ /******************************************************/
+ if (mot_mb[7].sad - PREF_NULL_VEC < sad16 && mot_mb[7].sad - PREF_NULL_VEC < sad8)
+ {
+ mot_mb[0].sad = mot_mb[7].sad - PREF_NULL_VEC;
+ mot_mb[0].x = mot_mb[0].y = 0;
+ *mode_mb = MODE_INTER;
+ }
+ /******************************************************/
+#endif
+ if (*mode_mb == MODE_INTER)
+ {
+ if (mot_mb[0].x == 0 && mot_mb[0].y == 0) /* use zero vector */
+ mot_mb[0].sad += PREF_NULL_VEC; /* add back the bias */
+
+ mot_mb[1].sad = mot_mb[2].sad = mot_mb[3].sad = mot_mb[4].sad = (mot_mb[0].sad + 2) >> 2;
+ mot_mb[1].x = mot_mb[2].x = mot_mb[3].x = mot_mb[4].x = mot_mb[0].x;
+ mot_mb[1].y = mot_mb[2].y = mot_mb[3].y = mot_mb[4].y = mot_mb[0].y;
+
+ }
+ }
+
+ /* find maximum magnitude */
+ /* compute average SAD for rate control, 11/28/00 */
+ if (*mode_mb == MODE_INTER)
+ {
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, "%d MODE_INTER\n", mbnum);
+ fclose(fp_debug);
+#endif
+ totalSAD += mot_mb[0].sad;
+ if (mot_mb[0].x > max_mag)
+ max_mag = mot_mb[0].x;
+ if (mot_mb[0].y > max_mag)
+ max_mag = mot_mb[0].y;
+ if (mot_mb[0].x < min_mag)
+ min_mag = mot_mb[0].x;
+ if (mot_mb[0].y < min_mag)
+ min_mag = mot_mb[0].y;
+ }
+ else if (*mode_mb == MODE_INTER4V)
+ {
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, "%d MODE_INTER4V\n", mbnum);
+ fclose(fp_debug);
+#endif
+ totalSAD += sad8;
+ for (comp = 1; comp <= 4; comp++)
+ {
+ if (mot_mb[comp].x > max_mag)
+ max_mag = mot_mb[comp].x;
+ if (mot_mb[comp].y > max_mag)
+ max_mag = mot_mb[comp].y;
+ if (mot_mb[comp].x < min_mag)
+ min_mag = mot_mb[comp].x;
+ if (mot_mb[comp].y < min_mag)
+ min_mag = mot_mb[comp].y;
+ }
+ }
+ else /* MODE_INTRA */
+ {
+#ifdef PRINT_MV
+ fp_debug = fopen("c:\\bitstream\\mv1_debug.txt", "a");
+ fprintf(fp_debug, "%d MODE_INTRA\n", mbnum);
+ fclose(fp_debug);
+#endif
+ totalSAD += mot_mb[0].sad;
+ }
+ mbnum += incr_i;
+ offset += (incr_i << 4);
+
+ }
+ }
+
+ if (incr_i > 1 && numLoop) /* scene change on and first loop */
+ {
+ //if(numIntra > ((totalMB>>3)<<1) + (totalMB>>3)) /* 75% of 50%MBs */
+ if (numIntra > (0.30*(totalMB / 2.0))) /* 15% of 50%MBs */
+ {
+ /******** scene change detected *******************/
+ currVop->predictionType = I_VOP;
+ M4VENC_MEMSET(Mode, MODE_INTRA, sizeof(UChar)*totalMB); /* set this for MB level coding*/
+ currVop->quantizer = video->encParams->InitQuantIvop[video->currLayer];
+
+ /* compute the SAV for rate control & fast DCT */
+ totalSAD = 0;
+ offset = 0;
+ mbnum = 0;
+ cur = currFrame->yChan;
+
+ for (j = 0; j < mbheight; j++)
+ {
+ for (i = 0; i < mbwidth; i++)
+ {
+ video->mbnum = mbnum;
+ mot_mb = mot[mbnum];
+
+
+ (*ComputeMBSum)(cur + (i << 4), width, mot_mb);
+ totalSAD += mot_mb[0].sad;
+
+ mbnum++;
+ }
+ cur += (width << 4);
+ }
+
+ video->sumMAD = (float)totalSAD / (float)NumPixelMB;
+ ResetIntraUpdate(intraArray, totalMB);
+ /* video->numVopsInGOP=0; 3/13/01 move it to vop.c*/
+
+ return ;
+ }
+ }
+ /******** no scene change, continue motion search **********************/
+ start_i = 0;
+ type_pred++; /* second pass */
+ }
+
+ video->sumMAD = (float)totalSAD / (float)NumPixelMB; /* avg SAD */
+
+ /* find f_code , 10/27/2000 */
+ f_code_p = 1;
+ while ((max_mag >> (4 + f_code_p)) > 0)
+ f_code_p++;
+
+ f_code_n = 1;
+ min_mag *= -1;
+ while ((min_mag - 1) >> (4 + f_code_n) > 0)
+ f_code_n++;
+
+ currVop->fcodeForward = (f_code_p > f_code_n ? f_code_p : f_code_n);
+
+#ifdef HTFM
+ /***** HYPOTHESIS TESTING ********/ /* 2/28/01 */
+ if (collect)
+ {
+ collect = 0;
+ UpdateHTFM(video, newvar, exp_lamda, &htfm_stat);
+ }
+ /*********************************/
+#endif
+
+ return ;
+}
+
+
+#ifdef HTFM
+void InitHTFM(VideoEncData *video, HTFM_Stat *htfm_stat, double *newvar, Int *collect)
+{
+ Int i;
+ Int lx = video->currVop->width; // padding
+ Int lx2 = lx << 1;
+ Int lx3 = lx2 + lx;
+ Int rx = video->currVop->pitch;
+ Int rx2 = rx << 1;
+ Int rx3 = rx2 + rx;
+
+ Int *offset, *offset2;
+
+ /* 4/11/01, collect data every 30 frames, doesn't have to be base layer */
+ if (((Int)video->numVopsInGOP) % 30 == 1)
+ {
+
+ *collect = 1;
+
+ htfm_stat->countbreak = 0;
+ htfm_stat->abs_dif_mad_avg = 0;
+
+ for (i = 0; i < 16; i++)
+ {
+ newvar[i] = 0.0;
+ }
+// video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM_Collect;
+ video->functionPointer->SAD_Macroblock = &SAD_MB_HTFM_Collect;
+ video->functionPointer->SAD_MB_HalfPel[0] = NULL;
+ video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFM_Collectxh;
+ video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFM_Collectyh;
+ video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFM_Collectxhyh;
+ video->sad_extra_info = (void*)(htfm_stat);
+ offset = htfm_stat->offsetArray;
+ offset2 = htfm_stat->offsetRef;
+ }
+ else
+ {
+// video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING_HTFM;
+ video->functionPointer->SAD_Macroblock = &SAD_MB_HTFM;
+ video->functionPointer->SAD_MB_HalfPel[0] = NULL;
+ video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HP_HTFMxh;
+ video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HP_HTFMyh;
+ video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HP_HTFMxhyh;
+ video->sad_extra_info = (void*)(video->nrmlz_th);
+ offset = video->nrmlz_th + 16;
+ offset2 = video->nrmlz_th + 32;
+ }
+
+ offset[0] = 0;
+ offset[1] = lx2 + 2;
+ offset[2] = 2;
+ offset[3] = lx2;
+ offset[4] = lx + 1;
+ offset[5] = lx3 + 3;
+ offset[6] = lx + 3;
+ offset[7] = lx3 + 1;
+ offset[8] = lx;
+ offset[9] = lx3 + 2;
+ offset[10] = lx3 ;
+ offset[11] = lx + 2 ;
+ offset[12] = 1;
+ offset[13] = lx2 + 3;
+ offset[14] = lx2 + 1;
+ offset[15] = 3;
+
+ offset2[0] = 0;
+ offset2[1] = rx2 + 2;
+ offset2[2] = 2;
+ offset2[3] = rx2;
+ offset2[4] = rx + 1;
+ offset2[5] = rx3 + 3;
+ offset2[6] = rx + 3;
+ offset2[7] = rx3 + 1;
+ offset2[8] = rx;
+ offset2[9] = rx3 + 2;
+ offset2[10] = rx3 ;
+ offset2[11] = rx + 2 ;
+ offset2[12] = 1;
+ offset2[13] = rx2 + 3;
+ offset2[14] = rx2 + 1;
+ offset2[15] = 3;
+
+ return ;
+}
+
+void UpdateHTFM(VideoEncData *video, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat)
+{
+ if (htfm_stat->countbreak == 0)
+ htfm_stat->countbreak = 1;
+
+ newvar[0] = (double)(htfm_stat->abs_dif_mad_avg) / (htfm_stat->countbreak * 16.);
+
+ if (newvar[0] < 0.001)
+ {
+ newvar[0] = 0.001; /* to prevent floating overflow */
+ }
+ exp_lamda[0] = 1 / (newvar[0] * 1.4142136);
+ exp_lamda[1] = exp_lamda[0] * 1.5825;
+ exp_lamda[2] = exp_lamda[0] * 2.1750;
+ exp_lamda[3] = exp_lamda[0] * 3.5065;
+ exp_lamda[4] = exp_lamda[0] * 3.1436;
+ exp_lamda[5] = exp_lamda[0] * 3.5315;
+ exp_lamda[6] = exp_lamda[0] * 3.7449;
+ exp_lamda[7] = exp_lamda[0] * 4.5854;
+ exp_lamda[8] = exp_lamda[0] * 4.6191;
+ exp_lamda[9] = exp_lamda[0] * 5.4041;
+ exp_lamda[10] = exp_lamda[0] * 6.5974;
+ exp_lamda[11] = exp_lamda[0] * 10.5341;
+ exp_lamda[12] = exp_lamda[0] * 10.0719;
+ exp_lamda[13] = exp_lamda[0] * 12.0516;
+ exp_lamda[14] = exp_lamda[0] * 15.4552;
+
+ CalcThreshold(HTFM_Pf, exp_lamda, video->nrmlz_th);
+ return ;
+}
+
+
+void CalcThreshold(double pf, double exp_lamda[], Int nrmlz_th[])
+{
+ Int i;
+ double temp[15];
+ // printf("\nLamda: ");
+
+ /* parametric PREMODELling */
+ for (i = 0; i < 15; i++)
+ {
+ // printf("%g ",exp_lamda[i]);
+ if (pf < 0.5)
+ temp[i] = 1 / exp_lamda[i] * M4VENC_LOG(2 * pf);
+ else
+ temp[i] = -1 / exp_lamda[i] * M4VENC_LOG(2 * (1 - pf));
+ }
+
+ nrmlz_th[15] = 0;
+ for (i = 0; i < 15; i++) /* scale upto no.pixels */
+ nrmlz_th[i] = (Int)(temp[i] * ((i + 1) << 4) + 0.5);
+
+ return ;
+}
+
+void HTFMPrepareCurMB(VideoEncData *video, HTFM_Stat *htfm_stat, UChar *cur)
+{
+ void* tmp = (void*)(video->currYMB);
+ ULong *htfmMB = (ULong*)tmp;
+ UChar *ptr, byte;
+ Int *offset;
+ Int i;
+ ULong word;
+ Int width = video->currVop->width;
+
+ if (((Int)video->numVopsInGOP) % 30 == 1)
+ {
+ offset = htfm_stat->offsetArray;
+ }
+ else
+ {
+ offset = video->nrmlz_th + 16;
+ }
+
+ for (i = 0; i < 16; i++)
+ {
+ ptr = cur + offset[i];
+ word = ptr[0];
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+
+ word = *(ptr += (width << 2));
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+
+ word = *(ptr += (width << 2));
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+
+ word = *(ptr += (width << 2));
+ byte = ptr[4];
+ word |= (byte << 8);
+ byte = ptr[8];
+ word |= (byte << 16);
+ byte = ptr[12];
+ word |= (byte << 24);
+ *htfmMB++ = word;
+ }
+
+ return ;
+}
+
+
+#endif
+
+void PrepareCurMB(VideoEncData *video, UChar *cur)
+{
+ void* tmp = (void*)(video->currYMB);
+ ULong *currYMB = (ULong*)tmp;
+ Int i;
+ Int width = video->currVop->width;
+
+ cur -= width;
+
+ for (i = 0; i < 16; i++)
+ {
+ *currYMB++ = *((ULong*)(cur += width));
+ *currYMB++ = *((ULong*)(cur + 4));
+ *currYMB++ = *((ULong*)(cur + 8));
+ *currYMB++ = *((ULong*)(cur + 12));
+ }
+
+ return ;
+}
+
+
+/*==================================================================
+ Function: MBMotionSearch
+ Date: 09/06/2000
+ Purpose: Perform motion estimation for a macroblock.
+ Find 1MV and 4MVs in half-pels resolutions.
+ Using ST1 algorithm provided by Chalidabhongse and Kuo
+ CSVT March'98.
+
+==================================================================*/
+
+void MBMotionSearch(VideoEncData *video, UChar *cur, UChar *best_cand[],
+ Int i0, Int j0, Int type_pred, Int FS_en, Int *hp_guess)
+{
+ Vol *currVol = video->vol[video->currLayer];
+ UChar *ref, *cand, *ncand = NULL, *cur8;
+ void *extra_info = video->sad_extra_info;
+ Int mbnum = video->mbnum;
+ Int width = video->currVop->width; /* 6/12/01, must be multiple of 16 */
+ Int height = video->currVop->height;
+ MOT **mot = video->mot;
+ UChar use_4mv = video->encParams->MV8x8_Enabled;
+ UChar h263_mode = video->encParams->H263_Enabled;
+ Int(*SAD_Macroblock)(UChar*, UChar*, Int, void*) = video->functionPointer->SAD_Macroblock;
+ Int(*SAD_Block)(UChar*, UChar*, Int, Int, void*) = video->functionPointer->SAD_Block;
+ VideoEncParams *encParams = video->encParams;
+ Int range = encParams->SearchRange;
+
+ Int lx = video->currVop->pitch; /* padding */
+ Int comp;
+ Int i, j, imin, jmin, ilow, ihigh, jlow, jhigh, iorg, jorg;
+ Int d, dmin, dn[9];
+#if (ZERO_MV_PREF==1) /* compute (0,0) MV at the end */
+ Int d0;
+#endif
+ Int k;
+ Int mvx[5], mvy[5], imin0, jmin0;
+ Int num_can, center_again;
+ Int last_loc, new_loc = 0;
+ Int step, max_step = range >> 1;
+ Int next;
+
+ ref = video->forwardRefVop->yChan; /* origin of actual frame */
+
+ cur = video->currYMB; /* use smaller memory space for current MB */
+
+ /* find limit of the search (adjusting search range)*/
+
+ if (!h263_mode)
+ {
+ ilow = i0 - range;
+ if (ilow < -15)
+ ilow = -15;
+ ihigh = i0 + range - 1;
+ if (ihigh > width - 1)
+ ihigh = width - 1;
+ jlow = j0 - range;
+ if (jlow < -15)
+ jlow = -15;
+ jhigh = j0 + range - 1;
+ if (jhigh > height - 1)
+ jhigh = height - 1;
+ }
+ else
+ {
+ ilow = i0 - range;
+ if (ilow < 0)
+ ilow = 0;
+ ihigh = i0 + range - 1;
+ if (ihigh > width - 16)
+ ihigh = width - 16;
+ jlow = j0 - range;
+ if (jlow < 0)
+ jlow = 0;
+ jhigh = j0 + range - 1;
+ if (jhigh > height - 16)
+ jhigh = height - 16;
+ }
+
+ imin = i0;
+ jmin = j0; /* needed for fullsearch */
+ ncand = ref + imin + jmin * lx;
+
+ /* for first row of MB, fullsearch can be used */
+ if (FS_en)
+ {
+ *hp_guess = 0; /* no guess for fast half-pel */
+
+ dmin = fullsearch(video, currVol, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh);
+
+ ncand = ref + imin + jmin * lx;
+
+ mot[mbnum][0].sad = dmin;
+ mot[mbnum][0].x = (imin - i0) << 1;
+ mot[mbnum][0].y = (jmin - j0) << 1;
+ imin0 = imin << 1; /* 16x16 MV in half-pel resolution */
+ jmin0 = jmin << 1;
+ best_cand[0] = ncand;
+ }
+ else
+ { /* 4/7/01, modified this testing for fullsearch the top row to only upto (0,3) MB */
+ /* upto 30% complexity saving with the same complexity */
+ if (video->forwardRefVop->predictionType == I_VOP && j0 == 0 && i0 <= 64 && type_pred != 1)
+ {
+ *hp_guess = 0; /* no guess for fast half-pel */
+ dmin = fullsearch(video, currVol, ref, cur, &imin, &jmin, ilow, ihigh, jlow, jhigh);
+ ncand = ref + imin + jmin * lx;
+ }
+ else
+ {
+ /************** initialize candidate **************************/
+ /* find initial motion vector */
+ CandidateSelection(mvx, mvy, &num_can, i0 >> 4, j0 >> 4, video, type_pred);
+
+ dmin = 65535;
+
+ /* check if all are equal */
+ if (num_can == ALL_CAND_EQUAL)
+ {
+ i = i0 + mvx[0];
+ j = j0 + mvy[0];
+
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ cand = ref + i + j * lx;
+
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+
+ if (d < dmin)
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ ncand = cand;
+ }
+ }
+ }
+ else
+ {
+ /************** evaluate unique candidates **********************/
+ for (k = 0; k < num_can; k++)
+ {
+ i = i0 + mvx[k];
+ j = j0 + mvy[k];
+
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ cand = ref + i + j * lx;
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+
+ if (d < dmin)
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ ncand = cand;
+ }
+ else if ((d == dmin) && PV_ABS(mvx[k]) + PV_ABS(mvy[k]) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
+ {
+ dmin = d;
+ imin = i;
+ jmin = j;
+ ncand = cand;
+ }
+ }
+ }
+ }
+ if (num_can == 0 || dmin == 65535) /* no candidate selected */
+ {
+ ncand = ref + i0 + j0 * lx; /* use (0,0) MV as initial value */
+ mot[mbnum][7].sad = dmin = (*SAD_Macroblock)(ncand, cur, (65535 << 16) | lx, extra_info);
+#if (ZERO_MV_PREF==1) /* compute (0,0) MV at the end */
+ d0 = dmin;
+#endif
+ imin = i0;
+ jmin = j0;
+ }
+
+#if (ZERO_MV_PREF==0) /* COMPUTE ZERO VECTOR FIRST !!!!!*/
+ dmin -= PREF_NULL_VEC;
+#endif
+
+ /******************* local refinement ***************************/
+ center_again = 0;
+ last_loc = new_loc = 0;
+ // ncand = ref + jmin*lx + imin; /* center of the search */
+ step = 0;
+ dn[0] = dmin;
+ while (!center_again && step <= max_step)
+ {
+
+ MoveNeighborSAD(dn, last_loc);
+
+ center_again = 1;
+ i = imin;
+ j = jmin - 1;
+ cand = ref + i + j * lx;
+
+ /* starting from [0,-1] */
+ /* spiral check one step at a time*/
+ for (k = 2; k <= 8; k += 2)
+ {
+ if (!tab_exclude[last_loc][k]) /* exclude last step computation */
+ { /* not already computed */
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, extra_info);
+ dn[k] = d; /* keep it for half pel use */
+
+ if (d < dmin)
+ {
+ ncand = cand;
+ dmin = d;
+ imin = i;
+ jmin = j;
+ center_again = 0;
+ new_loc = k;
+ }
+ else if ((d == dmin) && PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
+ {
+ ncand = cand;
+ imin = i;
+ jmin = j;
+ center_again = 0;
+ new_loc = k;
+ }
+ }
+ }
+ if (k == 8) /* end side search*/
+ {
+ if (!center_again)
+ {
+ k = -1; /* start diagonal search */
+ cand -= lx;
+ j--;
+ }
+ }
+ else
+ {
+ next = refine_next[k][0];
+ i += next;
+ cand += next;
+ next = refine_next[k][1];
+ j += next;
+ cand += lx * next;
+ }
+ }
+ last_loc = new_loc;
+ step ++;
+ }
+ if (!center_again)
+ MoveNeighborSAD(dn, last_loc);
+
+ *hp_guess = FindMin(dn);
+
+ }
+
+#if (ZERO_MV_PREF==1) /* compute (0,0) MV at the end */
+ if (d0 - PREF_NULL_VEC < dmin)
+ {
+ ncand = ref + i0 + j0 * lx;
+ dmin = d0;
+ imin = i0;
+ jmin = j0;
+ }
+#endif
+ mot[mbnum][0].sad = dmin;
+ mot[mbnum][0].x = (imin - i0) << 1;
+ mot[mbnum][0].y = (jmin - j0) << 1;
+ imin0 = imin << 1; /* 16x16 MV in half-pel resolution */
+ jmin0 = jmin << 1;
+ best_cand[0] = ncand;
+ }
+ /* imin and jmin is the best 1 MV */
+#ifndef NO_INTER4V
+ /******************* Find 4 motion vectors ****************************/
+ if (use_4mv && !h263_mode)
+ {
+#ifdef _SAD_STAT
+ num_Blk += 4;
+#endif
+ /* starting from the best 1MV */
+ //offset = imin + jmin*lx;
+ iorg = i0;
+ jorg = j0;
+
+ for (comp = 0; comp < 4; comp++)
+ {
+ i0 = iorg + ((comp & 1) << 3);
+ j0 = jorg + ((comp & 2) << 2);
+
+ imin = (imin0 >> 1) + ((comp & 1) << 3); /* starting point from 16x16 MV */
+ jmin = (jmin0 >> 1) + ((comp & 2) << 2);
+ ncand = ref + imin + jmin * lx;
+
+ cur8 = cur + ((comp & 1) << 3) + (((comp & 2) << 2) << 4) ; /* 11/30/05, smaller cache */
+
+ /* find limit of the search (adjusting search range)*/
+ ilow = i0 - range;
+ ihigh = i0 + range - 1 ;/* 4/9/01 */
+ if (ilow < -15)
+ ilow = -15;
+ if (ihigh > width - 1)
+ ihigh = width - 1;
+ jlow = j0 - range;
+ jhigh = j0 + range - 1 ;/* 4/9/01 */
+ if (jlow < -15)
+ jlow = -15;
+ if (jhigh > height - 1)
+ jhigh = height - 1;
+
+ SAD_Block = video->functionPointer->SAD_Block;
+
+ if (FS_en) /* fullsearch enable, center around 16x16 MV */
+ {
+ dmin = fullsearchBlk(video, currVol, ncand, cur8, &imin, &jmin, ilow, ihigh, jlow, jhigh, range);
+ ncand = ref + imin + jmin * lx;
+
+ mot[mbnum][comp+1].sad = dmin;
+ mot[mbnum][comp+1].x = (imin - i0) << 1;
+ mot[mbnum][comp+1].y = (jmin - j0) << 1;
+ best_cand[comp+1] = ncand;
+ }
+ else /* no fullsearch, do local search */
+ {
+ /* starting point from 16x16 */
+ dmin = (*SAD_Block)(ncand, cur8, 65536, lx, extra_info);
+
+ /******************* local refinement ***************************/
+ center_again = 0;
+ last_loc = 0;
+
+ while (!center_again)
+ {
+ center_again = 1;
+ i = imin;
+ j = jmin - 1;
+ cand = ref + i + j * lx;
+
+ /* starting from [0,-1] */
+ /* spiral check one step at a time*/
+ for (k = 2; k <= 8; k += 2)
+ {
+ if (!tab_exclude[last_loc][k]) /* exclude last step computation */
+ { /* not already computed */
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ d = (*SAD_Block)(cand, cur8, dmin, lx, extra_info);
+
+ if (d < dmin)
+ {
+ ncand = cand;
+ dmin = d;
+ imin = i;
+ jmin = j;
+ center_again = 0;
+ new_loc = k;
+ }
+ else if ((d == dmin) &&
+ PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - imin) + PV_ABS(j0 - jmin))
+ {
+ ncand = cand;
+ imin = i;
+ jmin = j;
+ center_again = 0;
+ new_loc = k;
+ }
+ }
+ }
+ if (k == 8) /* end side search*/
+ {
+ if (!center_again)
+ {
+ k = -1; /* start diagonal search */
+ if (j <= height - 1 && j > 0) cand -= lx;
+ j--;
+ }
+ }
+ else
+ {
+ next = refine_next[k][0];
+ cand += next;
+ i += next;
+ next = refine_next[k][1];
+ cand += lx * next;
+ j += next;
+ }
+ }
+ last_loc = new_loc;
+ }
+ mot[mbnum][comp+1].sad = dmin;
+ mot[mbnum][comp+1].x = (imin - i0) << 1;
+ mot[mbnum][comp+1].y = (jmin - j0) << 1;
+ best_cand[comp+1] = ncand;
+ }
+ /********************************************/
+ }
+ }
+ else
+#endif /* NO_INTER4V */
+ {
+ mot[mbnum][1].sad = mot[mbnum][2].sad = mot[mbnum][3].sad = mot[mbnum][4].sad = (dmin + 2) >> 2;
+ mot[mbnum][1].x = mot[mbnum][2].x = mot[mbnum][3].x = mot[mbnum][4].x = mot[mbnum][0].x;
+ mot[mbnum][1].y = mot[mbnum][2].y = mot[mbnum][3].y = mot[mbnum][4].y = mot[mbnum][0].y;
+ best_cand[1] = best_cand[2] = best_cand[3] = best_cand[4] = ncand;
+
+ }
+ return ;
+}
+
+
+/*===============================================================================
+ Function: fullsearch
+ Date: 09/16/2000
+ Purpose: Perform full-search motion estimation over the range of search
+ region in a spiral-outward manner.
+ Input/Output: VideoEncData, current Vol, previou Vop, pointer to the left corner of
+ current VOP, current coord (also output), boundaries.
+===============================================================================*/
+
+Int fullsearch(VideoEncData *video, Vol *currVol, UChar *prev, UChar *cur,
+ Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh)
+{
+ Int range = video->encParams->SearchRange;
+ UChar *cand;
+ Int i, j, k, l;
+ Int d, dmin;
+ Int i0 = *imin; /* current position */
+ Int j0 = *jmin;
+ Int(*SAD_Macroblock)(UChar*, UChar*, Int, void*) = video->functionPointer->SAD_Macroblock;
+ void *extra_info = video->sad_extra_info;
+// UChar h263_mode = video->encParams->H263_Enabled;
+ Int lx = video->currVop->pitch; /* with padding */
+
+ Int offset = i0 + j0 * lx;
+
+ OSCL_UNUSED_ARG(currVol);
+
+ cand = prev + offset;
+
+ dmin = (*SAD_Macroblock)(cand, cur, (65535 << 16) | lx, (void*)extra_info) - PREF_NULL_VEC;
+
+ /* perform spiral search */
+ for (k = 1; k <= range; k++)
+ {
+
+ i = i0 - k;
+ j = j0 - k;
+
+ cand = prev + i + j * lx;
+
+ for (l = 0; l < 8*k; l++)
+ {
+ /* no need for boundary checking again */
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ d = (*SAD_Macroblock)(cand, cur, (dmin << 16) | lx, (void*)extra_info);
+
+ if (d < dmin)
+ {
+ dmin = d;
+ *imin = i;
+ *jmin = j;
+ }
+ else if ((d == dmin) && PV_ABS(i0 - i) + PV_ABS(j0 - j) < PV_ABS(i0 - *imin) + PV_ABS(j0 - *jmin))
+ {
+ dmin = d;
+ *imin = i;
+ *jmin = j;
+ }
+ }
+
+ if (l < (k << 1))
+ {
+ i++;
+ cand++;
+ }
+ else if (l < (k << 2))
+ {
+ j++;
+ cand += lx;
+ }
+ else if (l < ((k << 2) + (k << 1)))
+ {
+ i--;
+ cand--;
+ }
+ else
+ {
+ j--;
+ cand -= lx;
+ }
+ }
+ }
+
+ return dmin;
+}
+
+#ifndef NO_INTER4V
+/*===============================================================================
+ Function: fullsearchBlk
+ Date: 01/9/2001
+ Purpose: Perform full-search motion estimation of an 8x8 block over the range
+ of search region in a spiral-outward manner centered at the 16x16 MV.
+ Input/Output: VideoEncData, MB coordinate, pointer to the initial MV on the
+ reference, pointer to coor of current block, search range.
+===============================================================================*/
+Int fullsearchBlk(VideoEncData *video, Vol *currVol, UChar *cent, UChar *cur,
+ Int *imin, Int *jmin, Int ilow, Int ihigh, Int jlow, Int jhigh, Int range)
+{
+ UChar *cand, *ref;
+ Int i, j, k, l, istart, jstart;
+ Int d, dmin;
+ Int lx = video->currVop->pitch; /* with padding */
+ Int(*SAD_Block)(UChar*, UChar*, Int, Int, void*) = video->functionPointer->SAD_Block;
+ void *extra_info = video->sad_extra_info;
+
+ OSCL_UNUSED_ARG(currVol);
+
+ /* starting point centered at 16x16 MV */
+ ref = cent;
+ istart = *imin;
+ jstart = *jmin;
+
+ dmin = (*SAD_Block)(ref, cur, 65536, lx, (void*)extra_info);
+
+ cand = ref;
+ /* perform spiral search */
+ for (k = 1; k <= range; k++)
+ {
+
+ i = istart - k;
+ j = jstart - k;
+ cand -= (lx + 1); /* candidate region */
+
+ for (l = 0; l < 8*k; l++)
+ {
+ /* no need for boundary checking again */
+ if (i >= ilow && i <= ihigh && j >= jlow && j <= jhigh)
+ {
+ d = (*SAD_Block)(cand, cur, dmin, lx, (void*)extra_info);
+
+ if (d < dmin)
+ {
+ dmin = d;
+ *imin = i;
+ *jmin = j;
+ }
+ else if ((d == dmin) &&
+ PV_ABS(istart - i) + PV_ABS(jstart - j) < PV_ABS(istart - *imin) + PV_ABS(jstart - *jmin))
+ {
+ dmin = d;
+ *imin = i;
+ *jmin = j;
+ }
+ }
+
+ if (l < (k << 1))
+ {
+ i++;
+ cand++;
+ }
+ else if (l < (k << 2))
+ {
+ j++;
+ cand += lx;
+ }
+ else if (l < ((k << 2) + (k << 1)))
+ {
+ i--;
+ cand--;
+ }
+ else
+ {
+ j--;
+ cand -= lx;
+ }
+ }
+ }
+
+ return dmin;
+}
+#endif /* NO_INTER4V */
+
+/*===============================================================================
+ Function: CandidateSelection
+ Date: 09/16/2000
+ Purpose: Fill up the list of candidate using spatio-temporal correlation
+ among neighboring blocks.
+ Input/Output: type_pred = 0: first pass, 1: second pass, or no SCD
+ Modified: 09/23/01, get rid of redundant candidates before passing back.
+===============================================================================*/
+
+void CandidateSelection(Int *mvx, Int *mvy, Int *num_can, Int imb, Int jmb,
+ VideoEncData *video, Int type_pred)
+{
+ MOT **mot = video->mot;
+ MOT *pmot;
+ Int mbnum = video->mbnum;
+ Vol *currVol = video->vol[video->currLayer];
+ Int mbwidth = currVol->nMBPerRow;
+ Int mbheight = currVol->nMBPerCol;
+ Int i, j, same, num1;
+
+ *num_can = 0;
+
+ if (video->forwardRefVop->predictionType == P_VOP)
+ {
+ /* Spatio-Temporal Candidate (five candidates) */
+ if (type_pred == 0) /* first pass */
+ {
+ pmot = &mot[mbnum][0]; /* same coordinate previous frame */
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ if (imb >= (mbwidth >> 1) && imb > 0) /*left neighbor previous frame */
+ {
+ pmot = &mot[mbnum-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ else if (imb + 1 < mbwidth) /*right neighbor previous frame */
+ {
+ pmot = &mot[mbnum+1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+
+ if (jmb < mbheight - 1) /*bottom neighbor previous frame */
+ {
+ pmot = &mot[mbnum+mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ else if (jmb > 0) /*upper neighbor previous frame */
+ {
+ pmot = &mot[mbnum-mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+
+ if (imb > 0 && jmb > 0) /* upper-left neighbor current frame*/
+ {
+ pmot = &mot[mbnum-mbwidth-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (jmb > 0 && imb < mbheight - 1) /* upper right neighbor current frame*/
+ {
+ pmot = &mot[mbnum-mbwidth+1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ }
+ else /* second pass */
+ /* original ST1 algorithm */
+ {
+ pmot = &mot[mbnum][0]; /* same coordinate previous frame */
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+
+ if (imb > 0) /*left neighbor current frame */
+ {
+ pmot = &mot[mbnum-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (jmb > 0) /*upper neighbor current frame */
+ {
+ pmot = &mot[mbnum-mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (imb < mbwidth - 1) /*right neighbor previous frame */
+ {
+ pmot = &mot[mbnum+1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (jmb < mbheight - 1) /*bottom neighbor previous frame */
+ {
+ pmot = &mot[mbnum+mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ }
+ }
+ else /* only Spatial Candidate (four candidates)*/
+ {
+ if (type_pred == 0) /*first pass*/
+ {
+ if (imb > 1) /* neighbor two blocks away to the left */
+ {
+ pmot = &mot[mbnum-2][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (imb > 0 && jmb > 0) /* upper-left neighbor */
+ {
+ pmot = &mot[mbnum-mbwidth-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (jmb > 0 && imb < mbheight - 1) /* upper right neighbor */
+ {
+ pmot = &mot[mbnum-mbwidth+1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ }
+//#ifdef SCENE_CHANGE_DETECTION
+ /* second pass (ST2 algorithm)*/
+ else if (type_pred == 1) /* 4/7/01 */
+ {
+ if (imb > 0) /*left neighbor current frame */
+ {
+ pmot = &mot[mbnum-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (jmb > 0) /*upper neighbor current frame */
+ {
+ pmot = &mot[mbnum-mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (imb < mbwidth - 1) /*right neighbor current frame */
+ {
+ pmot = &mot[mbnum+1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ if (jmb < mbheight - 1) /*bottom neighbor current frame */
+ {
+ pmot = &mot[mbnum+mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ }
+//#else
+ else /* original ST1 algorithm */
+ {
+ if (imb > 0) /*left neighbor current frame */
+ {
+ pmot = &mot[mbnum-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+
+ if (jmb > 0) /*upper-left neighbor current frame */
+ {
+ pmot = &mot[mbnum-mbwidth-1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+
+ }
+ if (jmb > 0) /*upper neighbor current frame */
+ {
+ pmot = &mot[mbnum-mbwidth][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+
+ if (imb < mbheight - 1) /*upper-right neighbor current frame */
+ {
+ pmot = &mot[mbnum-mbwidth+1][0];
+ mvx[(*num_can)] = (pmot->x) >> 1;
+ mvy[(*num_can)++] = (pmot->y) >> 1;
+ }
+ }
+ }
+//#endif
+ }
+
+ /* 3/23/01, remove redundant candidate (possible k-mean) */
+ num1 = *num_can;
+ *num_can = 1;
+ for (i = 1; i < num1; i++)
+ {
+ same = 0;
+ j = 0;
+ while (!same && j < *num_can)
+ {
+#if (CANDIDATE_DISTANCE==0)
+ if (mvx[i] == mvx[j] && mvy[i] == mvy[j])
+#else
+ // modified k-mean, 3/24/01, shouldn't be greater than 3
+ if (PV_ABS(mvx[i] - mvx[j]) + PV_ABS(mvy[i] - mvy[j]) < CANDIDATE_DISTANCE)
+#endif
+ same = 1;
+ j++;
+ }
+ if (!same)
+ {
+ mvx[*num_can] = mvx[i];
+ mvy[*num_can] = mvy[i];
+ (*num_can)++;
+ }
+ }
+
+#ifdef _SAD_STAT
+ num_cand += (*num_can);
+#endif
+
+ if (num1 == 5 && *num_can == 1)
+ *num_can = ALL_CAND_EQUAL; /* all are equal */
+
+ return ;
+}
+
+/*===========================================================================
+ Function: RasterIntraUpdate
+ Date: 2/26/01
+ Purpose: To raster-scan assign INTRA-update .
+ N macroblocks are updated (also was programmable).
+===========================================================================*/
+void RasterIntraUpdate(UChar *intraArray, UChar *Mode, Int totalMB, Int numRefresh)
+{
+ Int indx, i;
+
+ /* find the last refresh MB */
+ indx = 0;
+ while (intraArray[indx] == 1 && indx < totalMB)
+ indx++;
+
+ /* add more */
+ for (i = 0; i < numRefresh && indx < totalMB; i++)
+ {
+ Mode[indx] = MODE_INTRA;
+ intraArray[indx++] = 1;
+ }
+
+ /* if read the end of frame, reset and loop around */
+ if (indx >= totalMB - 1)
+ {
+ ResetIntraUpdate(intraArray, totalMB);
+ indx = 0;
+ while (i < numRefresh && indx < totalMB)
+ {
+ intraArray[indx] = 1;
+ Mode[indx++] = MODE_INTRA;
+ i++;
+ }
+ }
+
+ return ;
+}
+
+/*===========================================================================
+ Function: ResetIntraUpdate
+ Date: 11/28/00
+ Purpose: Reset already intra updated flags to all zero
+===========================================================================*/
+
+void ResetIntraUpdate(UChar *intraArray, Int totalMB)
+{
+ M4VENC_MEMSET(intraArray, 0, sizeof(UChar)*totalMB);
+ return ;
+}
+
+/*===========================================================================
+ Function: ResetIntraUpdateRegion
+ Date: 12/1/00
+ Purpose: Reset already intra updated flags in one region to all zero
+===========================================================================*/
+void ResetIntraUpdateRegion(UChar *intraArray, Int start_i, Int rwidth,
+ Int start_j, Int rheight, Int mbwidth, Int mbheight)
+{
+ Int indx, j;
+
+ if (start_i + rwidth >= mbwidth)
+ rwidth = mbwidth - start_i;
+ if (start_j + rheight >= mbheight)
+ rheight = mbheight - start_j;
+
+ for (j = start_j; j < start_j + rheight; j++)
+ {
+ indx = j * mbwidth;
+ M4VENC_MEMSET(intraArray + indx + start_i, 0, sizeof(UChar)*rwidth);
+ }
+
+ return ;
+}
+
+/*************************************************************
+ Function: MoveNeighborSAD
+ Date: 3/27/01
+ Purpose: Move neighboring SAD around when center has shifted
+*************************************************************/
+
+void MoveNeighborSAD(Int dn[], Int new_loc)
+{
+ Int tmp[9];
+ tmp[0] = dn[0];
+ tmp[1] = dn[1];
+ tmp[2] = dn[2];
+ tmp[3] = dn[3];
+ tmp[4] = dn[4];
+ tmp[5] = dn[5];
+ tmp[6] = dn[6];
+ tmp[7] = dn[7];
+ tmp[8] = dn[8];
+ dn[0] = dn[1] = dn[2] = dn[3] = dn[4] = dn[5] = dn[6] = dn[7] = dn[8] = 65536;
+
+ switch (new_loc)
+ {
+ case 0:
+ break;
+ case 1:
+ dn[4] = tmp[2];
+ dn[5] = tmp[0];
+ dn[6] = tmp[8];
+ break;
+ case 2:
+ dn[4] = tmp[3];
+ dn[5] = tmp[4];
+ dn[6] = tmp[0];
+ dn[7] = tmp[8];
+ dn[8] = tmp[1];
+ break;
+ case 3:
+ dn[6] = tmp[4];
+ dn[7] = tmp[0];
+ dn[8] = tmp[2];
+ break;
+ case 4:
+ dn[1] = tmp[2];
+ dn[2] = tmp[3];
+ dn[6] = tmp[5];
+ dn[7] = tmp[6];
+ dn[8] = tmp[0];
+ break;
+ case 5:
+ dn[1] = tmp[0];
+ dn[2] = tmp[4];
+ dn[8] = tmp[6];
+ break;
+ case 6:
+ dn[1] = tmp[8];
+ dn[2] = tmp[0];
+ dn[3] = tmp[4];
+ dn[4] = tmp[5];
+ dn[8] = tmp[7];
+ break;
+ case 7:
+ dn[2] = tmp[8];
+ dn[3] = tmp[0];
+ dn[4] = tmp[6];
+ break;
+ case 8:
+ dn[2] = tmp[1];
+ dn[3] = tmp[2];
+ dn[4] = tmp[0];
+ dn[5] = tmp[6];
+ dn[6] = tmp[7];
+ break;
+ }
+ dn[0] = tmp[new_loc];
+
+ return ;
+}
+
+/* 3/28/01, find minimal of dn[9] */
+
+Int FindMin(Int dn[])
+{
+ Int min, i;
+ Int dmin;
+
+ dmin = dn[1];
+ min = 1;
+ for (i = 2; i < 9; i++)
+ {
+ if (dn[i] < dmin)
+ {
+ dmin = dn[i];
+ min = i;
+ }
+ }
+
+ return min;
+}
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h
new file mode 100644
index 0000000..0d5a3e8
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4def.h
@@ -0,0 +1,229 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _PVDECDEF_H_
+#define _PVDECDEF_H_
+
+#include <stdint.h> // for uint8_t, etc
+#include <stdlib.h>
+#include <string.h>
+
+// Redefine the int types
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef int16_t int16;
+typedef uint32_t uint32;
+typedef int32_t int32;
+typedef unsigned int uint;
+
+/********** platform dependent in-line assembly *****************************/
+
+/*************** Intel *****************/
+
+/*************** ARM *****************/
+/* for general ARM instruction. #define __ARM has to be defined in compiler set up.*/
+/* for DSP MUL */
+#ifdef __TARGET_FEATURE_DSPMUL
+#define _ARM_DSP_MUL
+#endif
+
+/* for Count Leading Zero instruction */
+#ifdef __TARGET_ARCH_5T
+#define _ARM_CLZ
+#endif
+#ifdef __TARGET_ARCH_5TE
+#define _ARM_CLZ
+#endif
+/****************************************************************************/
+
+#ifndef _PV_TYPES_
+#define _PV_TYPES_
+typedef unsigned char UChar;
+typedef char Char;
+typedef unsigned int UInt;
+typedef int Int;
+typedef unsigned short UShort;
+typedef short Short;
+typedef short int SInt;
+typedef unsigned int Bool;
+typedef unsigned long ULong;
+typedef void Void;
+
+#define PV_CODEC_INIT 0
+#define PV_CODEC_STOP 1
+#define PV_CODEC_RUNNING 2
+#define PV_CODEC_RESET 3
+#endif
+
+typedef enum
+{
+ PV_SUCCESS,
+ PV_FAIL,
+ PV_EOS, /* hit End_Of_Sequence */
+ PV_MB_STUFFING, /* hit Macroblock_Stuffing */
+ PV_END_OF_VOP, /* hit End_of_Video_Object_Plane */
+ PV_END_OF_MB, /* hit End_of_Macroblock */
+ PV_END_OF_BUF /* hit End_of_Bitstream_Buffer */
+} PV_STATUS;
+
+typedef UChar PIXEL;
+//typedef Int MOT; /* : "int" type runs faster on RISC machine */
+
+#define HTFM /* 3/2/01, Hypothesis Test Fast Matching for early drop-out*/
+//#define _MOVE_INTERFACE
+
+//#define RANDOM_REFSELCODE
+
+/* handle the case of devision by zero in RC */
+#define MAD_MIN 1
+
+/* 4/11/01, if SSE or MMX, no HTFM, no SAD_HP_FLY */
+
+/* Code size reduction related Macros */
+#ifdef H263_ONLY
+#ifndef NO_RVLC
+#define NO_RVLC
+#endif
+#ifndef NO_MPEG_QUANT
+#define NO_MPEG_QUANT
+#endif
+#ifndef NO_INTER4V
+#define NO_INTER4V
+#endif
+#endif
+/**************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+#define PV_ABS(x) (((x)<0)? -(x) : (x))
+#define PV_SIGN(x) (((x)<0)? -1 : 1)
+#define PV_SIGN0(a) (((a)<0)? -1 : (((a)>0) ? 1 : 0))
+#define PV_MAX(a,b) ((a)>(b)? (a):(b))
+#define PV_MIN(a,b) ((a)<(b)? (a):(b))
+
+#define MODE_INTRA 0
+#define MODE_INTER 1
+#define MODE_INTRA_Q 2
+#define MODE_INTER_Q 3
+#define MODE_INTER4V 4
+#define MODE_SKIPPED 6
+
+#define I_VOP 0
+#define P_VOP 1
+#define B_VOP 2
+
+/*09/04/00 Add MB height and width */
+#define MB_WIDTH 16
+#define MB_HEIGHT 16
+
+#define VOP_BRIGHT_WHITEENC 255
+
+
+#define LUMINANCE_DC_TYPE 1
+#define CHROMINANCE_DC_TYPE 2
+
+#define EOB_CODE 1
+#define EOB_CODE_LENGTH 32
+
+/* 11/30/98 */
+#define FoundRM 1 /* Resync Marker */
+#define FoundVSC 2 /* VOP_START_CODE. */
+#define FoundGSC 3 /* GROUP_START_CODE */
+#define FoundEOB 4 /* EOB_CODE */
+
+
+/* 05/08/2000, the error code returned from BitstreamShowBits() */
+#define BITSTREAM_ERROR_CODE 0xFFFFFFFF
+
+/* PacketVideo "absolution timestamp" object. 06/13/2000 */
+#define PVTS_START_CODE 0x01C4
+#define PVTS_START_CODE_LENGTH 32
+
+/* session layer and vop layer start codes */
+
+#define SESSION_START_CODE 0x01B0
+#define SESSION_END_CODE 0x01B1
+#define VISUAL_OBJECT_START_CODE 0x01B5
+
+#define VO_START_CODE 0x8
+#define VO_HEADER_LENGTH 32 /* lengtho of VO header: VO_START_CODE + VO_ID */
+
+#define SOL_START_CODE 0x01BE
+#define SOL_START_CODE_LENGTH 32
+
+#define VOL_START_CODE 0x12
+#define VOL_START_CODE_LENGTH 28
+
+#define VOP_START_CODE 0x1B6
+#define VOP_START_CODE_LENGTH 32
+
+#define GROUP_START_CODE 0x01B3
+#define GROUP_START_CODE_LENGTH 32
+
+#define VOP_ID_CODE_LENGTH 5
+#define VOP_TEMP_REF_CODE_LENGTH 16
+
+#define USER_DATA_START_CODE 0x01B2
+#define USER_DATA_START_CODE_LENGTH 32
+
+#define START_CODE_PREFIX 0x01
+#define START_CODE_PREFIX_LENGTH 24
+
+#define SHORT_VIDEO_START_MARKER 0x20
+#define SHORT_VIDEO_START_MARKER_LENGTH 22
+#define SHORT_VIDEO_END_MARKER 0x3F
+#define GOB_RESYNC_MARKER 0x01
+#define GOB_RESYNC_MARKER_LENGTH 17
+
+/* motion and resync markers used in error resilient mode */
+
+#define DC_MARKER 438273
+#define DC_MARKER_LENGTH 19
+
+#define MOTION_MARKER_COMB 126977
+#define MOTION_MARKER_COMB_LENGTH 17
+
+#define MOTION_MARKER_SEP 81921
+#define MOTION_MARKER_SEP_LENGTH 17
+
+#define RESYNC_MARKER 1
+#define RESYNC_MARKER_LENGTH 17
+
+#define SPRITE_NOT_USED 0
+#define STATIC_SPRITE 1
+#define ONLINE_SPRITE 2
+#define GMC_SPRITE 3
+
+/* macroblock and block size */
+#define MB_SIZE 16
+#define NCOEFF_MB (MB_SIZE*MB_SIZE)
+#define B_SIZE 8
+#define NCOEFF_BLOCK (B_SIZE*B_SIZE)
+#define NCOEFF_Y NCOEFF_MB
+#define NCOEFF_U NCOEFF_BLOCK
+#define NCOEFF_V NCOEFF_BLOCK
+
+/* overrun buffer size */
+#define DEFAULT_OVERRUN_BUFFER_SIZE 1000
+
+
+/* VLC decoding related definitions */
+#define VLC_ERROR (-1)
+#define VLC_ESCAPE 7167
+
+#endif /* _PVDECDEF_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
new file mode 100644
index 0000000..946e3d0
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_api.cpp
@@ -0,0 +1,3278 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#include "mp4enc_lib.h"
+#include "bitstream_io.h"
+#include "rate_control.h"
+#include "m4venc_oscl.h"
+
+
+/* Inverse normal zigzag */
+const static Int zigzag_i[NCOEFF_BLOCK] =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+/* INTRA */
+const static Int mpeg_iqmat_def[NCOEFF_BLOCK] =
+ { 8, 17, 18, 19, 21, 23, 25, 27,
+ 17, 18, 19, 21, 23, 25, 27, 28,
+ 20, 21, 22, 23, 24, 26, 28, 30,
+ 21, 22, 23, 24, 26, 28, 30, 32,
+ 22, 23, 24, 26, 28, 30, 32, 35,
+ 23, 24, 26, 28, 30, 32, 35, 38,
+ 25, 26, 28, 30, 32, 35, 38, 41,
+ 27, 28, 30, 32, 35, 38, 41, 45
+ };
+
+/* INTER */
+const static Int mpeg_nqmat_def[64] =
+ { 16, 17, 18, 19, 20, 21, 22, 23,
+ 17, 18, 19, 20, 21, 22, 23, 24,
+ 18, 19, 20, 21, 22, 23, 24, 25,
+ 19, 20, 21, 22, 23, 24, 26, 27,
+ 20, 21, 22, 23, 25, 26, 27, 28,
+ 21, 22, 23, 24, 26, 27, 28, 30,
+ 22, 23, 24, 26, 27, 28, 30, 31,
+ 23, 24, 25, 27, 28, 30, 31, 33
+ };
+
+/* Profiles and levels */
+/* Simple profile(level 0-3) and Core profile (level 1-2) */
+/* {SPL0, SPL1, SPL2, SPL3, CPL1, CPL2, CPL2, CPL2} , SPL0: Simple Profile@Level0, CPL1: Core Profile@Level1, the last two are redundant for easy table manipulation */
+const static Int profile_level_code[8] =
+{
+ 0x08, 0x01, 0x02, 0x03, 0x21, 0x22, 0x22, 0x22
+};
+
+const static Int profile_level_max_bitrate[8] =
+{
+ 64000, 64000, 128000, 384000, 384000, 2000000, 2000000, 2000000
+};
+
+const static Int profile_level_max_packet_size[8] =
+{
+ 2048, 2048, 4096, 8192, 4096, 8192, 8192, 8192
+};
+
+const static Int profile_level_max_mbsPerSec[8] =
+{
+ 1485, 1485, 5940, 11880, 5940, 23760, 23760, 23760
+};
+
+const static Int profile_level_max_VBV_size[8] =
+{
+ 163840, 163840, 655360, 655360, 262144, 1310720, 1310720, 1310720
+};
+
+
+/* Simple scalable profile (level 0-2) and Core scalable profile (level 1-3) */
+/* {SSPL0, SSPL1, SSPL2, SSPL2, CSPL1, CSPL2, CSPL3, CSPL3} , SSPL0: Simple Scalable Profile@Level0, CSPL1: Core Scalable Profile@Level1, the fourth is redundant for easy table manipulation */
+
+const static Int scalable_profile_level_code[8] =
+{
+ 0x10, 0x11, 0x12, 0x12, 0xA1, 0xA2, 0xA3, 0xA3
+};
+
+const static Int scalable_profile_level_max_bitrate[8] =
+{
+ 128000, 128000, 256000, 256000, 768000, 1500000, 4000000, 4000000
+};
+
+/* in bits */
+const static Int scalable_profile_level_max_packet_size[8] =
+{
+ 2048, 2048, 4096, 4096, 4096, 4096, 16384, 16384
+};
+
+const static Int scalable_profile_level_max_mbsPerSec[8] =
+{
+ 1485, 7425, 23760, 23760, 14850, 29700, 120960, 120960
+};
+
+const static Int scalable_profile_level_max_VBV_size[8] =
+{
+ 163840, 655360, 655360, 655360, 1048576, 1310720, 1310720, 1310720
+};
+
+
+/* H263 profile 0 @ level 10-70 */
+const static Int h263Level[8] = {0, 10, 20, 30, 40, 50, 60, 70};
+const static float rBR_bound[8] = {0, 1, 2, 6, 32, 64, 128, 256};
+const static float max_h263_framerate[2] = {(float)30000 / (float)2002,
+ (float)30000 / (float)1001
+ };
+const static Int max_h263_width[2] = {176, 352};
+const static Int max_h263_height[2] = {144, 288};
+
+/* 6/2/2001, newly added functions to make PVEncodeVop more readable. */
+Int DetermineCodingLayer(VideoEncData *video, Int *nLayer, ULong modTime);
+void DetermineVopType(VideoEncData *video, Int currLayer);
+Int UpdateSkipNextFrame(VideoEncData *video, ULong *modTime, Int *size, PV_STATUS status);
+Bool SetProfile_BufferSize(VideoEncData *video, float delay, Int bInitialized);
+
+#ifdef PRINT_RC_INFO
+extern FILE *facct;
+extern int tiTotalNumBitsGenerated;
+extern int iStuffBits;
+#endif
+
+#ifdef PRINT_EC
+extern FILE *fec;
+#endif
+
+
+/* ======================================================================== */
+/* Function : PVGetDefaultEncOption() */
+/* Date : 12/12/2005 */
+/* Purpose : */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetDefaultEncOption(VideoEncOptions *encOption, Int encUseCase)
+{
+ VideoEncOptions defaultUseCase = {H263_MODE, profile_level_max_packet_size[SIMPLE_PROFILE_LEVEL0] >> 3,
+ SIMPLE_PROFILE_LEVEL0, PV_OFF, 0, 1, 1000, 33, {144, 144}, {176, 176}, {15, 30}, {64000, 128000},
+ {10, 10}, {12, 12}, {0, 0}, CBR_1, 0.0, PV_OFF, -1, 0, PV_OFF, 16, PV_OFF, 0, PV_ON
+ };
+
+ OSCL_UNUSED_ARG(encUseCase); // unused for now. Later we can add more defaults setting and use this
+ // argument to select the right one.
+ /* in the future we can create more meaningful use-cases */
+ if (encOption == NULL)
+ {
+ return PV_FALSE;
+ }
+
+ M4VENC_MEMCPY(encOption, &defaultUseCase, sizeof(VideoEncOptions));
+
+ return PV_TRUE;
+}
+
+/* ======================================================================== */
+/* Function : PVInitVideoEncoder() */
+/* Date : 08/22/2000 */
+/* Purpose : Initialization of MP4 Encoder and VO bitstream */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : 5/21/01, allocate only yChan and assign uChan & vChan */
+/* 12/12/05, add encoding option as input argument */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVInitVideoEncoder(VideoEncControls *encoderControl, VideoEncOptions *encOption)
+{
+
+ Bool status = PV_TRUE;
+ Int nLayers, idx, i, j;
+ Int max = 0, max_width = 0, max_height = 0, pitch, offset;
+ Int size = 0, nTotalMB = 0;
+ VideoEncData *video;
+ Vol *pVol;
+ VideoEncParams *pEncParams;
+ Int temp_w, temp_h, mbsPerSec;
+
+ /******************************************/
+ /* this part use to be PVSetEncode() */
+ Int profile_table_index, *profile_level_table;
+ Int profile_level = encOption->profile_level;
+ Int PacketSize = encOption->packetSize << 3;
+ Int timeInc, timeIncRes;
+ float profile_max_framerate;
+ VideoEncParams *encParams;
+
+ if (encoderControl->videoEncoderData) /* this has been called */
+ {
+ if (encoderControl->videoEncoderInit) /* check if PVInitVideoEncoder() has been called */
+ {
+ PVCleanUpVideoEncoder(encoderControl);
+ encoderControl->videoEncoderInit = 0;
+ }
+
+ M4VENC_FREE(encoderControl->videoEncoderData);
+ encoderControl->videoEncoderData = NULL;
+ }
+ encoderControl->videoEncoderInit = 0; /* reset this value */
+
+ video = (VideoEncData *)M4VENC_MALLOC(sizeof(VideoEncData)); /* allocate memory for encData */
+
+ if (video == NULL)
+ return PV_FALSE;
+
+ M4VENC_MEMSET(video, 0, sizeof(VideoEncData));
+
+ encoderControl->videoEncoderData = (void *) video; /* set up pointer in VideoEncData structure */
+
+ video->encParams = (VideoEncParams *)M4VENC_MALLOC(sizeof(VideoEncParams));
+ if (video->encParams == NULL)
+ goto CLEAN_UP;
+
+ M4VENC_MEMSET(video->encParams, 0, sizeof(VideoEncParams));
+
+ encParams = video->encParams;
+ encParams->nLayers = encOption->numLayers;
+
+ /* Check whether the input packetsize is valid (Note: put code here (before any memory allocation) in order to avoid memory leak */
+ if ((Int)profile_level < (Int)(SIMPLE_SCALABLE_PROFILE_LEVEL0)) /* non-scalable profile */
+ {
+ profile_level_table = (Int *)profile_level_max_packet_size;
+ profile_table_index = (Int)profile_level;
+ if (encParams->nLayers != 1)
+ {
+ goto CLEAN_UP;
+ }
+
+ encParams->LayerMaxMbsPerSec[0] = profile_level_max_mbsPerSec[profile_table_index];
+
+ }
+ else /* scalable profile */
+ {
+ profile_level_table = (Int *)scalable_profile_level_max_packet_size;
+ profile_table_index = (Int)profile_level - (Int)(SIMPLE_SCALABLE_PROFILE_LEVEL0);
+ if (encParams->nLayers < 2)
+ {
+ goto CLEAN_UP;
+ }
+ for (i = 0; i < encParams->nLayers; i++)
+ {
+ encParams->LayerMaxMbsPerSec[i] = scalable_profile_level_max_mbsPerSec[profile_table_index];
+ }
+
+ }
+
+ /* cannot have zero size packet with these modes */
+ if (PacketSize == 0)
+ {
+ if (encOption->encMode == DATA_PARTITIONING_MODE)
+ {
+ goto CLEAN_UP;
+ }
+ if (encOption->encMode == COMBINE_MODE_WITH_ERR_RES)
+ {
+ encOption->encMode = COMBINE_MODE_NO_ERR_RES;
+ }
+ }
+
+ if (encOption->gobHeaderInterval == 0)
+ {
+ if (encOption->encMode == H263_MODE_WITH_ERR_RES)
+ {
+ encOption->encMode = H263_MODE;
+ }
+
+ if (encOption->encMode == SHORT_HEADER_WITH_ERR_RES)
+ {
+ encOption->encMode = SHORT_HEADER;
+ }
+ }
+
+ if (PacketSize > profile_level_table[profile_table_index])
+ goto CLEAN_UP;
+
+ /* Initial Defaults for all Modes */
+
+ encParams->SequenceStartCode = 1;
+ encParams->GOV_Enabled = 0;
+ encParams->RoundingType = 0;
+ encParams->IntraDCVlcThr = PV_MAX(PV_MIN(encOption->intraDCVlcTh, 7), 0);
+ encParams->ACDCPrediction = ((encOption->useACPred == PV_ON) ? TRUE : FALSE);
+ encParams->RC_Type = encOption->rcType;
+ encParams->Refresh = encOption->numIntraMB;
+ encParams->ResyncMarkerDisable = 0; /* Enable Resync Marker */
+
+ for (i = 0; i < encOption->numLayers; i++)
+ {
+#ifdef NO_MPEG_QUANT
+ encParams->QuantType[i] = 0;
+#else
+ encParams->QuantType[i] = encOption->quantType[i]; /* H263 */
+#endif
+ if (encOption->pQuant[i] >= 1 && encOption->pQuant[i] <= 31)
+ {
+ encParams->InitQuantPvop[i] = encOption->pQuant[i];
+ }
+ else
+ {
+ goto CLEAN_UP;
+ }
+ if (encOption->iQuant[i] >= 1 && encOption->iQuant[i] <= 31)
+ {
+ encParams->InitQuantIvop[i] = encOption->iQuant[i];
+ }
+ else
+ {
+ goto CLEAN_UP;
+ }
+ }
+
+ encParams->HalfPel_Enabled = 1;
+ encParams->SearchRange = encOption->searchRange; /* 4/16/2001 */
+ encParams->FullSearch_Enabled = 0;
+#ifdef NO_INTER4V
+ encParams->MV8x8_Enabled = 0;
+#else
+ encParams->MV8x8_Enabled = 0;// comment out for now!! encOption->mv8x8Enable;
+#endif
+ encParams->H263_Enabled = 0;
+ encParams->GOB_Header_Interval = 0; // need to be reset to 0
+ encParams->IntraPeriod = encOption->intraPeriod; /* Intra update period update default*/
+ encParams->SceneChange_Det = encOption->sceneDetect;
+ encParams->FineFrameSkip_Enabled = 0;
+ encParams->NoFrameSkip_Enabled = encOption->noFrameSkipped;
+ encParams->NoPreSkip_Enabled = encOption->noFrameSkipped;
+ encParams->GetVolHeader[0] = 0;
+ encParams->GetVolHeader[1] = 0;
+ encParams->ResyncPacketsize = encOption->packetSize << 3;
+ encParams->LayerMaxBitRate[0] = 0;
+ encParams->LayerMaxBitRate[1] = 0;
+ encParams->LayerMaxFrameRate[0] = (float)0.0;
+ encParams->LayerMaxFrameRate[1] = (float)0.0;
+ encParams->VBV_delay = encOption->vbvDelay; /* 2sec VBV buffer size */
+
+ switch (encOption->encMode)
+ {
+
+ case SHORT_HEADER:
+ case SHORT_HEADER_WITH_ERR_RES:
+
+ /* From Table 6-26 */
+ encParams->nLayers = 1;
+ encParams->QuantType[0] = 0; /*H263 */
+ encParams->ResyncMarkerDisable = 1; /* Disable Resync Marker */
+ encParams->DataPartitioning = 0; /* Combined Mode */
+ encParams->ReversibleVLC = 0; /* Disable RVLC */
+ encParams->RoundingType = 0;
+ encParams->IntraDCVlcThr = 7; /* use_intra_dc_vlc = 0 */
+ encParams->MV8x8_Enabled = 0;
+
+ encParams->GOB_Header_Interval = encOption->gobHeaderInterval;
+ encParams->H263_Enabled = 2;
+ encParams->GOV_Enabled = 0;
+ encParams->TimeIncrementRes = 30000; /* timeIncrementRes for H263 */
+ break;
+
+ case H263_MODE:
+ case H263_MODE_WITH_ERR_RES:
+
+ /* From Table 6-26 */
+ encParams->nLayers = 1;
+ encParams->QuantType[0] = 0; /*H263 */
+ encParams->ResyncMarkerDisable = 1; /* Disable Resync Marker */
+ encParams->DataPartitioning = 0; /* Combined Mode */
+ encParams->ReversibleVLC = 0; /* Disable RVLC */
+ encParams->RoundingType = 0;
+ encParams->IntraDCVlcThr = 7; /* use_intra_dc_vlc = 0 */
+ encParams->MV8x8_Enabled = 0;
+
+ encParams->H263_Enabled = 1;
+ encParams->GOV_Enabled = 0;
+ encParams->TimeIncrementRes = 30000; /* timeIncrementRes for H263 */
+
+ break;
+#ifndef H263_ONLY
+ case DATA_PARTITIONING_MODE:
+
+ encParams->DataPartitioning = 1; /* Base Layer Data Partitioning */
+ encParams->ResyncMarkerDisable = 0; /* Resync Marker */
+#ifdef NO_RVLC
+ encParams->ReversibleVLC = 0;
+#else
+ encParams->ReversibleVLC = (encOption->rvlcEnable == PV_ON); /* RVLC when Data Partitioning */
+#endif
+ encParams->ResyncPacketsize = PacketSize;
+ break;
+
+ case COMBINE_MODE_WITH_ERR_RES:
+
+ encParams->DataPartitioning = 0; /* Combined Mode */
+ encParams->ResyncMarkerDisable = 0; /* Resync Marker */
+ encParams->ReversibleVLC = 0; /* No RVLC */
+ encParams->ResyncPacketsize = PacketSize;
+ break;
+
+ case COMBINE_MODE_NO_ERR_RES:
+
+ encParams->DataPartitioning = 0; /* Combined Mode */
+ encParams->ResyncMarkerDisable = 1; /* Disable Resync Marker */
+ encParams->ReversibleVLC = 0; /* No RVLC */
+ break;
+#endif
+ default:
+ goto CLEAN_UP;
+ }
+ /* Set the constraints (maximum values) according to the input profile and level */
+ /* Note that profile_table_index is already figured out above */
+
+ /* base layer */
+ encParams->profile_table_index = profile_table_index; /* Used to limit the profile and level in SetProfile_BufferSize() */
+
+ /* check timeIncRes */
+ timeIncRes = encOption->timeIncRes;
+ timeInc = encOption->tickPerSrc;
+
+ if ((timeIncRes >= 1) && (timeIncRes <= 65536) && (timeInc < timeIncRes) && (timeInc != 0))
+ {
+ if (!encParams->H263_Enabled)
+ {
+ encParams->TimeIncrementRes = timeIncRes;
+ }
+ else
+ {
+ encParams->TimeIncrementRes = 30000;
+// video->FrameRate = 30000/(float)1001; /* fix it to 29.97 fps */
+ }
+ video->FrameRate = timeIncRes / ((float)timeInc);
+ }
+ else
+ {
+ goto CLEAN_UP;
+ }
+
+ /* check frame dimension */
+ if (encParams->H263_Enabled)
+ {
+ switch (encOption->encWidth[0])
+ {
+ case 128:
+ if (encOption->encHeight[0] != 96) /* source_format = 1 */
+ goto CLEAN_UP;
+ break;
+ case 176:
+ if (encOption->encHeight[0] != 144) /* source_format = 2 */
+ goto CLEAN_UP;
+ break;
+ case 352:
+ if (encOption->encHeight[0] != 288) /* source_format = 2 */
+ goto CLEAN_UP;
+ break;
+
+ case 704:
+ if (encOption->encHeight[0] != 576) /* source_format = 2 */
+ goto CLEAN_UP;
+ break;
+ case 1408:
+ if (encOption->encHeight[0] != 1152) /* source_format = 2 */
+ goto CLEAN_UP;
+ break;
+
+ default:
+ goto CLEAN_UP;
+ }
+ }
+ for (i = 0; i < encParams->nLayers; i++)
+ {
+ encParams->LayerHeight[i] = encOption->encHeight[i];
+ encParams->LayerWidth[i] = encOption->encWidth[i];
+ }
+
+ /* check frame rate */
+ for (i = 0; i < encParams->nLayers; i++)
+ {
+ encParams->LayerFrameRate[i] = encOption->encFrameRate[i];
+ }
+
+ if (encParams->nLayers > 1)
+ {
+ if (encOption->encFrameRate[0] == encOption->encFrameRate[1] ||
+ encOption->encFrameRate[0] == 0. || encOption->encFrameRate[1] == 0.) /* 7/31/03 */
+ goto CLEAN_UP;
+ }
+ /* set max frame rate */
+ for (i = 0; i < encParams->nLayers; i++)
+ {
+
+ /* Make sure the maximum framerate is consistent with the given profile and level */
+ nTotalMB = ((encParams->LayerWidth[i] + 15) / 16) * ((encParams->LayerHeight[i] + 15) / 16);
+
+ if (nTotalMB > 0)
+ profile_max_framerate = (float)encParams->LayerMaxMbsPerSec[i] / (float)nTotalMB;
+
+ else
+ profile_max_framerate = (float)30.0;
+
+ encParams->LayerMaxFrameRate[i] = PV_MIN(profile_max_framerate, encParams->LayerFrameRate[i]);
+ }
+
+ /* check bit rate */
+ /* set max bit rate */
+ for (i = 0; i < encParams->nLayers; i++)
+ {
+ encParams->LayerBitRate[i] = encOption->bitRate[i];
+ encParams->LayerMaxBitRate[i] = encOption->bitRate[i];
+ }
+ if (encParams->nLayers > 1)
+ {
+ if (encOption->bitRate[0] == encOption->bitRate[1] ||
+ encOption->bitRate[0] == 0 || encOption->bitRate[1] == 0) /* 7/31/03 */
+ goto CLEAN_UP;
+ }
+ /* check rate control and vbv delay*/
+ encParams->RC_Type = encOption->rcType;
+
+ if (encOption->vbvDelay == 0.0) /* set to default */
+ {
+ switch (encOption->rcType)
+ {
+ case CBR_1:
+ case CBR_2:
+ encParams->VBV_delay = (float)2.0; /* default 2sec VBV buffer size */
+ break;
+
+ case CBR_LOWDELAY:
+ encParams->VBV_delay = (float)0.5; /* default 0.5sec VBV buffer size */
+ break;
+
+ case VBR_1:
+ case VBR_2:
+ encParams->VBV_delay = (float)10.0; /* default 10sec VBV buffer size */
+ break;
+ default:
+ break;
+ }
+ }
+ else /* force this value */
+ {
+ encParams->VBV_delay = encOption->vbvDelay;
+ }
+
+ /* check search range */
+ if (encParams->H263_Enabled && encOption->searchRange > 16)
+ {
+ encParams->SearchRange = 16; /* 4/16/2001 */
+ }
+
+ /*****************************************/
+ /* checking for conflict between options */
+ /*****************************************/
+
+ if (video->encParams->RC_Type == CBR_1 || video->encParams->RC_Type == CBR_2 || video->encParams->RC_Type == CBR_LOWDELAY) /* if CBR */
+ {
+#ifdef _PRINT_STAT
+ if (video->encParams->NoFrameSkip_Enabled == PV_ON ||
+ video->encParams->NoPreSkip_Enabled == PV_ON) /* don't allow frame skip*/
+ printf("WARNING!!!! CBR with NoFrameSkip\n");
+#endif
+ }
+ else if (video->encParams->RC_Type == CONSTANT_Q) /* constant_Q */
+ {
+ video->encParams->NoFrameSkip_Enabled = PV_ON; /* no frame skip */
+ video->encParams->NoPreSkip_Enabled = PV_ON; /* no frame skip */
+#ifdef _PRINT_STAT
+ printf("Turn on NoFrameSkip\n");
+#endif
+ }
+
+ if (video->encParams->NoFrameSkip_Enabled == PV_ON) /* if no frame skip */
+ {
+ video->encParams->FineFrameSkip_Enabled = PV_OFF;
+#ifdef _PRINT_STAT
+ printf("NoFrameSkip !!! may violate VBV_BUFFER constraint.\n");
+ printf("Turn off FineFrameSkip\n");
+#endif
+ }
+
+ /******************************************/
+ /******************************************/
+
+ nLayers = video->encParams->nLayers; /* Number of Layers to be encoded */
+
+ /* Find the maximum width*height for memory allocation of the VOPs */
+ for (idx = 0; idx < nLayers; idx++)
+ {
+ temp_w = video->encParams->LayerWidth[idx];
+ temp_h = video->encParams->LayerHeight[idx];
+
+ if ((temp_w*temp_h) > max)
+ {
+ max = temp_w * temp_h;
+ max_width = ((temp_w + 15) >> 4) << 4;
+ max_height = ((temp_h + 15) >> 4) << 4;
+ nTotalMB = ((max_width * max_height) >> 8);
+ }
+
+ /* Check if the video size and framerate(MBsPerSec) are vald */
+ mbsPerSec = (Int)(nTotalMB * video->encParams->LayerFrameRate[idx]);
+ if (mbsPerSec > video->encParams->LayerMaxMbsPerSec[idx]) status = PV_FALSE;
+ }
+
+ /****************************************************/
+ /* Set Profile and Video Buffer Size for each layer */
+ /****************************************************/
+ if (video->encParams->RC_Type == CBR_LOWDELAY) video->encParams->VBV_delay = 0.5; /* For CBR_LOWDELAY, we set 0.5sec buffer */
+ status = SetProfile_BufferSize(video, video->encParams->VBV_delay, 1);
+ if (status != PV_TRUE)
+ goto CLEAN_UP;
+
+ /****************************************/
+ /* memory allocation and initialization */
+ /****************************************/
+
+ if (video == NULL) goto CLEAN_UP;
+
+ /* cyclic reference for passing through both structures */
+ video->videoEncControls = encoderControl;
+
+ //video->currLayer = 0; /* Set current Layer to 0 */
+ //video->currFrameNo = 0; /* Set current frame Number to 0 */
+ video->nextModTime = 0;
+ video->nextEncIVop = 0; /* Sets up very first frame to be I-VOP! */
+ video->numVopsInGOP = 0; /* counter for Vops in Gop, 2/8/01 */
+
+ //video->frameRate = video->encParams->LayerFrameRate[0]; /* Set current layer frame rate */
+
+ video->QPMB = (UChar *) M4VENC_MALLOC(nTotalMB * sizeof(UChar)); /* Memory for MB quantizers */
+ if (video->QPMB == NULL) goto CLEAN_UP;
+
+
+ video->headerInfo.Mode = (UChar *) M4VENC_MALLOC(sizeof(UChar) * nTotalMB); /* Memory for MB Modes */
+ if (video->headerInfo.Mode == NULL) goto CLEAN_UP;
+ video->headerInfo.CBP = (UChar *) M4VENC_MALLOC(sizeof(UChar) * nTotalMB); /* Memory for CBP (Y and C) of each MB */
+ if (video->headerInfo.CBP == NULL) goto CLEAN_UP;
+
+ /* Allocating motion vector space and interpolation memory*/
+
+ video->mot = (MOT **)M4VENC_MALLOC(sizeof(MOT *) * nTotalMB);
+ if (video->mot == NULL) goto CLEAN_UP;
+
+ for (idx = 0; idx < nTotalMB; idx++)
+ {
+ video->mot[idx] = (MOT *)M4VENC_MALLOC(sizeof(MOT) * 8);
+ if (video->mot[idx] == NULL)
+ {
+ goto CLEAN_UP;
+ }
+ }
+
+ video->intraArray = (UChar *)M4VENC_MALLOC(sizeof(UChar) * nTotalMB);
+ if (video->intraArray == NULL) goto CLEAN_UP;
+
+ video->sliceNo = (UChar *) M4VENC_MALLOC(nTotalMB); /* Memory for Slice Numbers */
+ if (video->sliceNo == NULL) goto CLEAN_UP;
+ /* Allocating space for predDCAC[][8][16], Not that I intentionally */
+ /* increase the dimension of predDCAC from [][6][15] to [][8][16] */
+ /* so that compilers can generate faster code to indexing the */
+ /* data inside (by using << instead of *). 04/14/2000. */
+ /* 5/29/01, use decoder lib ACDC prediction memory scheme. */
+ video->predDC = (typeDCStore *) M4VENC_MALLOC(nTotalMB * sizeof(typeDCStore));
+ if (video->predDC == NULL) goto CLEAN_UP;
+
+ if (!video->encParams->H263_Enabled)
+ {
+ video->predDCAC_col = (typeDCACStore *) M4VENC_MALLOC(((max_width >> 4) + 1) * sizeof(typeDCACStore));
+ if (video->predDCAC_col == NULL) goto CLEAN_UP;
+
+ /* element zero will be used for storing vertical (col) AC coefficients */
+ /* the rest will be used for storing horizontal (row) AC coefficients */
+ video->predDCAC_row = video->predDCAC_col + 1; /* ACDC */
+
+ video->acPredFlag = (Int *) M4VENC_MALLOC(nTotalMB * sizeof(Int)); /* Memory for acPredFlag */
+ if (video->acPredFlag == NULL) goto CLEAN_UP;
+ }
+
+ video->outputMB = (MacroBlock *) M4VENC_MALLOC(sizeof(MacroBlock)); /* Allocating macroblock space */
+ if (video->outputMB == NULL) goto CLEAN_UP;
+ M4VENC_MEMSET(video->outputMB->block[0], 0, (sizeof(Short) << 6)*6);
+
+ M4VENC_MEMSET(video->dataBlock, 0, sizeof(Short) << 7);
+ /* Allocate (2*packetsize) working bitstreams */
+
+ video->bitstream1 = BitStreamCreateEnc(2 * 4096); /*allocate working stream 1*/
+ if (video->bitstream1 == NULL) goto CLEAN_UP;
+ video->bitstream2 = BitStreamCreateEnc(2 * 4096); /*allocate working stream 2*/
+ if (video->bitstream2 == NULL) goto CLEAN_UP;
+ video->bitstream3 = BitStreamCreateEnc(2 * 4096); /*allocate working stream 3*/
+ if (video->bitstream3 == NULL) goto CLEAN_UP;
+
+ /* allocate overrun buffer */
+ // this buffer is used when user's buffer is too small to hold one frame.
+ // It is not needed for slice-based encoding.
+ if (nLayers == 1)
+ {
+ video->oBSize = encParams->BufferSize[0] >> 3;
+ }
+ else
+ {
+ video->oBSize = PV_MAX((encParams->BufferSize[0] >> 3), (encParams->BufferSize[1] >> 3));
+ }
+
+ if (video->oBSize > DEFAULT_OVERRUN_BUFFER_SIZE || encParams->RC_Type == CONSTANT_Q) // set limit
+ {
+ video->oBSize = DEFAULT_OVERRUN_BUFFER_SIZE;
+ }
+ video->overrunBuffer = (UChar*) M4VENC_MALLOC(sizeof(UChar) * video->oBSize);
+ if (video->overrunBuffer == NULL) goto CLEAN_UP;
+
+
+ video->currVop = (Vop *) M4VENC_MALLOC(sizeof(Vop)); /* Memory for Current VOP */
+ if (video->currVop == NULL) goto CLEAN_UP;
+
+ /* add padding, 09/19/05 */
+ if (video->encParams->H263_Enabled) /* make it conditional 11/28/05 */
+ {
+ pitch = max_width;
+ offset = 0;
+ }
+ else
+ {
+ pitch = max_width + 32;
+ offset = (pitch << 4) + 16;
+ max_height += 32;
+ }
+ size = pitch * max_height;
+
+ video->currVop->yChan = (PIXEL *)M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for currVop Y */
+ if (video->currVop->yChan == NULL) goto CLEAN_UP;
+ video->currVop->uChan = video->currVop->yChan + size;/* Memory for currVop U */
+ video->currVop->vChan = video->currVop->uChan + (size >> 2);/* Memory for currVop V */
+
+ /* shift for the offset */
+ if (offset)
+ {
+ video->currVop->yChan += offset; /* offset to the origin.*/
+ video->currVop->uChan += (offset >> 2) + 4;
+ video->currVop->vChan += (offset >> 2) + 4;
+ }
+
+ video->forwardRefVop = video->currVop; /* Initialize forwardRefVop */
+ video->backwardRefVop = video->currVop; /* Initialize backwardRefVop */
+
+ video->prevBaseVop = (Vop *) M4VENC_MALLOC(sizeof(Vop)); /* Memory for Previous Base Vop */
+ if (video->prevBaseVop == NULL) goto CLEAN_UP;
+ video->prevBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for prevBaseVop Y */
+ if (video->prevBaseVop->yChan == NULL) goto CLEAN_UP;
+ video->prevBaseVop->uChan = video->prevBaseVop->yChan + size; /* Memory for prevBaseVop U */
+ video->prevBaseVop->vChan = video->prevBaseVop->uChan + (size >> 2); /* Memory for prevBaseVop V */
+
+ if (offset)
+ {
+ video->prevBaseVop->yChan += offset; /* offset to the origin.*/
+ video->prevBaseVop->uChan += (offset >> 2) + 4;
+ video->prevBaseVop->vChan += (offset >> 2) + 4;
+ }
+
+
+ if (0) /* If B Frames */
+ {
+ video->nextBaseVop = (Vop *) M4VENC_MALLOC(sizeof(Vop)); /* Memory for Next Base Vop */
+ if (video->nextBaseVop == NULL) goto CLEAN_UP;
+ video->nextBaseVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for nextBaseVop Y */
+ if (video->nextBaseVop->yChan == NULL) goto CLEAN_UP;
+ video->nextBaseVop->uChan = video->nextBaseVop->yChan + size; /* Memory for nextBaseVop U */
+ video->nextBaseVop->vChan = video->nextBaseVop->uChan + (size >> 2); /* Memory for nextBaseVop V */
+
+ if (offset)
+ {
+ video->nextBaseVop->yChan += offset; /* offset to the origin.*/
+ video->nextBaseVop->uChan += (offset >> 2) + 4;
+ video->nextBaseVop->vChan += (offset >> 2) + 4;
+ }
+ }
+
+ if (nLayers > 1) /* If enhancement layers */
+ {
+ video->prevEnhanceVop = (Vop *) M4VENC_MALLOC(sizeof(Vop)); /* Memory for Previous Enhancement Vop */
+ if (video->prevEnhanceVop == NULL) goto CLEAN_UP;
+ video->prevEnhanceVop->yChan = (PIXEL *) M4VENC_MALLOC(sizeof(PIXEL) * (size + (size >> 1))); /* Memory for Previous Ehancement Y */
+ if (video->prevEnhanceVop->yChan == NULL) goto CLEAN_UP;
+ video->prevEnhanceVop->uChan = video->prevEnhanceVop->yChan + size; /* Memory for Previous Enhancement U */
+ video->prevEnhanceVop->vChan = video->prevEnhanceVop->uChan + (size >> 2); /* Memory for Previous Enhancement V */
+
+ if (offset)
+ {
+ video->prevEnhanceVop->yChan += offset; /* offset to the origin.*/
+ video->prevEnhanceVop->uChan += (offset >> 2) + 4;
+ video->prevEnhanceVop->vChan += (offset >> 2) + 4;
+ }
+ }
+
+ video->numberOfLayers = nLayers; /* Number of Layers */
+ video->sumMAD = 0;
+
+
+ /* 04/09/01, for Vops in the use multipass processing */
+ for (idx = 0; idx < nLayers; idx++)
+ {
+ video->pMP[idx] = (MultiPass *)M4VENC_MALLOC(sizeof(MultiPass));
+ if (video->pMP[idx] == NULL) goto CLEAN_UP;
+ M4VENC_MEMSET(video->pMP[idx], 0, sizeof(MultiPass));
+
+ video->pMP[idx]->encoded_frames = -1; /* forget about the very first I frame */
+
+
+ /* RDInfo **pRDSamples */
+ video->pMP[idx]->pRDSamples = (RDInfo **)M4VENC_MALLOC(30 * sizeof(RDInfo *));
+ if (video->pMP[idx]->pRDSamples == NULL) goto CLEAN_UP;
+ for (i = 0; i < 30; i++)
+ {
+ video->pMP[idx]->pRDSamples[i] = (RDInfo *)M4VENC_MALLOC(32 * sizeof(RDInfo));
+ if (video->pMP[idx]->pRDSamples[i] == NULL) goto CLEAN_UP;
+ for (j = 0; j < 32; j++) M4VENC_MEMSET(&(video->pMP[idx]->pRDSamples[i][j]), 0, sizeof(RDInfo));
+ }
+ video->pMP[idx]->frameRange = (Int)(video->encParams->LayerFrameRate[idx] * 1.0); /* 1.0s time frame*/
+ video->pMP[idx]->frameRange = PV_MAX(video->pMP[idx]->frameRange, 5);
+ video->pMP[idx]->frameRange = PV_MIN(video->pMP[idx]->frameRange, 30);
+
+ video->pMP[idx]->framePos = -1;
+
+ }
+ /* /// End /////////////////////////////////////// */
+
+
+ video->vol = (Vol **)M4VENC_MALLOC(nLayers * sizeof(Vol *)); /* Memory for VOL pointers */
+
+ /* Memory allocation and Initialization of Vols and writing of headers */
+ if (video->vol == NULL) goto CLEAN_UP;
+
+ for (idx = 0; idx < nLayers; idx++)
+ {
+ video->volInitialize[idx] = 1;
+ video->refTick[idx] = 0;
+ video->relLayerCodeTime[idx] = 1000;
+ video->vol[idx] = (Vol *)M4VENC_MALLOC(sizeof(Vol));
+ if (video->vol[idx] == NULL) goto CLEAN_UP;
+
+ pVol = video->vol[idx];
+ pEncParams = video->encParams;
+
+ M4VENC_MEMSET(video->vol[idx], 0, sizeof(Vol));
+ /* Initialize some VOL parameters */
+ pVol->volID = idx; /* Set VOL ID */
+ pVol->shortVideoHeader = pEncParams->H263_Enabled; /*Short Header */
+ pVol->GOVStart = pEncParams->GOV_Enabled; /* GOV Header */
+ pVol->timeIncrementResolution = video->encParams->TimeIncrementRes;
+ pVol->nbitsTimeIncRes = 1;
+ while (pVol->timeIncrementResolution > (1 << pVol->nbitsTimeIncRes))
+ {
+ pVol->nbitsTimeIncRes++;
+ }
+
+ /* timing stuff */
+ pVol->timeIncrement = 0;
+ pVol->moduloTimeBase = 0;
+ pVol->fixedVopRate = 0; /* No fixed VOP rate */
+ pVol->stream = (BitstreamEncVideo *)M4VENC_MALLOC(sizeof(BitstreamEncVideo)); /* allocate BitstreamEncVideo Instance */
+ if (pVol->stream == NULL) goto CLEAN_UP;
+
+ pVol->width = pEncParams->LayerWidth[idx]; /* Layer Width */
+ pVol->height = pEncParams->LayerHeight[idx]; /* Layer Height */
+ // pVol->intra_acdcPredDisable = pEncParams->ACDCPrediction; /* ACDC Prediction */
+ pVol->ResyncMarkerDisable = pEncParams->ResyncMarkerDisable; /* Resync Marker Mode */
+ pVol->dataPartitioning = pEncParams->DataPartitioning; /* Data Partitioning */
+ pVol->useReverseVLC = pEncParams->ReversibleVLC; /* RVLC */
+ if (idx > 0) /* Scalability layers */
+ {
+ pVol->ResyncMarkerDisable = 1;
+ pVol->dataPartitioning = 0;
+ pVol->useReverseVLC = 0; /* No RVLC */
+ }
+ pVol->quantType = pEncParams->QuantType[idx]; /* Quantizer Type */
+
+ /* no need to init Quant Matrices */
+
+ pVol->scalability = 0; /* Vol Scalability */
+ if (idx > 0)
+ pVol->scalability = 1; /* Multiple layers => Scalability */
+
+ /* Initialize Vol to Temporal scalability. It can change during encoding */
+ pVol->scalType = 1;
+ /* Initialize reference Vol ID to the base layer = 0 */
+ pVol->refVolID = 0;
+ /* Initialize layer resolution to same as the reference */
+ pVol->refSampDir = 0;
+ pVol->horSamp_m = 1;
+ pVol->horSamp_n = 1;
+ pVol->verSamp_m = 1;
+ pVol->verSamp_n = 1;
+ pVol->enhancementType = 0; /* We always enhance the entire region */
+
+ pVol->nMBPerRow = (pVol->width + 15) / 16;
+ pVol->nMBPerCol = (pVol->height + 15) / 16;
+ pVol->nTotalMB = pVol->nMBPerRow * pVol->nMBPerCol;
+
+ if (pVol->nTotalMB >= 1)
+ pVol->nBitsForMBID = 1;
+ if (pVol->nTotalMB >= 3)
+ pVol->nBitsForMBID = 2;
+ if (pVol->nTotalMB >= 5)
+ pVol->nBitsForMBID = 3;
+ if (pVol->nTotalMB >= 9)
+ pVol->nBitsForMBID = 4;
+ if (pVol->nTotalMB >= 17)
+ pVol->nBitsForMBID = 5;
+ if (pVol->nTotalMB >= 33)
+ pVol->nBitsForMBID = 6;
+ if (pVol->nTotalMB >= 65)
+ pVol->nBitsForMBID = 7;
+ if (pVol->nTotalMB >= 129)
+ pVol->nBitsForMBID = 8;
+ if (pVol->nTotalMB >= 257)
+ pVol->nBitsForMBID = 9;
+ if (pVol->nTotalMB >= 513)
+ pVol->nBitsForMBID = 10;
+ if (pVol->nTotalMB >= 1025)
+ pVol->nBitsForMBID = 11;
+ if (pVol->nTotalMB >= 2049)
+ pVol->nBitsForMBID = 12;
+ if (pVol->nTotalMB >= 4097)
+ pVol->nBitsForMBID = 13;
+ if (pVol->nTotalMB >= 8193)
+ pVol->nBitsForMBID = 14;
+ if (pVol->nTotalMB >= 16385)
+ pVol->nBitsForMBID = 15;
+ if (pVol->nTotalMB >= 32769)
+ pVol->nBitsForMBID = 16;
+ if (pVol->nTotalMB >= 65537)
+ pVol->nBitsForMBID = 17;
+ if (pVol->nTotalMB >= 131073)
+ pVol->nBitsForMBID = 18;
+
+ if (pVol->shortVideoHeader)
+ {
+ switch (pVol->width)
+ {
+ case 128:
+ if (pVol->height == 96) /* source_format = 1 */
+ {
+ pVol->nGOBinVop = 6;
+ pVol->nMBinGOB = 8;
+ }
+ else
+ status = PV_FALSE;
+ break;
+
+ case 176:
+ if (pVol->height == 144) /* source_format = 2 */
+ {
+ pVol->nGOBinVop = 9;
+ pVol->nMBinGOB = 11;
+ }
+ else
+ status = PV_FALSE;
+ break;
+ case 352:
+ if (pVol->height == 288) /* source_format = 2 */
+ {
+ pVol->nGOBinVop = 18;
+ pVol->nMBinGOB = 22;
+ }
+ else
+ status = PV_FALSE;
+ break;
+
+ case 704:
+ if (pVol->height == 576) /* source_format = 2 */
+ {
+ pVol->nGOBinVop = 18;
+ pVol->nMBinGOB = 88;
+ }
+ else
+ status = PV_FALSE;
+ break;
+ case 1408:
+ if (pVol->height == 1152) /* source_format = 2 */
+ {
+ pVol->nGOBinVop = 18;
+ pVol->nMBinGOB = 352;
+ }
+ else
+ status = PV_FALSE;
+ break;
+
+ default:
+ status = PV_FALSE;
+ break;
+ }
+ }
+ }
+
+ /***************************************************/
+ /* allocate and initialize rate control parameters */
+ /***************************************************/
+
+ /* BEGIN INITIALIZATION OF ANNEX L RATE CONTROL */
+ if (video->encParams->RC_Type != CONSTANT_Q)
+ {
+ for (idx = 0; idx < nLayers; idx++) /* 12/25/00 */
+ {
+ video->rc[idx] =
+ (rateControl *)M4VENC_MALLOC(sizeof(rateControl));
+
+ if (video->rc[idx] == NULL) goto CLEAN_UP;
+
+ M4VENC_MEMSET(video->rc[idx], 0, sizeof(rateControl));
+ }
+ if (PV_SUCCESS != RC_Initialize(video))
+ {
+ goto CLEAN_UP;
+ }
+ /* initialization for 2-pass rate control */
+ }
+ /* END INITIALIZATION OF ANNEX L RATE CONTROL */
+
+ /********** assign platform dependent functions ***********************/
+ /* 1/23/01 */
+ /* This must be done at run-time not a compile time */
+ video->functionPointer = (FuncPtr*) M4VENC_MALLOC(sizeof(FuncPtr));
+ if (video->functionPointer == NULL) goto CLEAN_UP;
+
+ video->functionPointer->ComputeMBSum = &ComputeMBSum_C;
+ video->functionPointer->SAD_MB_HalfPel[0] = NULL;
+ video->functionPointer->SAD_MB_HalfPel[1] = &SAD_MB_HalfPel_Cxh;
+ video->functionPointer->SAD_MB_HalfPel[2] = &SAD_MB_HalfPel_Cyh;
+ video->functionPointer->SAD_MB_HalfPel[3] = &SAD_MB_HalfPel_Cxhyh;
+
+#ifndef NO_INTER4V
+ video->functionPointer->SAD_Blk_HalfPel = &SAD_Blk_HalfPel_C;
+ video->functionPointer->SAD_Block = &SAD_Block_C;
+#endif
+ video->functionPointer->SAD_Macroblock = &SAD_Macroblock_C;
+ video->functionPointer->ChooseMode = &ChooseMode_C;
+ video->functionPointer->GetHalfPelMBRegion = &GetHalfPelMBRegion_C;
+// video->functionPointer->SAD_MB_PADDING = &SAD_MB_PADDING; /* 4/21/01 */
+
+
+ encoderControl->videoEncoderInit = 1; /* init done! */
+
+ return PV_TRUE;
+
+CLEAN_UP:
+ PVCleanUpVideoEncoder(encoderControl);
+
+ return PV_FALSE;
+}
+
+
+/* ======================================================================== */
+/* Function : PVCleanUpVideoEncoder() */
+/* Date : 08/22/2000 */
+/* Purpose : Deallocates allocated memory from InitVideoEncoder() */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : 5/21/01, free only yChan in Vop */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVCleanUpVideoEncoder(VideoEncControls *encoderControl)
+{
+ Int idx, i;
+ VideoEncData *video = (VideoEncData *)encoderControl->videoEncoderData;
+ int nTotalMB;
+ int max_width, offset;
+
+#ifdef PRINT_RC_INFO
+ if (facct != NULL)
+ {
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "TOTAL NUM BITS GENERATED %d\n", tiTotalNumBitsGenerated);
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "TOTAL NUMBER OF FRAMES CODED %d\n",
+ video->encParams->rc[0]->totalFrameNumber);
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "Average BitRate %d\n",
+ (tiTotalNumBitsGenerated / (90 / 30)));
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "TOTAL NUMBER OF STUFF BITS %d\n", (iStuffBits + 10740));
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "TOTAL NUMBER OF BITS TO NETWORK %d\n", (35800*90 / 30));;
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "SUM OF STUFF BITS AND GENERATED BITS %d\n",
+ (tiTotalNumBitsGenerated + iStuffBits + 10740));
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fprintf(facct, "UNACCOUNTED DIFFERENCE %d\n",
+ ((35800*90 / 30) - (tiTotalNumBitsGenerated + iStuffBits + 10740)));
+ fprintf(facct, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
+ fclose(facct);
+ }
+#endif
+
+#ifdef PRINT_EC
+ fclose(fec);
+#endif
+
+ if (video != NULL)
+ {
+
+ if (video->QPMB) M4VENC_FREE(video->QPMB);
+ if (video->headerInfo.Mode)M4VENC_FREE(video->headerInfo.Mode);
+ if (video->headerInfo.CBP)M4VENC_FREE(video->headerInfo.CBP);
+
+
+ if (video->mot)
+ {
+ nTotalMB = video->vol[0]->nTotalMB;
+ for (idx = 1; idx < video->currLayer; idx++)
+ if (video->vol[idx]->nTotalMB > nTotalMB)
+ nTotalMB = video->vol[idx]->nTotalMB;
+ for (idx = 0; idx < nTotalMB; idx++)
+ {
+ if (video->mot[idx])
+ M4VENC_FREE(video->mot[idx]);
+ }
+ M4VENC_FREE(video->mot);
+ }
+
+ if (video->intraArray) M4VENC_FREE(video->intraArray);
+
+ if (video->sliceNo)M4VENC_FREE(video->sliceNo);
+ if (video->acPredFlag)M4VENC_FREE(video->acPredFlag);
+// if(video->predDCAC)M4VENC_FREE(video->predDCAC);
+ if (video->predDC) M4VENC_FREE(video->predDC);
+ video->predDCAC_row = NULL;
+ if (video->predDCAC_col) M4VENC_FREE(video->predDCAC_col);
+ if (video->outputMB)M4VENC_FREE(video->outputMB);
+
+ if (video->bitstream1)BitstreamCloseEnc(video->bitstream1);
+ if (video->bitstream2)BitstreamCloseEnc(video->bitstream2);
+ if (video->bitstream3)BitstreamCloseEnc(video->bitstream3);
+
+ if (video->overrunBuffer) M4VENC_FREE(video->overrunBuffer);
+
+ max_width = video->encParams->LayerWidth[0];
+ max_width = (((max_width + 15) >> 4) << 4); /* 09/19/05 */
+ if (video->encParams->H263_Enabled)
+ {
+ offset = 0;
+ }
+ else
+ {
+ offset = ((max_width + 32) << 4) + 16;
+ }
+
+ if (video->currVop)
+ {
+ if (video->currVop->yChan)
+ {
+ video->currVop->yChan -= offset;
+ M4VENC_FREE(video->currVop->yChan);
+ }
+ M4VENC_FREE(video->currVop);
+ }
+
+ if (video->nextBaseVop)
+ {
+ if (video->nextBaseVop->yChan)
+ {
+ video->nextBaseVop->yChan -= offset;
+ M4VENC_FREE(video->nextBaseVop->yChan);
+ }
+ M4VENC_FREE(video->nextBaseVop);
+ }
+
+ if (video->prevBaseVop)
+ {
+ if (video->prevBaseVop->yChan)
+ {
+ video->prevBaseVop->yChan -= offset;
+ M4VENC_FREE(video->prevBaseVop->yChan);
+ }
+ M4VENC_FREE(video->prevBaseVop);
+ }
+ if (video->prevEnhanceVop)
+ {
+ if (video->prevEnhanceVop->yChan)
+ {
+ video->prevEnhanceVop->yChan -= offset;
+ M4VENC_FREE(video->prevEnhanceVop->yChan);
+ }
+ M4VENC_FREE(video->prevEnhanceVop);
+ }
+
+ /* 04/09/01, for Vops in the use multipass processing */
+ for (idx = 0; idx < video->encParams->nLayers; idx++)
+ {
+ if (video->pMP[idx])
+ {
+ if (video->pMP[idx]->pRDSamples)
+ {
+ for (i = 0; i < 30; i++)
+ {
+ if (video->pMP[idx]->pRDSamples[i])
+ M4VENC_FREE(video->pMP[idx]->pRDSamples[i]);
+ }
+ M4VENC_FREE(video->pMP[idx]->pRDSamples);
+ }
+
+ M4VENC_MEMSET(video->pMP[idx], 0, sizeof(MultiPass));
+ M4VENC_FREE(video->pMP[idx]);
+ }
+ }
+ /* // End /////////////////////////////////////// */
+
+ if (video->vol)
+ {
+ for (idx = 0; idx < video->encParams->nLayers; idx++)
+ {
+ if (video->vol[idx])
+ {
+ if (video->vol[idx]->stream)
+ M4VENC_FREE(video->vol[idx]->stream);
+ M4VENC_FREE(video->vol[idx]);
+ }
+ }
+ M4VENC_FREE(video->vol);
+ }
+
+ /***************************************************/
+ /* stop rate control parameters */
+ /***************************************************/
+
+ /* ANNEX L RATE CONTROL */
+ if (video->encParams->RC_Type != CONSTANT_Q)
+ {
+ RC_Cleanup(video->rc, video->encParams->nLayers);
+
+ for (idx = 0; idx < video->encParams->nLayers; idx++)
+ {
+ if (video->rc[idx])
+ M4VENC_FREE(video->rc[idx]);
+ }
+ }
+
+ if (video->functionPointer) M4VENC_FREE(video->functionPointer);
+
+ /* If application has called PVCleanUpVideoEncoder then we deallocate */
+ /* If PVInitVideoEncoder class it, then we DO NOT deallocate */
+ if (video->encParams)
+ {
+ M4VENC_FREE(video->encParams);
+ }
+
+ M4VENC_FREE(video);
+ encoderControl->videoEncoderData = NULL; /* video */
+ }
+
+ encoderControl->videoEncoderInit = 0;
+
+ return PV_TRUE;
+}
+
+/* ======================================================================== */
+/* Function : PVGetVolHeader() */
+/* Date : 7/17/2001, */
+/* Purpose : */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetVolHeader(VideoEncControls *encCtrl, UChar *volHeader, Int *size, Int layer)
+{
+ VideoEncData *encData;
+ PV_STATUS EncodeVOS_Start(VideoEncControls *encCtrl);
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+
+ encData->currLayer = layer; /* Set Layer */
+ /*pv_status = */
+ EncodeVOS_Start(encCtrl); /* Encode VOL Header */
+
+ encData->encParams->GetVolHeader[layer] = 1; /* Set usage flag: Needed to support old method*/
+
+ /* Copy bitstream to buffer and set the size */
+
+ if (*size > encData->bitstream1->byteCount)
+ {
+ *size = encData->bitstream1->byteCount;
+ M4VENC_MEMCPY(volHeader, encData->bitstream1->bitstreamBuffer, *size);
+ }
+ else
+ return PV_FALSE;
+
+ /* Reset bitstream1 buffer parameters */
+ BitstreamEncReset(encData->bitstream1);
+
+ return PV_TRUE;
+}
+
+/* ======================================================================== */
+/* Function : PVGetOverrunBuffer() */
+/* Purpose : Get the overrun buffer ` */
+/* In/out : */
+/* Return : Pointer to overrun buffer. */
+/* Modified : */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF UChar* PVGetOverrunBuffer(VideoEncControls *encCtrl)
+{
+ VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+ Int currLayer = video->currLayer;
+ Vol *currVol = video->vol[currLayer];
+
+ if (currVol->stream->bitstreamBuffer != video->overrunBuffer) // not used
+ {
+ return NULL;
+ }
+
+ return video->overrunBuffer;
+}
+
+
+
+
+/* ======================================================================== */
+/* Function : EncodeVideoFrame() */
+/* Date : 08/22/2000 */
+/* Purpose : Encode video frame and return bitstream */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* 02.14.2001 */
+/* Finishing new timestamp 32-bit input */
+/* Applications need to take care of wrap-around */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVEncodeVideoFrame(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, VideoEncFrameIO *vid_out,
+ ULong *nextModTime, UChar *bstream, Int *size, Int *nLayer)
+{
+ Bool status = PV_TRUE;
+ PV_STATUS pv_status;
+ VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+ VideoEncParams *encParams = video->encParams;
+ Vol *currVol;
+ Vop *tempForwRefVop = NULL;
+ Int tempRefSelCode = 0;
+ PV_STATUS EncodeVOS_Start(VideoEncControls *encCtrl);
+ Int width_16, height_16;
+ Int width, height;
+ Vop *temp;
+ Int encodeVop = 0;
+ void PaddingEdge(Vop *padVop);
+ Int currLayer = -1;
+ //Int nLayers = encParams->nLayers;
+
+ ULong modTime = vid_in->timestamp;
+
+#ifdef RANDOM_REFSELCODE /* add random selection of reference Vop */
+ Int random_val[30] = {0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0};
+ static Int rand_idx = 0;
+#endif
+
+ /*******************************************************/
+ /* Determine Next Vop to encode, if any, and nLayer */
+ /*******************************************************/
+ //i = nLayers-1;
+
+ if (video->volInitialize[0]) /* first vol to code */
+ {
+ video->nextModTime = video->modTimeRef = ((modTime) - ((modTime) % 1000));
+ }
+
+ encodeVop = DetermineCodingLayer(video, nLayer, modTime);
+ currLayer = *nLayer;
+ if ((currLayer < 0) || (currLayer > encParams->nLayers - 1))
+ return PV_FALSE;
+
+ /******************************************/
+ /* If post-skipping still effective --- return */
+ /******************************************/
+
+ if (!encodeVop) /* skip enh layer, no base layer coded --- return */
+ {
+#ifdef _PRINT_STAT
+ printf("No frame coded. Continue to next frame.");
+#endif
+ /* expected next code time, convert back to millisec */
+ *nextModTime = video->nextModTime;
+
+#ifdef ALLOW_VOP_NOT_CODED
+ if (video->vol[0]->shortVideoHeader) /* Short Video Header = 1 */
+ {
+ *size = 0;
+ *nLayer = -1;
+ }
+ else
+ {
+ *nLayer = 0;
+ EncodeVopNotCoded(video, bstream, size, modTime);
+ *size = video->vol[0]->stream->byteCount;
+ }
+#else
+ *size = 0;
+ *nLayer = -1;
+#endif
+ return status;
+ }
+
+
+//ENCODE_VOP_AGAIN: /* 12/30/00 */
+
+ /**************************************************************/
+ /* Initialize Vol stream structure with application bitstream */
+ /**************************************************************/
+
+ currVol = video->vol[currLayer];
+ currVol->stream->bitstreamBuffer = bstream;
+ currVol->stream->bufferSize = *size;
+ BitstreamEncReset(currVol->stream);
+ BitstreamSetOverrunBuffer(currVol->stream, video->overrunBuffer, video->oBSize, video);
+
+ /***********************************************************/
+ /* Encode VOS and VOL Headers on first call for each layer */
+ /***********************************************************/
+
+ if (video->volInitialize[currLayer])
+ {
+ video->currVop->timeInc = 0;
+ video->prevBaseVop->timeInc = 0;
+ if (!video->encParams->GetVolHeader[currLayer])
+ pv_status = EncodeVOS_Start(encCtrl);
+ }
+
+ /***************************************************/
+ /* Copy Input Video Frame to Internal Video Buffer */
+ /***************************************************/
+ /* Determine Width and Height of Vop Layer */
+
+ width = encParams->LayerWidth[currLayer]; /* Get input width */
+ height = encParams->LayerHeight[currLayer]; /* Get input height */
+ /* Round Up to nearest multiple of 16 : MPEG-4 Standard */
+
+ width_16 = ((width + 15) / 16) * 16; /* Round up to nearest multiple of 16 */
+ height_16 = ((height + 15) / 16) * 16; /* Round up to nearest multiple of 16 */
+
+ video->input = vid_in; /* point to the frame input */
+
+ /*// End ////////////////////////////// */
+
+
+ /**************************************/
+ /* Determine VOP Type */
+ /* 6/2/2001, separate function */
+ /**************************************/
+ DetermineVopType(video, currLayer);
+
+ /****************************/
+ /* Initialize VOP */
+ /****************************/
+ video->currVop->volID = currVol->volID;
+ video->currVop->width = width_16;
+ video->currVop->height = height_16;
+ if (video->encParams->H263_Enabled) /* 11/28/05 */
+ {
+ video->currVop->pitch = width_16;
+ }
+ else
+ {
+ video->currVop->pitch = width_16 + 32;
+ }
+ video->currVop->timeInc = currVol->timeIncrement;
+ video->currVop->vopCoded = 1;
+ video->currVop->roundingType = 0;
+ video->currVop->intraDCVlcThr = encParams->IntraDCVlcThr;
+
+ if (currLayer == 0
+#ifdef RANDOM_REFSELCODE /* add random selection of reference Vop */
+ || random_val[rand_idx] || video->volInitialize[currLayer]
+#endif
+ )
+ {
+ tempForwRefVop = video->forwardRefVop; /* keep initial state */
+ if (tempForwRefVop != NULL) tempRefSelCode = tempForwRefVop->refSelectCode;
+
+ video->forwardRefVop = video->prevBaseVop;
+ video->forwardRefVop->refSelectCode = 1;
+ }
+#ifdef RANDOM_REFSELCODE
+ else
+ {
+ tempForwRefVop = video->forwardRefVop; /* keep initial state */
+ if (tempForwRefVop != NULL) tempRefSelCode = tempForwRefVop->refSelectCode;
+
+ video->forwardRefVop = video->prevEnhanceVop;
+ video->forwardRefVop->refSelectCode = 0;
+ }
+ rand_idx++;
+ rand_idx %= 30;
+#endif
+
+ video->currVop->refSelectCode = video->forwardRefVop->refSelectCode;
+ video->currVop->gobNumber = 0;
+ video->currVop->gobFrameID = video->currVop->predictionType;
+ video->currVop->temporalRef = (modTime * 30 / 1001) % 256;
+
+ video->currVop->temporalInterval = 0;
+
+ if (video->currVop->predictionType == I_VOP)
+ video->currVop->quantizer = encParams->InitQuantIvop[currLayer];
+ else
+ video->currVop->quantizer = encParams->InitQuantPvop[currLayer];
+
+
+ /****************/
+ /* Encode Vop */
+ /****************/
+ video->slice_coding = 0;
+
+ pv_status = EncodeVop(video);
+#ifdef _PRINT_STAT
+ if (video->currVop->predictionType == I_VOP)
+ printf(" I-VOP ");
+ else
+ printf(" P-VOP (ref.%d)", video->forwardRefVop->refSelectCode);
+#endif
+
+ /************************************/
+ /* Update Skip Next Frame */
+ /************************************/
+ *nLayer = UpdateSkipNextFrame(video, nextModTime, size, pv_status);
+ if (*nLayer == -1) /* skip current frame */
+ {
+ /* make sure that pointers are restored to the previous state */
+ if (currLayer == 0)
+ {
+ video->forwardRefVop = tempForwRefVop; /* For P-Vop base only */
+ video->forwardRefVop->refSelectCode = tempRefSelCode;
+ }
+
+ return status;
+ }
+
+ /* If I-VOP was encoded, reset IntraPeriod */
+ if ((currLayer == 0) && (encParams->IntraPeriod > 0) && (video->currVop->predictionType == I_VOP))
+ video->nextEncIVop = encParams->IntraPeriod;
+
+ /* Set HintTrack Information */
+ if (currLayer != -1)
+ {
+ if (currVol->prevModuloTimeBase)
+ video->hintTrackInfo.MTB = 1;
+ else
+ video->hintTrackInfo.MTB = 0;
+ video->hintTrackInfo.LayerID = (UChar)currVol->volID;
+ video->hintTrackInfo.CodeType = (UChar)video->currVop->predictionType;
+ video->hintTrackInfo.RefSelCode = (UChar)video->currVop->refSelectCode;
+ }
+
+ /************************************************/
+ /* Determine nLayer and timeInc for next encode */
+ /* 12/27/00 always go by the highest layer*/
+ /************************************************/
+
+ /**********************************************************/
+ /* Copy Reconstructed Buffer to Output Video Frame Buffer */
+ /**********************************************************/
+ vid_out->yChan = video->currVop->yChan;
+ vid_out->uChan = video->currVop->uChan;
+ vid_out->vChan = video->currVop->vChan;
+ if (video->encParams->H263_Enabled)
+ {
+ vid_out->height = video->currVop->height; /* padded height */
+ vid_out->pitch = video->currVop->width; /* padded width */
+ }
+ else
+ {
+ vid_out->height = video->currVop->height + 32; /* padded height */
+ vid_out->pitch = video->currVop->width + 32; /* padded width */
+ }
+ //video_out->timestamp = video->modTime;
+ vid_out->timestamp = (ULong)(((video->prevFrameNum[currLayer] * 1000) / encParams->LayerFrameRate[currLayer]) + video->modTimeRef + 0.5);
+
+ /*// End /////////////////////// */
+
+ /***********************************/
+ /* Update Ouput bstream byte count */
+ /***********************************/
+
+ *size = currVol->stream->byteCount;
+
+ /****************************************/
+ /* Swap Vop Pointers for Base Layer */
+ /****************************************/
+ if (currLayer == 0)
+ {
+ temp = video->prevBaseVop;
+ video->prevBaseVop = video->currVop;
+ video->prevBaseVop->padded = 0; /* not padded */
+ video->currVop = temp;
+ video->forwardRefVop = video->prevBaseVop; /* For P-Vop base only */
+ video->forwardRefVop->refSelectCode = 1;
+ }
+ else
+ {
+ temp = video->prevEnhanceVop;
+ video->prevEnhanceVop = video->currVop;
+ video->prevEnhanceVop->padded = 0; /* not padded */
+ video->currVop = temp;
+ video->forwardRefVop = video->prevEnhanceVop;
+ video->forwardRefVop->refSelectCode = 0;
+ }
+
+ /****************************************/
+ /* Modify the intialize flag at the end.*/
+ /****************************************/
+ if (video->volInitialize[currLayer])
+ video->volInitialize[currLayer] = 0;
+
+ return status;
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/* Function : PVEncodeFrameSet() */
+/* Date : 04/18/2000 */
+/* Purpose : Enter a video frame and perform front-end time check plus ME */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVEncodeFrameSet(VideoEncControls *encCtrl, VideoEncFrameIO *vid_in, ULong *nextModTime, Int *nLayer)
+{
+ Bool status = PV_TRUE;
+ VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+ VideoEncParams *encParams = video->encParams;
+ Vol *currVol;
+ PV_STATUS EncodeVOS_Start(VideoEncControls *encCtrl);
+ Int width_16, height_16;
+ Int width, height;
+ Int encodeVop = 0;
+ void PaddingEdge(Vop *padVop);
+ Int currLayer = -1;
+ //Int nLayers = encParams->nLayers;
+
+ ULong modTime = vid_in->timestamp;
+
+#ifdef RANDOM_REFSELCODE /* add random selection of reference Vop */
+ Int random_val[30] = {0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0};
+ static Int rand_idx = 0;
+#endif
+ /*******************************************************/
+ /* Determine Next Vop to encode, if any, and nLayer */
+ /*******************************************************/
+
+ video->modTime = modTime;
+
+ //i = nLayers-1;
+
+ if (video->volInitialize[0]) /* first vol to code */
+ {
+ video->nextModTime = video->modTimeRef = ((modTime) - ((modTime) % 1000));
+ }
+
+
+ encodeVop = DetermineCodingLayer(video, nLayer, modTime);
+
+ currLayer = *nLayer;
+
+ /******************************************/
+ /* If post-skipping still effective --- return */
+ /******************************************/
+
+ if (!encodeVop) /* skip enh layer, no base layer coded --- return */
+ {
+#ifdef _PRINT_STAT
+ printf("No frame coded. Continue to next frame.");
+#endif
+ *nLayer = -1;
+
+ /* expected next code time, convert back to millisec */
+ *nextModTime = video->nextModTime;;
+ return status;
+ }
+
+ /**************************************************************/
+ /* Initialize Vol stream structure with application bitstream */
+ /**************************************************************/
+
+ currVol = video->vol[currLayer];
+ currVol->stream->bufferSize = 0;
+ BitstreamEncReset(currVol->stream);
+
+ /***********************************************************/
+ /* Encode VOS and VOL Headers on first call for each layer */
+ /***********************************************************/
+
+ if (video->volInitialize[currLayer])
+ {
+ video->currVop->timeInc = 0;
+ video->prevBaseVop->timeInc = 0;
+ }
+
+ /***************************************************/
+ /* Copy Input Video Frame to Internal Video Buffer */
+ /***************************************************/
+ /* Determine Width and Height of Vop Layer */
+
+ width = encParams->LayerWidth[currLayer]; /* Get input width */
+ height = encParams->LayerHeight[currLayer]; /* Get input height */
+ /* Round Up to nearest multiple of 16 : MPEG-4 Standard */
+
+ width_16 = ((width + 15) / 16) * 16; /* Round up to nearest multiple of 16 */
+ height_16 = ((height + 15) / 16) * 16; /* Round up to nearest multiple of 16 */
+
+ video->input = vid_in; /* point to the frame input */
+
+ /*// End ////////////////////////////// */
+
+
+ /**************************************/
+ /* Determine VOP Type */
+ /* 6/2/2001, separate function */
+ /**************************************/
+ DetermineVopType(video, currLayer);
+
+ /****************************/
+ /* Initialize VOP */
+ /****************************/
+ video->currVop->volID = currVol->volID;
+ video->currVop->width = width_16;
+ video->currVop->height = height_16;
+ if (video->encParams->H263_Enabled) /* 11/28/05 */
+ {
+ video->currVop->pitch = width_16;
+ }
+ else
+ {
+ video->currVop->pitch = width_16 + 32;
+ }
+ video->currVop->timeInc = currVol->timeIncrement;
+ video->currVop->vopCoded = 1;
+ video->currVop->roundingType = 0;
+ video->currVop->intraDCVlcThr = encParams->IntraDCVlcThr;
+
+ if (currLayer == 0
+#ifdef RANDOM_REFSELCODE /* add random selection of reference Vop */
+ || random_val[rand_idx] || video->volInitialize[currLayer]
+#endif
+ )
+ {
+ video->tempForwRefVop = video->forwardRefVop; /* keep initial state */
+ if (video->tempForwRefVop != NULL) video->tempRefSelCode = video->tempForwRefVop->refSelectCode;
+
+ video->forwardRefVop = video->prevBaseVop;
+ video->forwardRefVop->refSelectCode = 1;
+ }
+#ifdef RANDOM_REFSELCODE
+ else
+ {
+ video->tempForwRefVop = video->forwardRefVop; /* keep initial state */
+ if (video->tempForwRefVop != NULL) video->tempRefSelCode = video->tempForwRefVop->refSelectCode;
+
+ video->forwardRefVop = video->prevEnhanceVop;
+ video->forwardRefVop->refSelectCode = 0;
+ }
+ rand_idx++;
+ rand_idx %= 30;
+#endif
+
+ video->currVop->refSelectCode = video->forwardRefVop->refSelectCode;
+ video->currVop->gobNumber = 0;
+ video->currVop->gobFrameID = video->currVop->predictionType;
+ video->currVop->temporalRef = ((modTime) * 30 / 1001) % 256;
+
+ video->currVop->temporalInterval = 0;
+
+ if (video->currVop->predictionType == I_VOP)
+ video->currVop->quantizer = encParams->InitQuantIvop[currLayer];
+ else
+ video->currVop->quantizer = encParams->InitQuantPvop[currLayer];
+
+ /****************/
+ /* Encode Vop */
+ /****************/
+ video->slice_coding = 1;
+
+ /*pv_status =*/
+ EncodeVop(video);
+
+#ifdef _PRINT_STAT
+ if (video->currVop->predictionType == I_VOP)
+ printf(" I-VOP ");
+ else
+ printf(" P-VOP (ref.%d)", video->forwardRefVop->refSelectCode);
+#endif
+
+ /* Set HintTrack Information */
+ if (currVol->prevModuloTimeBase)
+ video->hintTrackInfo.MTB = 1;
+ else
+ video->hintTrackInfo.MTB = 0;
+
+ video->hintTrackInfo.LayerID = (UChar)currVol->volID;
+ video->hintTrackInfo.CodeType = (UChar)video->currVop->predictionType;
+ video->hintTrackInfo.RefSelCode = (UChar)video->currVop->refSelectCode;
+
+ return status;
+}
+#endif /* NO_SLICE_ENCODE */
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/* Function : PVEncodePacket() */
+/* Date : 04/18/2002 */
+/* Purpose : Encode one packet and return bitstream */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVEncodeSlice(VideoEncControls *encCtrl, UChar *bstream, Int *size,
+ Int *endofFrame, VideoEncFrameIO *vid_out, ULong *nextModTime)
+{
+ PV_STATUS pv_status;
+ VideoEncData *video = (VideoEncData *)encCtrl->videoEncoderData;
+ VideoEncParams *encParams = video->encParams;
+ Vol *currVol;
+ PV_STATUS EncodeVOS_Start(VideoEncControls *encCtrl);
+ Vop *temp;
+ void PaddingEdge(Vop *padVop);
+ Int currLayer = video->currLayer;
+ Int pre_skip;
+ Int pre_size;
+ /**************************************************************/
+ /* Initialize Vol stream structure with application bitstream */
+ /**************************************************************/
+
+ currVol = video->vol[currLayer];
+ currVol->stream->bitstreamBuffer = bstream;
+ pre_size = currVol->stream->byteCount;
+ currVol->stream->bufferSize = pre_size + (*size);
+
+ /***********************************************************/
+ /* Encode VOS and VOL Headers on first call for each layer */
+ /***********************************************************/
+
+ if (video->volInitialize[currLayer])
+ {
+ if (!video->encParams->GetVolHeader[currLayer])
+ pv_status = EncodeVOS_Start(encCtrl);
+ }
+
+ /****************/
+ /* Encode Slice */
+ /****************/
+ pv_status = EncodeSlice(video);
+
+ *endofFrame = 0;
+
+ if (video->mbnum >= currVol->nTotalMB && !video->end_of_buf)
+ {
+ *endofFrame = 1;
+
+ /************************************/
+ /* Update Skip Next Frame */
+ /************************************/
+ pre_skip = UpdateSkipNextFrame(video, nextModTime, size, pv_status); /* modified such that no pre-skipped */
+
+ if (pre_skip == -1) /* error */
+ {
+ *endofFrame = -1;
+ /* make sure that pointers are restored to the previous state */
+ if (currLayer == 0)
+ {
+ video->forwardRefVop = video->tempForwRefVop; /* For P-Vop base only */
+ video->forwardRefVop->refSelectCode = video->tempRefSelCode;
+ }
+
+ return pv_status;
+ }
+
+ /* If I-VOP was encoded, reset IntraPeriod */
+ if ((currLayer == 0) && (encParams->IntraPeriod > 0) && (video->currVop->predictionType == I_VOP))
+ video->nextEncIVop = encParams->IntraPeriod;
+
+ /**********************************************************/
+ /* Copy Reconstructed Buffer to Output Video Frame Buffer */
+ /**********************************************************/
+ vid_out->yChan = video->currVop->yChan;
+ vid_out->uChan = video->currVop->uChan;
+ vid_out->vChan = video->currVop->vChan;
+ if (video->encParams->H263_Enabled)
+ {
+ vid_out->height = video->currVop->height; /* padded height */
+ vid_out->pitch = video->currVop->width; /* padded width */
+ }
+ else
+ {
+ vid_out->height = video->currVop->height + 32; /* padded height */
+ vid_out->pitch = video->currVop->width + 32; /* padded width */
+ }
+ //vid_out->timestamp = video->modTime;
+ vid_out->timestamp = (ULong)(((video->prevFrameNum[currLayer] * 1000) / encParams->LayerFrameRate[currLayer]) + video->modTimeRef + 0.5);
+
+ /*// End /////////////////////// */
+
+ /****************************************/
+ /* Swap Vop Pointers for Base Layer */
+ /****************************************/
+
+ if (currLayer == 0)
+ {
+ temp = video->prevBaseVop;
+ video->prevBaseVop = video->currVop;
+ video->prevBaseVop->padded = 0; /* not padded */
+ video->currVop = temp;
+ video->forwardRefVop = video->prevBaseVop; /* For P-Vop base only */
+ video->forwardRefVop->refSelectCode = 1;
+ }
+ else
+ {
+ temp = video->prevEnhanceVop;
+ video->prevEnhanceVop = video->currVop;
+ video->prevEnhanceVop->padded = 0; /* not padded */
+ video->currVop = temp;
+ video->forwardRefVop = video->prevEnhanceVop;
+ video->forwardRefVop->refSelectCode = 0;
+ }
+ }
+
+ /***********************************/
+ /* Update Ouput bstream byte count */
+ /***********************************/
+
+ *size = currVol->stream->byteCount - pre_size;
+
+ /****************************************/
+ /* Modify the intialize flag at the end.*/
+ /****************************************/
+ if (video->volInitialize[currLayer])
+ video->volInitialize[currLayer] = 0;
+
+ return pv_status;
+}
+#endif /* NO_SLICE_ENCODE */
+
+
+/* ======================================================================== */
+/* Function : PVGetH263ProfileLevelID() */
+/* Date : 02/05/2003 */
+/* Purpose : Get H.263 Profile ID and level ID for profile 0 */
+/* In/out : Profile ID=0, levelID is what we want */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* Note : h263Level[8], rBR_bound[8], max_h263_framerate[2] */
+/* max_h263_width[2], max_h263_height[2] are global */
+/* */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVGetH263ProfileLevelID(VideoEncControls *encCtrl, Int *profileID, Int *levelID)
+{
+ VideoEncData *encData;
+ Int width, height;
+ float bitrate_r, framerate;
+
+
+ /* For this version, we only support H.263 profile 0 */
+ *profileID = 0;
+
+ *levelID = 0;
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ if (!encData->encParams->H263_Enabled) return PV_FALSE;
+
+
+ /* get image width, height, bitrate and framerate */
+ width = encData->encParams->LayerWidth[0];
+ height = encData->encParams->LayerHeight[0];
+ bitrate_r = (float)(encData->encParams->LayerBitRate[0]) / (float)64000.0;
+ framerate = encData->encParams->LayerFrameRate[0];
+ if (!width || !height || !(bitrate_r > 0 && framerate > 0)) return PV_FALSE;
+
+ /* This is the most frequent case : level 10 */
+ if (bitrate_r <= rBR_bound[1] && framerate <= max_h263_framerate[0] &&
+ (width <= max_h263_width[0] && height <= max_h263_height[0]))
+ {
+ *levelID = h263Level[1];
+ return PV_TRUE;
+ }
+ else if (bitrate_r > rBR_bound[4] ||
+ (width > max_h263_width[1] || height > max_h263_height[1]) ||
+ framerate > max_h263_framerate[1]) /* check the highest level 70 */
+ {
+ *levelID = h263Level[7];
+ return PV_TRUE;
+ }
+ else /* search level 20, 30, 40 */
+ {
+
+ /* pick out level 20 */
+ if (bitrate_r <= rBR_bound[2] &&
+ ((width <= max_h263_width[0] && height <= max_h263_height[0] && framerate <= max_h263_framerate[1]) ||
+ (width <= max_h263_width[1] && height <= max_h263_height[1] && framerate <= max_h263_framerate[0])))
+ {
+ *levelID = h263Level[2];
+ return PV_TRUE;
+ }
+ else /* width, height and framerate are ok, now choose level 30 or 40 */
+ {
+ *levelID = (bitrate_r <= rBR_bound[3] ? h263Level[3] : h263Level[4]);
+ return PV_TRUE;
+ }
+ }
+}
+
+/* ======================================================================== */
+/* Function : PVGetMPEG4ProfileLevelID() */
+/* Date : 26/06/2008 */
+/* Purpose : Get MPEG4 Level after initialized */
+/* In/out : profile_level according to interface */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVGetMPEG4ProfileLevelID(VideoEncControls *encCtrl, Int *profile_level, Int nLayer)
+{
+ VideoEncData* video;
+ Int i;
+
+ video = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (nLayer == 0)
+ {
+ for (i = 0; i < 8; i++)
+ {
+ if (video->encParams->ProfileLevel[0] == profile_level_code[i])
+ {
+ break;
+ }
+ }
+ *profile_level = i;
+ }
+ else
+ {
+ for (i = 0; i < 8; i++)
+ {
+ if (video->encParams->ProfileLevel[0] == scalable_profile_level_code[i])
+ {
+ break;
+ }
+ }
+ *profile_level = i + SIMPLE_SCALABLE_PROFILE_LEVEL0;
+ }
+
+ return true;
+}
+
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVUpdateEncFrameRate */
+/* Date : 04/08/2002 */
+/* Purpose : Update target frame rates of the encoded base and enhance */
+/* layer(if any) while encoding operation is ongoing */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVUpdateEncFrameRate(VideoEncControls *encCtrl, float *frameRate)
+{
+ VideoEncData *encData;
+ Int i;// nTotalMB, mbPerSec;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ /* Update the framerates for all the layers */
+ for (i = 0; i < encData->encParams->nLayers; i++)
+ {
+
+ /* New check: encoding framerate should be consistent with the given profile and level */
+ //nTotalMB = (((encData->encParams->LayerWidth[i]+15)/16)*16)*(((encData->encParams->LayerHeight[i]+15)/16)*16)/(16*16);
+ //mbPerSec = (Int)(nTotalMB * frameRate[i]);
+ //if(mbPerSec > encData->encParams->LayerMaxMbsPerSec[i]) return PV_FALSE;
+ if (frameRate[i] > encData->encParams->LayerMaxFrameRate[i]) return PV_FALSE; /* set by users or profile */
+
+ encData->encParams->LayerFrameRate[i] = frameRate[i];
+ }
+
+ return RC_UpdateBXRCParams((void*) encData);
+
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVUpdateBitRate */
+/* Date : 04/08/2002 */
+/* Purpose : Update target bit rates of the encoded base and enhance */
+/* layer(if any) while encoding operation is ongoing */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVUpdateBitRate(VideoEncControls *encCtrl, Int *bitRate)
+{
+ VideoEncData *encData;
+ Int i;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ /* Update the bitrates for all the layers */
+ for (i = 0; i < encData->encParams->nLayers; i++)
+ {
+ if (bitRate[i] > encData->encParams->LayerMaxBitRate[i]) /* set by users or profile */
+ {
+ return PV_FALSE;
+ }
+ encData->encParams->LayerBitRate[i] = bitRate[i];
+ }
+
+ return RC_UpdateBXRCParams((void*) encData);
+
+}
+#endif
+#ifndef LIMITED_API
+/* ============================================================================ */
+/* Function : PVUpdateVBVDelay() */
+/* Date : 4/23/2004 */
+/* Purpose : Update VBV buffer size(in delay) */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ============================================================================ */
+
+Bool PVUpdateVBVDelay(VideoEncControls *encCtrl, float delay)
+{
+
+ VideoEncData *encData;
+ Int total_bitrate, max_buffer_size;
+ int index;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ /* Check whether the input delay is valid based on the given profile */
+ total_bitrate = (encData->encParams->nLayers == 1 ? encData->encParams->LayerBitRate[0] :
+ encData->encParams->LayerBitRate[1]);
+ index = encData->encParams->profile_table_index;
+ max_buffer_size = (encData->encParams->nLayers == 1 ? profile_level_max_VBV_size[index] :
+ scalable_profile_level_max_VBV_size[index]);
+
+ if (total_bitrate*delay > (float)max_buffer_size)
+ return PV_FALSE;
+
+ encData->encParams->VBV_delay = delay;
+ return PV_TRUE;
+
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVUpdateIFrameInterval() */
+/* Date : 04/10/2002 */
+/* Purpose : updates the INTRA frame refresh interval while encoding */
+/* is ongoing */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVUpdateIFrameInterval(VideoEncControls *encCtrl, Int aIFramePeriod)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ encData->encParams->IntraPeriod = aIFramePeriod;
+ return PV_TRUE;
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVSetNumIntraMBRefresh() */
+/* Date : 08/05/2003 */
+/* Purpose : */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+OSCL_EXPORT_REF Bool PVUpdateNumIntraMBRefresh(VideoEncControls *encCtrl, Int numMB)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+
+ encData->encParams->Refresh = numMB;
+
+ return PV_TRUE;
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVIFrameRequest() */
+/* Date : 04/10/2002 */
+/* Purpose : encodes the next base frame as an I-Vop */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVIFrameRequest(VideoEncControls *encCtrl)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ encData->nextEncIVop = 1;
+ return PV_TRUE;
+}
+#endif
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVGetEncMemoryUsage() */
+/* Date : 10/17/2000 */
+/* Purpose : */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Int PVGetEncMemoryUsage(VideoEncControls *encCtrl)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+ return encData->encParams->MemoryUsage;
+}
+#endif
+
+/* ======================================================================== */
+/* Function : PVGetHintTrack() */
+/* Date : 1/17/2001, */
+/* Purpose : */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetHintTrack(VideoEncControls *encCtrl, MP4HintTrack *info)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+ info->MTB = encData->hintTrackInfo.MTB;
+ info->LayerID = encData->hintTrackInfo.LayerID;
+ info->CodeType = encData->hintTrackInfo.CodeType;
+ info->RefSelCode = encData->hintTrackInfo.RefSelCode;
+
+ return PV_TRUE;
+}
+
+/* ======================================================================== */
+/* Function : PVGetMaxVideoFrameSize() */
+/* Date : 7/17/2001, */
+/* Purpose : Function merely returns the maximum buffer size */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetMaxVideoFrameSize(VideoEncControls *encCtrl, Int *maxVideoFrameSize)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+
+
+ *maxVideoFrameSize = encData->encParams->BufferSize[0];
+
+ if (encData->encParams->nLayers == 2)
+ if (*maxVideoFrameSize < encData->encParams->BufferSize[1])
+ *maxVideoFrameSize = encData->encParams->BufferSize[1];
+ *maxVideoFrameSize >>= 3; /* Convert to Bytes */
+
+ if (*maxVideoFrameSize <= 4000)
+ *maxVideoFrameSize = 4000;
+
+ return PV_TRUE;
+}
+#ifndef LIMITED_API
+/* ======================================================================== */
+/* Function : PVGetVBVSize() */
+/* Date : 4/15/2002 */
+/* Purpose : Function merely returns the maximum buffer size */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+OSCL_EXPORT_REF Bool PVGetVBVSize(VideoEncControls *encCtrl, Int *VBVSize)
+{
+ VideoEncData *encData;
+
+ encData = (VideoEncData *)encCtrl->videoEncoderData;
+
+ if (encData == NULL)
+ return PV_FALSE;
+ if (encData->encParams == NULL)
+ return PV_FALSE;
+
+ *VBVSize = encData->encParams->BufferSize[0];
+ if (encData->encParams->nLayers == 2)
+ *VBVSize += encData->encParams->BufferSize[1];
+
+ return PV_TRUE;
+
+}
+#endif
+/* ======================================================================== */
+/* Function : EncodeVOS_Start() */
+/* Date : 08/22/2000 */
+/* Purpose : Encodes the VOS,VO, and VOL or Short Headers */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+PV_STATUS EncodeVOS_Start(VideoEncControls *encoderControl)
+{
+
+ VideoEncData *video = (VideoEncData *)encoderControl->videoEncoderData;
+ Vol *currVol = video->vol[video->currLayer];
+ PV_STATUS status = PV_SUCCESS;
+ //int profile_level=0x01;
+ BitstreamEncVideo *stream = video->bitstream1;
+ int i, j;
+
+ /********************************/
+ /* Check for short_video_header */
+ /********************************/
+ if (currVol->shortVideoHeader == 1)
+ return status;
+ else
+ {
+ /* Short Video Header or M4V */
+
+ /**************************/
+ /* VisualObjectSequence ()*/
+ /**************************/
+ status = BitstreamPutGT16Bits(stream, 32, SESSION_START_CODE);
+ /* Determine profile_level */
+ status = BitstreamPutBits(stream, 8, video->encParams->ProfileLevel[video->currLayer]);
+
+ /******************/
+ /* VisualObject() */
+ /******************/
+
+ status = BitstreamPutGT16Bits(stream, 32, VISUAL_OBJECT_START_CODE);
+ status = BitstreamPut1Bits(stream, 0x00); /* visual object identifier */
+ status = BitstreamPutBits(stream, 4, 0x01); /* visual object Type == "video ID" */
+ status = BitstreamPut1Bits(stream, 0x00); /* no video signal type */
+
+ /*temp = */
+ BitstreamMpeg4ByteAlignStuffing(stream);
+
+
+ status = BitstreamPutGT16Bits(stream, 27, VO_START_CODE);/* byte align: should be 2 bits */
+ status = BitstreamPutBits(stream, 5, 0x00);/* Video ID = 0 */
+
+
+
+ /**********************/
+ /* VideoObjectLayer() */
+ /**********************/
+ if (currVol->shortVideoHeader == 0)
+ { /* M4V else Short Video Header */
+ status = BitstreamPutGT16Bits(stream, VOL_START_CODE_LENGTH, VOL_START_CODE);
+ status = BitstreamPutBits(stream, 4, currVol->volID);/* video_object_layer_id */
+ status = BitstreamPut1Bits(stream, 0x00);/* Random Access = 0 */
+
+ if (video->currLayer == 0)
+ status = BitstreamPutBits(stream, 8, 0x01);/* Video Object Type Indication = 1 ... Simple Object Type */
+ else
+ status = BitstreamPutBits(stream, 8, 0x02);/* Video Object Type Indication = 2 ... Simple Scalable Object Type */
+
+ status = BitstreamPut1Bits(stream, 0x00);/* is_object_layer_identifer = 0 */
+
+
+ status = BitstreamPutBits(stream, 4, 0x01); /* aspect_ratio_info = 1 ... 1:1(Square) */
+ status = BitstreamPut1Bits(stream, 0x00);/* vol_control_parameters = 0 */
+ status = BitstreamPutBits(stream, 2, 0x00);/* video_object_layer_shape = 00 ... rectangular */
+ status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+ status = BitstreamPutGT8Bits(stream, 16, currVol->timeIncrementResolution);/* vop_time_increment_resolution */
+ status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+ status = BitstreamPut1Bits(stream, currVol->fixedVopRate);/* fixed_vop_rate = 0 */
+
+ /* For Rectangular VO layer shape */
+ status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+ status = BitstreamPutGT8Bits(stream, 13, currVol->width);/* video_object_layer_width */
+ status = BitstreamPut1Bits(stream, 0x01);/* marker bit */
+ status = BitstreamPutGT8Bits(stream, 13, currVol->height);/* video_object_layer_height */
+ status = BitstreamPut1Bits(stream, 0x01);/*marker bit */
+
+ status = BitstreamPut1Bits(stream, 0x00);/*interlaced = 0 */
+ status = BitstreamPut1Bits(stream, 0x01);/* obmc_disable = 1 */
+ status = BitstreamPut1Bits(stream, 0x00);/* sprite_enable = 0 */
+ status = BitstreamPut1Bits(stream, 0x00);/* not_8_bit = 0 */
+ status = BitstreamPut1Bits(stream, currVol->quantType);/* quant_type */
+
+ if (currVol->quantType)
+ {
+ status = BitstreamPut1Bits(stream, currVol->loadIntraQuantMat); /* Intra quant matrix */
+ if (currVol->loadIntraQuantMat)
+ {
+ for (j = 63; j >= 1; j--)
+ if (currVol->iqmat[*(zigzag_i+j)] != currVol->iqmat[*(zigzag_i+j-1)])
+ break;
+ if ((j == 1) && (currVol->iqmat[*(zigzag_i+j)] == currVol->iqmat[*(zigzag_i+j-1)]))
+ j = 0;
+ for (i = 0; i < j + 1; i++)
+ BitstreamPutBits(stream, 8, currVol->iqmat[*(zigzag_i+i)]);
+ if (j < 63)
+ BitstreamPutBits(stream, 8, 0);
+ }
+ else
+ {
+ for (j = 0; j < 64; j++)
+ currVol->iqmat[j] = mpeg_iqmat_def[j];
+
+ }
+ status = BitstreamPut1Bits(stream, currVol->loadNonIntraQuantMat); /* Non-Intra quant matrix */
+ if (currVol->loadNonIntraQuantMat)
+ {
+ for (j = 63; j >= 1; j--)
+ if (currVol->niqmat[*(zigzag_i+j)] != currVol->niqmat[*(zigzag_i+j-1)])
+ break;
+ if ((j == 1) && (currVol->niqmat[*(zigzag_i+j)] == currVol->niqmat[*(zigzag_i+j-1)]))
+ j = 0;
+ for (i = 0; i < j + 1; i++)
+ BitstreamPutBits(stream, 8, currVol->niqmat[*(zigzag_i+i)]);
+ if (j < 63)
+ BitstreamPutBits(stream, 8, 0);
+ }
+ else
+ {
+ for (j = 0; j < 64; j++)
+ currVol->niqmat[j] = mpeg_nqmat_def[j];
+ }
+ }
+
+ status = BitstreamPut1Bits(stream, 0x01); /* complexity_estimation_disable = 1 */
+ status = BitstreamPut1Bits(stream, currVol->ResyncMarkerDisable);/* Resync_marker_disable */
+ status = BitstreamPut1Bits(stream, currVol->dataPartitioning);/* Data partitioned */
+
+ if (currVol->dataPartitioning)
+ status = BitstreamPut1Bits(stream, currVol->useReverseVLC); /* Reversible_vlc */
+
+
+ if (currVol->scalability) /* Scalability*/
+ {
+
+ status = BitstreamPut1Bits(stream, currVol->scalability);/* Scalability = 1 */
+ status = BitstreamPut1Bits(stream, currVol->scalType);/* hierarchy _type ... Spatial= 0 and Temporal = 1 */
+ status = BitstreamPutBits(stream, 4, currVol->refVolID);/* ref_layer_id */
+ status = BitstreamPut1Bits(stream, currVol->refSampDir);/* ref_layer_sampling_direc*/
+ status = BitstreamPutBits(stream, 5, currVol->horSamp_n);/*hor_sampling_factor_n*/
+ status = BitstreamPutBits(stream, 5, currVol->horSamp_m);/*hor_sampling_factor_m*/
+ status = BitstreamPutBits(stream, 5, currVol->verSamp_n);/*vert_sampling_factor_n*/
+ status = BitstreamPutBits(stream, 5, currVol->verSamp_m);/*vert_sampling_factor_m*/
+ status = BitstreamPut1Bits(stream, currVol->enhancementType);/* enhancement_type*/
+ }
+ else /* No Scalability */
+ status = BitstreamPut1Bits(stream, currVol->scalability);/* Scalability = 0 */
+
+ /*temp = */
+ BitstreamMpeg4ByteAlignStuffing(stream); /* Byte align Headers for VOP */
+ }
+ }
+
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : VOS_End() */
+/* Date : 08/22/2000 */
+/* Purpose : Visual Object Sequence End */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+PV_STATUS VOS_End(VideoEncControls *encoderControl)
+{
+ PV_STATUS status = PV_SUCCESS;
+ VideoEncData *video = (VideoEncData *)encoderControl->videoEncoderData;
+ Vol *currVol = video->vol[video->currLayer];
+ BitstreamEncVideo *stream = currVol->stream;
+
+
+ status = BitstreamPutBits(stream, SESSION_END_CODE, 32);
+
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : DetermineCodingLayer */
+/* Date : 06/02/2001 */
+/* Purpose : Find layer to code based on current mod time, assuming that
+ it's time to encode enhanced layer. */
+/* In/out : */
+/* Return : Number of layer to code. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+Int DetermineCodingLayer(VideoEncData *video, Int *nLayer, ULong modTime)
+{
+ Vol **vol = video->vol;
+ VideoEncParams *encParams = video->encParams;
+ Int numLayers = encParams->nLayers;
+ UInt modTimeRef = video->modTimeRef;
+ float *LayerFrameRate = encParams->LayerFrameRate;
+ UInt frameNum[4], frameTick;
+ ULong frameModTime, nextFrmModTime;
+#ifdef REDUCE_FRAME_VARIANCE /* To limit how close 2 frames can be */
+ float frameInterval;
+#endif
+ float srcFrameInterval;
+ Int frameInc;
+ Int i, extra_skip;
+ Int encodeVop = 0;
+
+ i = numLayers - 1;
+
+ if (modTime - video->nextModTime > ((ULong)(-1)) >> 1) /* next time wrapped around */
+ return 0; /* not time to code it yet */
+
+ video->relLayerCodeTime[i] -= 1000;
+ video->nextEncIVop--; /* number of Vops in highest layer resolution. */
+ video->numVopsInGOP++;
+
+ /* from this point frameModTime and nextFrmModTime are internal */
+
+ frameNum[i] = (UInt)((modTime - modTimeRef) * LayerFrameRate[i] + 500) / 1000;
+ if (video->volInitialize[i])
+ {
+ video->prevFrameNum[i] = frameNum[i] - 1;
+ }
+ else if (frameNum[i] <= video->prevFrameNum[i])
+ {
+ return 0; /* do not encode this frame */
+ }
+
+ /**** this part computes expected next frame *******/
+ frameModTime = (ULong)(((frameNum[i] * 1000) / LayerFrameRate[i]) + modTimeRef + 0.5); /* rec. time */
+ nextFrmModTime = (ULong)((((frameNum[i] + 1) * 1000) / LayerFrameRate[i]) + modTimeRef + 0.5); /* rec. time */
+
+ srcFrameInterval = 1000 / video->FrameRate;
+
+ video->nextModTime = nextFrmModTime - (ULong)(srcFrameInterval / 2.) - 1; /* between current and next frame */
+
+#ifdef REDUCE_FRAME_VARIANCE /* To limit how close 2 frames can be */
+ frameInterval = 1000 / LayerFrameRate[i]; /* next rec. time */
+ delta = (Int)(frameInterval / 4); /* empirical number */
+ if (video->nextModTime - modTime < (ULong)delta) /* need to move nextModTime further. */
+ {
+ video->nextModTime += ((delta - video->nextModTime + modTime)); /* empirical formula */
+ }
+#endif
+ /****************************************************/
+
+ /* map frame no.to tick from modTimeRef */
+ /*frameTick = (frameNum[i]*vol[i]->timeIncrementResolution) ;
+ frameTick = (UInt)((frameTick + (encParams->LayerFrameRate[i]/2))/encParams->LayerFrameRate[i]);*/
+ /* 11/16/01, change frameTick to be the closest tick from the actual modTime */
+ /* 12/12/02, add (double) to prevent large number wrap-around */
+ frameTick = (Int)(((double)(modTime - modTimeRef) * vol[i]->timeIncrementResolution + 500) / 1000);
+
+ /* find timeIncrement to be put in the bitstream */
+ /* refTick is second boundary reference. */
+ vol[i]->timeIncrement = frameTick - video->refTick[i];
+
+
+ vol[i]->moduloTimeBase = 0;
+ while (vol[i]->timeIncrement >= vol[i]->timeIncrementResolution)
+ {
+ vol[i]->timeIncrement -= vol[i]->timeIncrementResolution;
+ vol[i]->moduloTimeBase++;
+ /* do not update refTick and modTimeRef yet, do it after encoding!! */
+ }
+
+ if (video->relLayerCodeTime[i] <= 0) /* no skipping */
+ {
+ encodeVop = 1;
+ video->currLayer = *nLayer = i;
+ video->relLayerCodeTime[i] += 1000;
+
+ /* takes care of more dropped frame than expected */
+ extra_skip = -1;
+ frameInc = (frameNum[i] - video->prevFrameNum[i]);
+ extra_skip += frameInc;
+
+ if (extra_skip > 0)
+ { /* update rc->Nr, rc->B, (rc->Rr)*/
+ video->nextEncIVop -= extra_skip;
+ video->numVopsInGOP += extra_skip;
+ if (encParams->RC_Type != CONSTANT_Q)
+ {
+ RC_UpdateBuffer(video, i, extra_skip);
+ }
+ }
+
+ }
+ /* update frame no. */
+ video->prevFrameNum[i] = frameNum[i];
+
+ /* go through all lower layer */
+ for (i = (numLayers - 2); i >= 0; i--)
+ {
+
+ video->relLayerCodeTime[i] -= 1000;
+
+ /* find timeIncrement to be put in the bitstream */
+ vol[i]->timeIncrement = frameTick - video->refTick[i];
+
+ if (video->relLayerCodeTime[i] <= 0) /* time to encode base */
+ {
+ /* 12/27/00 */
+ encodeVop = 1;
+ video->currLayer = *nLayer = i;
+ video->relLayerCodeTime[i] +=
+ (Int)((1000.0 * encParams->LayerFrameRate[numLayers-1]) / encParams->LayerFrameRate[i]);
+
+ vol[i]->moduloTimeBase = 0;
+ while (vol[i]->timeIncrement >= vol[i]->timeIncrementResolution)
+ {
+ vol[i]->timeIncrement -= vol[i]->timeIncrementResolution;
+ vol[i]->moduloTimeBase++;
+ /* do not update refTick and modTimeRef yet, do it after encoding!! */
+ }
+
+ /* takes care of more dropped frame than expected */
+ frameNum[i] = (UInt)((frameModTime - modTimeRef) * encParams->LayerFrameRate[i] + 500) / 1000;
+ if (video->volInitialize[i])
+ video->prevFrameNum[i] = frameNum[i] - 1;
+
+ extra_skip = -1;
+ frameInc = (frameNum[i] - video->prevFrameNum[i]);
+ extra_skip += frameInc;
+
+ if (extra_skip > 0)
+ { /* update rc->Nr, rc->B, (rc->Rr)*/
+ if (encParams->RC_Type != CONSTANT_Q)
+ {
+ RC_UpdateBuffer(video, i, extra_skip);
+ }
+ }
+ /* update frame no. */
+ video->prevFrameNum[i] = frameNum[i];
+ }
+ }
+
+#ifdef _PRINT_STAT
+ if (encodeVop)
+ printf(" TI: %d ", vol[*nLayer]->timeIncrement);
+#endif
+
+ return encodeVop;
+}
+
+/* ======================================================================== */
+/* Function : DetermineVopType */
+/* Date : 06/02/2001 */
+/* Purpose : The name says it all. */
+/* In/out : */
+/* Return : void . */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+void DetermineVopType(VideoEncData *video, Int currLayer)
+{
+ VideoEncParams *encParams = video->encParams;
+// Vol *currVol = video->vol[currLayer];
+
+ if (encParams->IntraPeriod == 0) /* I-VOPs only */
+ {
+ if (video->currLayer > 0)
+ video->currVop->predictionType = P_VOP;
+ else
+ {
+ video->currVop->predictionType = I_VOP;
+ if (video->numVopsInGOP >= 132)
+ video->numVopsInGOP = 0;
+ }
+ }
+ else if (encParams->IntraPeriod == -1) /* IPPPPP... */
+ {
+
+ /* maintain frame type if previous frame is pre-skipped, 06/02/2001 */
+ if (encParams->RC_Type == CONSTANT_Q || video->rc[currLayer]->skip_next_frame != -1)
+ video->currVop->predictionType = P_VOP;
+
+ if (video->currLayer == 0)
+ {
+ if (/*video->numVopsInGOP>=132 || */video->volInitialize[currLayer])
+ {
+ video->currVop->predictionType = I_VOP;
+ video->numVopsInGOP = 0; /* force INTRA update every 132 base frames*/
+ video->nextEncIVop = 1;
+ }
+ else if (video->nextEncIVop == 0 || video->currVop->predictionType == I_VOP)
+ {
+ video->numVopsInGOP = 0;
+ video->nextEncIVop = 1;
+ }
+ }
+ }
+ else /* IntraPeriod>0 : IPPPPPIPPPPPI... */
+ {
+
+ /* maintain frame type if previous frame is pre-skipped, 06/02/2001 */
+ if (encParams->RC_Type == CONSTANT_Q || video->rc[currLayer]->skip_next_frame != -1)
+ video->currVop->predictionType = P_VOP;
+
+ if (currLayer == 0)
+ {
+ if (video->nextEncIVop <= 0 || video->currVop->predictionType == I_VOP)
+ {
+ video->nextEncIVop = encParams->IntraPeriod;
+ video->currVop->predictionType = I_VOP;
+ video->numVopsInGOP = 0;
+ }
+ }
+ }
+
+ return ;
+}
+
+/* ======================================================================== */
+/* Function : UpdateSkipNextFrame */
+/* Date : 06/02/2001 */
+/* Purpose : From rate control frame skipping decision, update timing
+ related parameters. */
+/* In/out : */
+/* Return : Current coded layer. */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+Int UpdateSkipNextFrame(VideoEncData *video, ULong *modTime, Int *size, PV_STATUS status)
+{
+ Int currLayer = video->currLayer;
+ Int nLayer = currLayer;
+ VideoEncParams *encParams = video->encParams;
+ Int numLayers = encParams->nLayers;
+ Vol *currVol = video->vol[currLayer];
+ Vol **vol = video->vol;
+ Int num_skip, extra_skip;
+ Int i;
+ UInt newRefTick, deltaModTime;
+ UInt temp;
+
+ if (encParams->RC_Type != CONSTANT_Q)
+ {
+ if (video->volInitialize[0] && currLayer == 0) /* always encode the first frame */
+ {
+ RC_ResetSkipNextFrame(video, currLayer);
+ //return currLayer; 09/15/05
+ }
+ else
+ {
+ if (RC_GetSkipNextFrame(video, currLayer) < 0 || status == PV_END_OF_BUF) /* Skip Current Frame */
+ {
+
+#ifdef _PRINT_STAT
+ printf("Skip current frame");
+#endif
+ currVol->moduloTimeBase = currVol->prevModuloTimeBase;
+
+ /*********************/
+ /* prepare to return */
+ /*********************/
+ *size = 0; /* Set Bitstream buffer to zero */
+
+ /* Determine nLayer and modTime for next encode */
+
+ *modTime = video->nextModTime;
+ nLayer = -1;
+
+ return nLayer; /* return immediately without updating RefTick & modTimeRef */
+ /* If I-VOP was attempted, then ensure next base is I-VOP */
+ /*if((encParams->IntraPeriod>0) && (video->currVop->predictionType == I_VOP))
+ video->nextEncIVop = 0; commented out by 06/05/01 */
+
+ }
+ else if ((num_skip = RC_GetSkipNextFrame(video, currLayer)) > 0)
+ {
+
+#ifdef _PRINT_STAT
+ printf("Skip next %d frames", num_skip);
+#endif
+ /* to keep the Nr of enh layer the same */
+ /* adjust relLayerCodeTime only, do not adjust layerCodeTime[numLayers-1] */
+ extra_skip = 0;
+ for (i = 0; i < currLayer; i++)
+ {
+ if (video->relLayerCodeTime[i] <= 1000)
+ {
+ extra_skip = 1;
+ break;
+ }
+ }
+
+ for (i = currLayer; i < numLayers; i++)
+ {
+ video->relLayerCodeTime[i] += (num_skip + extra_skip) *
+ ((Int)((1000.0 * encParams->LayerFrameRate[numLayers-1]) / encParams->LayerFrameRate[i]));
+ }
+ }
+ }/* first frame */
+ }
+ /***** current frame is encoded, now update refTick ******/
+
+ video->refTick[currLayer] += vol[currLayer]->prevModuloTimeBase * vol[currLayer]->timeIncrementResolution;
+
+ /* Reset layerCodeTime every I-VOP to prevent overflow */
+ if (currLayer == 0)
+ {
+ /* 12/12/02, fix for weird targer frame rate of 9.99 fps or 3.33 fps */
+ if (((encParams->IntraPeriod != 0) /*&& (video->currVop->predictionType==I_VOP)*/) ||
+ ((encParams->IntraPeriod == 0) && (video->numVopsInGOP == 0)))
+ {
+ newRefTick = video->refTick[0];
+
+ for (i = 1; i < numLayers; i++)
+ {
+ if (video->refTick[i] < newRefTick)
+ newRefTick = video->refTick[i];
+ }
+
+ /* check to make sure that the update is integer multiple of frame number */
+ /* how many msec elapsed from last modTimeRef */
+ deltaModTime = (newRefTick / vol[0]->timeIncrementResolution) * 1000;
+
+ for (i = numLayers - 1; i >= 0; i--)
+ {
+ temp = (UInt)(deltaModTime * encParams->LayerFrameRate[i]); /* 12/12/02 */
+ if (temp % 1000)
+ newRefTick = 0;
+
+ }
+ if (newRefTick > 0)
+ {
+ video->modTimeRef += deltaModTime;
+ for (i = numLayers - 1; i >= 0; i--)
+ {
+ video->prevFrameNum[i] -= (UInt)(deltaModTime * encParams->LayerFrameRate[i]) / 1000;
+ video->refTick[i] -= newRefTick;
+ }
+ }
+ }
+ }
+
+ *modTime = video->nextModTime;
+
+ return nLayer;
+}
+
+
+#ifndef ORIGINAL_VERSION
+
+/* ======================================================================== */
+/* Function : SetProfile_BufferSize */
+/* Date : 04/08/2002 */
+/* Purpose : Set profile and video buffer size, copied from Jim's code */
+/* in PVInitVideoEncoder(.), since we have different places */
+/* to reset profile and video buffer size */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+Bool SetProfile_BufferSize(VideoEncData *video, float delay, Int bInitialized)
+{
+ Int i, j, start, end;
+// Int BaseMBsPerSec = 0, EnhMBsPerSec = 0;
+ Int nTotalMB = 0;
+ Int idx, temp_w, temp_h, max = 0, max_width, max_height;
+
+ Int nLayers = video->encParams->nLayers; /* Number of Layers to be encoded */
+
+ Int total_bitrate = 0, base_bitrate;
+ Int total_packet_size = 0, base_packet_size;
+ Int total_MBsPerSec = 0, base_MBsPerSec;
+ Int total_VBV_size = 0, base_VBV_size, enhance_VBV_size = 0;
+ float total_framerate, base_framerate;
+ float upper_bound_ratio;
+ Int bFound = 0;
+ Int k = 0, width16, height16, index;
+ Int lowest_level;
+
+#define MIN_BUFF 16000 /* 16k minimum buffer size */
+#define BUFF_CONST 2.0 /* 2000ms */
+#define UPPER_BOUND_RATIO 8.54 /* upper_bound = 1.4*(1.1+bound/10)*bitrate/framerate */
+
+#define QCIF_WIDTH 176
+#define QCIF_HEIGHT 144
+
+ index = video->encParams->profile_table_index;
+
+ /* Calculate "nTotalMB" */
+ /* Find the maximum width*height for memory allocation of the VOPs */
+ for (idx = 0; idx < nLayers; idx++)
+ {
+ temp_w = video->encParams->LayerWidth[idx];
+ temp_h = video->encParams->LayerHeight[idx];
+
+ if ((temp_w*temp_h) > max)
+ {
+ max = temp_w * temp_h;
+ max_width = temp_w;
+ max_height = temp_h;
+ nTotalMB = ((max_width + 15) >> 4) * ((max_height + 15) >> 4);
+ }
+ }
+ upper_bound_ratio = (video->encParams->RC_Type == CBR_LOWDELAY ? (float)5.0 : (float)UPPER_BOUND_RATIO);
+
+
+ /* Get the basic information: bitrate, packet_size, MBs/s and VBV_size */
+ base_bitrate = video->encParams->LayerBitRate[0];
+ if (video->encParams->LayerMaxBitRate[0] != 0) /* video->encParams->LayerMaxBitRate[0] == 0 means it has not been set */
+ {
+ base_bitrate = PV_MAX(base_bitrate, video->encParams->LayerMaxBitRate[0]);
+ }
+ else /* if the max is not set, set it to the specified profile/level */
+ {
+ video->encParams->LayerMaxBitRate[0] = profile_level_max_bitrate[index];
+ }
+
+ base_framerate = video->encParams->LayerFrameRate[0];
+ if (video->encParams->LayerMaxFrameRate[0] != 0)
+ {
+ base_framerate = PV_MAX(base_framerate, video->encParams->LayerMaxFrameRate[0]);
+ }
+ else /* if the max is not set, set it to the specified profile/level */
+ {
+ video->encParams->LayerMaxFrameRate[0] = (float)profile_level_max_mbsPerSec[index] / nTotalMB;
+ }
+
+ base_packet_size = video->encParams->ResyncPacketsize;
+ base_MBsPerSec = (Int)(base_framerate * nTotalMB);
+ base_VBV_size = PV_MAX((Int)(base_bitrate * delay),
+ (Int)(upper_bound_ratio * base_bitrate / base_framerate));
+ base_VBV_size = PV_MAX(base_VBV_size, MIN_BUFF);
+
+ /* if the buffer is larger than maximum buffer size, we'll clip it */
+ if (base_VBV_size > profile_level_max_VBV_size[5])
+ base_VBV_size = profile_level_max_VBV_size[5];
+
+
+ /* Check if the buffer exceeds the maximum buffer size given the maximum profile and level */
+ if (nLayers == 1 && base_VBV_size > profile_level_max_VBV_size[index])
+ return FALSE;
+
+
+ if (nLayers == 2)
+ {
+ total_bitrate = video->encParams->LayerBitRate[1];
+ if (video->encParams->LayerMaxBitRate[1] != 0)
+ {
+ total_bitrate = PV_MIN(total_bitrate, video->encParams->LayerMaxBitRate[1]);
+ }
+ else /* if the max is not set, set it to the specified profile/level */
+ {
+ video->encParams->LayerMaxBitRate[1] = scalable_profile_level_max_bitrate[index];
+ }
+
+ total_framerate = video->encParams->LayerFrameRate[1];
+ if (video->encParams->LayerMaxFrameRate[1] != 0)
+ {
+ total_framerate = PV_MIN(total_framerate, video->encParams->LayerMaxFrameRate[1]);
+ }
+ else /* if the max is not set, set it to the specified profile/level */
+ {
+ video->encParams->LayerMaxFrameRate[1] = (float)scalable_profile_level_max_mbsPerSec[index] / nTotalMB;
+ }
+
+ total_packet_size = video->encParams->ResyncPacketsize;
+ total_MBsPerSec = (Int)(total_framerate * nTotalMB);
+
+ enhance_VBV_size = PV_MAX((Int)((total_bitrate - base_bitrate) * delay),
+ (Int)(upper_bound_ratio * (total_bitrate - base_bitrate) / (total_framerate - base_framerate)));
+ enhance_VBV_size = PV_MAX(enhance_VBV_size, MIN_BUFF);
+
+ total_VBV_size = base_VBV_size + enhance_VBV_size;
+
+ /* if the buffer is larger than maximum buffer size, we'll clip it */
+ if (total_VBV_size > scalable_profile_level_max_VBV_size[6])
+ {
+ total_VBV_size = scalable_profile_level_max_VBV_size[6];
+ enhance_VBV_size = total_VBV_size - base_VBV_size;
+ }
+
+ /* Check if the buffer exceeds the maximum buffer size given the maximum profile and level */
+ if (total_VBV_size > scalable_profile_level_max_VBV_size[index])
+ return FALSE;
+ }
+
+
+ if (!bInitialized) /* Has been initialized --> profile @ level has been figured out! */
+ {
+ video->encParams->BufferSize[0] = base_VBV_size;
+ if (nLayers > 1)
+ video->encParams->BufferSize[1] = enhance_VBV_size;
+
+ return PV_TRUE;
+ }
+
+
+ /* Profile @ level determination */
+ if (nLayers == 1)
+ {
+ /* BASE ONLY : Simple Profile(SP) Or Core Profile(CP) */
+ if (base_bitrate > profile_level_max_bitrate[index] ||
+ base_packet_size > profile_level_max_packet_size[index] ||
+ base_MBsPerSec > profile_level_max_mbsPerSec[index] ||
+ base_VBV_size > profile_level_max_VBV_size[index])
+
+ return PV_FALSE; /* Beyond the bound of Core Profile @ Level2 */
+
+ /* For H263/Short header, determine k*16384 */
+ width16 = ((video->encParams->LayerWidth[0] + 15) >> 4) << 4;
+ height16 = ((video->encParams->LayerHeight[0] + 15) >> 4) << 4;
+ if (video->encParams->H263_Enabled)
+ {
+ k = 4;
+ if (width16 == 2*QCIF_WIDTH && height16 == 2*QCIF_HEIGHT) /* CIF */
+ k = 16;
+
+ else if (width16 == 4*QCIF_WIDTH && height16 == 4*QCIF_HEIGHT) /* 4CIF */
+ k = 32;
+
+ else if (width16 == 8*QCIF_WIDTH && height16 == 8*QCIF_HEIGHT) /* 16CIF */
+ k = 64;
+
+ video->encParams->maxFrameSize = k * 16384;
+
+ /* Make sure the buffer size is limited to the top profile and level: the Core profile and level 2 */
+ if (base_VBV_size > (Int)(k*16384 + 4*(float)profile_level_max_bitrate[5]*1001.0 / 30000.0))
+ base_VBV_size = (Int)(k * 16384 + 4 * (float)profile_level_max_bitrate[5] * 1001.0 / 30000.0);
+
+ if (base_VBV_size > (Int)(k*16384 + 4*(float)profile_level_max_bitrate[index]*1001.0 / 30000.0))
+ return PV_FALSE;
+ }
+
+ /* Search the appropriate profile@level index */
+ if (!video->encParams->H263_Enabled &&
+ (video->encParams->IntraDCVlcThr != 0 || video->encParams->SearchRange > 16))
+ {
+ lowest_level = 1; /* cannot allow SPL0 */
+ }
+ else
+ {
+ lowest_level = 0; /* SPL0 */
+ }
+
+ for (i = lowest_level; i <= index; i++)
+ {
+ if (i != 4 && /* skip Core Profile@Level1 because the parameters in it are smaller than those in Simple Profile@Level3 */
+ base_bitrate <= profile_level_max_bitrate[i] &&
+ base_packet_size <= profile_level_max_packet_size[i] &&
+ base_MBsPerSec <= profile_level_max_mbsPerSec[i] &&
+ base_VBV_size <= (video->encParams->H263_Enabled ? (Int)(k*16384 + 4*(float)profile_level_max_bitrate[i]*1001.0 / 30000.0) :
+ profile_level_max_VBV_size[i]))
+ break;
+ }
+ if (i > index) return PV_FALSE; /* Nothing found!! */
+
+ /* Found out the actual profile @ level : index "i" */
+ if (i == 0)
+ {
+ /* For Simple Profile @ Level 0, we need to do one more check: image size <= QCIF */
+ if (width16 > QCIF_WIDTH || height16 > QCIF_HEIGHT)
+ i = 1; /* image size > QCIF, then set SP level1 */
+ }
+
+ video->encParams->ProfileLevel[0] = profile_level_code[i];
+ video->encParams->BufferSize[0] = base_VBV_size;
+
+ if (video->encParams->LayerMaxBitRate[0] == 0)
+ video->encParams->LayerMaxBitRate[0] = profile_level_max_bitrate[i];
+
+ if (video->encParams->LayerMaxFrameRate[0] == 0)
+ video->encParams->LayerMaxFrameRate[0] = PV_MIN(30, (float)profile_level_max_mbsPerSec[i] / nTotalMB);
+
+ /* For H263/Short header, one special constraint for VBV buffer size */
+ if (video->encParams->H263_Enabled)
+ video->encParams->BufferSize[0] = (Int)(k * 16384 + 4 * (float)profile_level_max_bitrate[i] * 1001.0 / 30000.0);
+
+ }
+ else
+ {
+ /* SCALABALE MODE: Simple Scalable Profile(SSP) Or Core Scalable Profile(CSP) */
+
+ if (total_bitrate > scalable_profile_level_max_bitrate[index] ||
+ total_packet_size > scalable_profile_level_max_packet_size[index] ||
+ total_MBsPerSec > scalable_profile_level_max_mbsPerSec[index] ||
+ total_VBV_size > scalable_profile_level_max_VBV_size[index])
+
+ return PV_FALSE; /* Beyond given profile and level */
+
+ /* One-time check: Simple Scalable Profile or Core Scalable Profile */
+ if (total_bitrate <= scalable_profile_level_max_bitrate[2] &&
+ total_packet_size <= scalable_profile_level_max_packet_size[2] &&
+ total_MBsPerSec <= scalable_profile_level_max_mbsPerSec[2] &&
+ total_VBV_size <= scalable_profile_level_max_VBV_size[2])
+
+ {
+ start = 0;
+ end = index;
+ }
+
+ else
+ {
+ start = 4;
+ end = index;
+ }
+
+
+ /* Search the scalable profile */
+ for (i = start; i <= end; i++)
+ {
+ if (total_bitrate <= scalable_profile_level_max_bitrate[i] &&
+ total_packet_size <= scalable_profile_level_max_packet_size[i] &&
+ total_MBsPerSec <= scalable_profile_level_max_mbsPerSec[i] &&
+ total_VBV_size <= scalable_profile_level_max_VBV_size[i])
+
+ break;
+ }
+ if (i > end) return PV_FALSE;
+
+ /* Search the base profile */
+ if (i == 0)
+ {
+ j = 0;
+ bFound = 1;
+ }
+ else bFound = 0;
+
+ for (j = start; !bFound && j <= i; j++)
+ {
+ if (base_bitrate <= profile_level_max_bitrate[j] &&
+ base_packet_size <= profile_level_max_packet_size[j] &&
+ base_MBsPerSec <= profile_level_max_mbsPerSec[j] &&
+ base_VBV_size <= profile_level_max_VBV_size[j])
+
+ {
+ bFound = 1;
+ break;
+ }
+ }
+
+ if (!bFound) // && start == 4)
+ return PV_FALSE; /* mis-match in the profiles between base layer and enhancement layer */
+
+ /* j for base layer, i for enhancement layer */
+ video->encParams->ProfileLevel[0] = profile_level_code[j];
+ video->encParams->ProfileLevel[1] = scalable_profile_level_code[i];
+ video->encParams->BufferSize[0] = base_VBV_size;
+ video->encParams->BufferSize[1] = enhance_VBV_size;
+
+ if (video->encParams->LayerMaxBitRate[0] == 0)
+ video->encParams->LayerMaxBitRate[0] = profile_level_max_bitrate[j];
+
+ if (video->encParams->LayerMaxBitRate[1] == 0)
+ video->encParams->LayerMaxBitRate[1] = scalable_profile_level_max_bitrate[i];
+
+ if (video->encParams->LayerMaxFrameRate[0] == 0)
+ video->encParams->LayerMaxFrameRate[0] = PV_MIN(30, (float)profile_level_max_mbsPerSec[j] / nTotalMB);
+
+ if (video->encParams->LayerMaxFrameRate[1] == 0)
+ video->encParams->LayerMaxFrameRate[1] = PV_MIN(30, (float)scalable_profile_level_max_mbsPerSec[i] / nTotalMB);
+
+
+ } /* end of: if(nLayers == 1) */
+
+
+ if (!video->encParams->H263_Enabled && (video->encParams->ProfileLevel[0] == 0x08)) /* SPL0 restriction*/
+ {
+ /* PV only allow frame-based rate control, no QP change from one MB to another
+ if(video->encParams->ACDCPrediction == TRUE && MB-based rate control)
+ return PV_FALSE */
+ }
+
+ return PV_TRUE;
+}
+
+#endif /* #ifndef ORIGINAL_VERSION */
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h
new file mode 100644
index 0000000..8293576
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4enc_lib.h
@@ -0,0 +1,207 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _MP4ENC_LIB_H_
+#define _MP4ENC_LIB_H_
+
+#include "mp4def.h" // typedef
+#include "mp4lib_int.h" // main video structure
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ /* defined in vop.c */
+ PV_STATUS EncodeVop(VideoEncData *video);
+ PV_STATUS EncodeSlice(VideoEncData *video);
+ PV_STATUS EncodeVideoPacketHeader(VideoEncData *video, int MB_number,
+ int quant_scale, Int insert);
+#ifdef ALLOW_VOP_NOT_CODED
+ PV_STATUS EncodeVopNotCoded(VideoEncData *video, UChar *bstream, Int *size, ULong modTime);
+#endif
+
+ /* defined in combined_decode.c */
+ PV_STATUS EncodeFrameCombinedMode(VideoEncData *video);
+ PV_STATUS EncodeSliceCombinedMode(VideoEncData *video);
+
+ /* defined in datapart_decode.c */
+ PV_STATUS EncodeFrameDataPartMode(VideoEncData *video);
+ PV_STATUS EncodeSliceDataPartMode(VideoEncData *video);
+
+ /* defined in fastcodeMB.c */
+
+//void m4v_memset(void *adr_dst, uint8 value, uint32 size);
+
+ PV_STATUS CodeMB_H263(VideoEncData *video, approxDCT *function, Int offsetQP, Int ncoefblck[]);
+#ifndef NO_MPEG_QUANT
+ PV_STATUS CodeMB_MPEG(VideoEncData *video, approxDCT *function, Int offsetQP, Int ncoefblck[]);
+#endif
+ Int getBlockSAV(Short block[]);
+ Int Sad8x8(UChar *rec, UChar *prev, Int lx);
+ Int getBlockSum(UChar *rec, Int lx);
+
+ /* defined in dct.c */
+ void blockIdct(Short *block);
+ void blockIdct_SSE(Short *input);
+ void BlockDCTEnc(Short *blockData, Short *blockCoeff);
+
+ /*---- FastQuant.c -----*/
+ Int cal_dc_scalerENC(Int QP, Int type) ;
+ Int BlockQuantDequantH263Inter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dummy, UChar shortHeader);
+
+ Int BlockQuantDequantH263Intra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int dctMode, Int comp, Int dc_scaler, UChar shortHeader);
+
+ Int BlockQuantDequantH263DCInter(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar *bitmaprow, UInt *bitmapzz, Int dummy, UChar shortHeader);
+
+ Int BlockQuantDequantH263DCIntra(Short *rcoeff, Short *qcoeff, struct QPstruct *QuantParam,
+ UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler, UChar shortHeader);
+
+#ifndef NO_MPEG_QUANT
+ Int BlockQuantDequantMPEGInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int DctMode, Int comp, Int dc_scaler);
+
+ Int BlockQuantDequantMPEGIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz,
+ Int DctMode, Int comp, Int dc_scaler);
+
+ Int BlockQuantDequantMPEGDCInter(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dummy);
+
+ Int BlockQuantDequantMPEGDCIntra(Short *rcoeff, Short *qcoeff, Int QP, Int *qmat,
+ UChar bitmapcol[ ], UChar *bitmaprow, UInt *bitmapzz, Int dc_scaler);
+#endif
+
+ /*---- FastIDCT.c -----*/
+ void BlockIDCTMotionComp(Short *block, UChar *bitmapcol, UChar bitmaprow,
+ Int dctMode, UChar *rec, UChar *prev, Int lx_intra_zeroMV);
+
+
+ /* defined in motion_comp.c */
+ void getMotionCompensatedMB(VideoEncData *video, Int ind_x, Int ind_y, Int offset);
+ void EncPrediction_INTER(Int xpred, Int ypred, UChar *c_prev, UChar *c_rec,
+ Int width, Int round1);
+
+ void EncPrediction_INTER4V(Int xpred, Int ypred, MOT *mot, UChar *c_prev, UChar *c_rec,
+ Int width, Int round1);
+
+ void EncPrediction_Chrom(Int xpred, Int ypred, UChar *cu_prev, UChar *cv_prev, UChar *cu_rec,
+ UChar *cv_rec, Int pitch_uv, Int width_uv, Int height_uv, Int round1);
+
+ void get_MB(UChar *c_prev, UChar *c_prev_u , UChar *c_prev_v,
+ Short mb[6][64], Int width, Int width_uv);
+
+ void PutSkippedBlock(UChar *rec, UChar *prev, Int lx);
+
+ /* defined in motion_est.c */
+ void MotionEstimation(VideoEncData *video);
+#ifdef HTFM
+ void InitHTFM(VideoEncData *video, HTFM_Stat *htfm_stat, double *newvar, Int *collect);
+ void UpdateHTFM(VideoEncData *video, double *newvar, double *exp_lamda, HTFM_Stat *htfm_stat);
+#endif
+
+ /* defined in ME_utils.c */
+ void ChooseMode_C(UChar *Mode, UChar *cur, Int lx, Int min_SAD);
+ void ChooseMode_MMX(UChar *Mode, UChar *cur, Int lx, Int min_SAD);
+ void GetHalfPelMBRegion_C(UChar *cand, UChar *hmem, Int lx);
+ void GetHalfPelMBRegion_SSE(UChar *cand, UChar *hmem, Int lx);
+ void GetHalfPelBlkRegion(UChar *cand, UChar *hmem, Int lx);
+ void PaddingEdge(Vop *padVop);
+ void ComputeMBSum_C(UChar *cur, Int lx, MOT *mot_mb);
+ void ComputeMBSum_MMX(UChar *cur, Int lx, MOT *mot_mb);
+ void ComputeMBSum_SSE(UChar *cur, Int lx, MOT *mot_mb);
+ void GetHalfPelMBRegionPadding(UChar *ncand, UChar *hmem, Int lx, Int *reptl);
+ void GetHalfPelBlkRegionPadding(UChar *ncand, UChar *hmem, Int lx, Int *reptl);
+
+ /* defined in findhalfpel.c */
+ void FindHalfPelMB(VideoEncData *video, UChar *cur, MOT *mot, UChar *ncand,
+ Int xpos, Int ypos, Int *xhmin, Int *yhmin, Int hp_guess);
+ Int FindHalfPelBlk(VideoEncData *video, UChar *cur, MOT *mot, Int sad16, UChar *ncand8[],
+ UChar *mode, Int xpos, Int ypos, Int *xhmin, Int *yhmin, UChar *hp_mem);
+
+
+ /* defined in sad.c */
+ Int SAD_MB_HalfPel_Cxhyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HalfPel_Cyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HalfPel_Cxh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HalfPel_MMX(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HalfPel_SSE(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_Blk_HalfPel_C(UChar *ref, UChar *blk, Int dmin, Int lx, Int rx, Int xh, Int yh, void *extra_info);
+ Int SAD_Blk_HalfPel_MMX(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+ Int SAD_Blk_HalfPel_SSE(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+ Int SAD_Macroblock_C(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_Macroblock_MMX(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_Macroblock_SSE(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_Block_C(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+ Int SAD_Block_MMX(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+ Int SAD_Block_SSE(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+
+#ifdef HTFM /* Hypothesis Testing Fast Matching */
+ Int SAD_MB_HP_HTFM_Collectxhyh(UChar *ref, UChar *blk, Int dmin_x, void *extra_info);
+ Int SAD_MB_HP_HTFM_Collectyh(UChar *ref, UChar *blk, Int dmin_x, void *extra_info);
+ Int SAD_MB_HP_HTFM_Collectxh(UChar *ref, UChar *blk, Int dmin_x, void *extra_info);
+ Int SAD_MB_HP_HTFMxhyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HP_HTFMyh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HP_HTFMxh(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HTFM_Collect(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int SAD_MB_HTFM(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+#endif
+ /* on-the-fly padding */
+ Int SAD_Blk_PADDING(UChar *ref, UChar *cur, Int dmin, Int lx, void *extra_info);
+ Int SAD_MB_PADDING(UChar *ref, UChar *cur, Int dmin, Int lx, void *extra_info);
+#ifdef HTFM
+ Int SAD_MB_PADDING_HTFM_Collect(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+ Int SAD_MB_PADDING_HTFM(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+#endif
+
+ /* defined in rate_control.c */
+ /* These are APIs to rate control exposed to core encoder module. */
+ PV_STATUS RC_Initialize(void *video);
+ PV_STATUS RC_VopQPSetting(VideoEncData *video, rateControl *rc[]);
+ PV_STATUS RC_VopUpdateStat(VideoEncData *video, rateControl *rc);
+ PV_STATUS RC_MBQPSetting(VideoEncData *video, rateControl *rc, Int start_packet_header);
+ PV_STATUS RC_MBUpdateStat(VideoEncData *video, rateControl *rc, Int Bi, Int Hi);
+ PV_STATUS RC_Cleanup(rateControl *rc[], Int numLayers);
+
+ Int RC_GetSkipNextFrame(VideoEncData *video, Int currLayer);
+ Int RC_GetRemainingVops(VideoEncData *video, Int currLayer);
+ void RC_ResetSkipNextFrame(VideoEncData *video, Int currLayer);
+ PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip);
+ PV_STATUS RC_UpdateBXRCParams(void *input);
+
+
+ /* defined in vlc_encode.c */
+ void MBVlcEncodeDataPar_I_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+ void MBVlcEncodeDataPar_P_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+ void MBVlcEncodeCombined_I_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+ void MBVlcEncodeCombined_P_VOP(VideoEncData *video, Int ncoefblck[], void *blkCodePtr);
+ void BlockCodeCoeff_ShortHeader(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode);
+ void BlockCodeCoeff_RVLC(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode);
+ void BlockCodeCoeff_Normal(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MP4ENC_LIB_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h b/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
new file mode 100644
index 0000000..3bc9421
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/mp4lib_int.h
@@ -0,0 +1,472 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+
+#ifndef _MP4LIB_INT_H_
+#define _MP4LIB_INT_H_
+
+#include "mp4def.h"
+#include "mp4enc_api.h"
+#include "rate_control.h"
+
+/* BitstreamEncVideo will be modified */
+typedef struct tagBitstream
+{
+ Int(*writeVideoPacket)(UChar *buf, Int nbytes_required); /*write video packet out */
+ UChar *bitstreamBuffer; /*buffer to hold one video packet*/
+ Int bufferSize; /*total bitstream buffer size in bytes */
+ Int byteCount; /*how many bytes already encoded*/
+ UInt word; /*hold one word temporarily */
+ Int bitLeft; /*number of bits left in "word" */
+ UChar* overrunBuffer; /* pointer to overrun buffer */
+ Int oBSize; /* length of overrun buffer */
+ struct tagVideoEncData *video;
+} BitstreamEncVideo;
+
+typedef struct tagVOP
+{
+ PIXEL *yChan; /* The Y component */
+ PIXEL *uChan; /* The U component */
+ PIXEL *vChan; /* The V component */
+ Int frame; /* frame number */
+ Int volID; /* Layer number */
+ //Int timeStamp; /* Vop TimeStamp in msec */
+
+ /* Syntax elements copied from VOL (standard) */
+ Int width; /* Width (multiple of 16) */
+ Int height; /* Height (multiple of 16) */
+ Int pitch; /* Pitch (differs from width for UMV case) */
+ Int padded; /* flag whether this frame has been padded */
+
+ /* Actual syntax elements for VOP (standard) */
+ Int predictionType; /* VOP prediction type */
+ Int timeInc; /* VOP time increment (relative to last mtb) */
+ Int vopCoded;
+ Int roundingType;
+ Int intraDCVlcThr;
+ Int quantizer; /* VOP quantizer */
+ Int fcodeForward; /* VOP dynamic range of motion vectors */
+ Int fcodeBackward; /* VOP dynamic range of motion vectors */
+ Int refSelectCode; /* enhancement layer reference select code */
+
+ /* H.263 parameters */
+ Int gobNumber;
+ Int gobFrameID;
+ Int temporalRef; /* temporal reference, roll over at 256 */
+ Int temporalInterval; /* increase every 256 temporalRef */
+
+} Vop;
+
+typedef struct tagVol
+{
+ Int volID; /* VOL identifier (for tracking) */
+ Int shortVideoHeader; /* shortVideoHeader mode */
+ Int GOVStart; /* Insert GOV Header */
+ Int timeIncrementResolution; /* VOL time increment */
+ Int nbitsTimeIncRes; /* number of bits for time increment */
+ Int timeIncrement; /* time increment */
+ Int moduloTimeBase; /* internal decoder clock */
+ Int prevModuloTimeBase; /* in case of pre-frameskip */
+
+ Int fixedVopRate;
+ BitstreamEncVideo *stream; /* library bitstream buffer (input buffer) */
+
+ /* VOL Dimensions */
+ Int width; /* Width */
+ Int height; /* Height */
+
+ /* Error Resilience Flags */
+ Int ResyncMarkerDisable; /* VOL Disable Resynch Markers */
+ Int useReverseVLC; /* VOL reversible VLCs */
+ Int dataPartitioning; /* VOL data partitioning */
+
+ /* Quantization related parameters */
+ Int quantPrecision; /* Quantizer precision */
+ Int quantType; /* MPEG-4 or H.263 Quantization Type */
+
+ /* Added loaded quant mat, 05/22/2000 */
+ Int loadIntraQuantMat; /* Load intra quantization matrix */
+ Int loadNonIntraQuantMat; /* Load nonintra quantization matrix */
+ Int iqmat[64]; /* Intra quant.matrix */
+ Int niqmat[64]; /* Non-intra quant.matrix */
+
+
+ /* Parameters used for scalability */
+ Int scalability; /* VOL scalability (flag) */
+ Int scalType; /* temporal = 0, spatial = 1, both = 2 */
+
+ Int refVolID; /* VOL id of reference VOL */
+ Int refSampDir; /* VOL resol. of ref. VOL */
+ Int horSamp_n; /* VOL hor. resampling of ref. VOL given by */
+ Int horSamp_m; /* sampfac = hor_samp_n/hor_samp_m */
+ Int verSamp_n; /* VOL ver. resampling of ref. VOL given by */
+ Int verSamp_m; /* sampfac = ver_samp_n/ver_samp_m */
+ Int enhancementType; /* VOL type of enhancement layer */
+
+ /* These variables were added since they are used a lot. */
+ Int nMBPerRow, nMBPerCol; /* number of MBs in each row & column */
+ Int nTotalMB;
+ Int nBitsForMBID; /* how many bits required for MB number? */
+
+ /* for short video header */
+ Int nMBinGOB; /* number of MBs in GOB, 05/22/00 */
+ Int nGOBinVop; /* number of GOB in Vop 05/22/00 */
+} Vol;
+
+typedef struct tagMacroBlock
+{
+ Int mb_x; /* X coordinate */
+ Int mb_y; /* Y coordinate */
+ Short block[9][64]; /* 4-Y, U and V blocks , and AAN Scale*/
+} MacroBlock;
+
+typedef struct tagRunLevelBlock
+{
+ Int run[64]; /* Runlength */
+ Int level[64]; /* Abs(level) */
+ Int s[64]; /* sign level */
+} RunLevelBlock;
+
+typedef struct tagHeaderInfoDecVideo
+{
+ UChar *Mode; /* Modes INTRA/INTER/etc. */
+ UChar *CBP; /* MCBPC/CBPY stuff */
+} HeaderInfoEncVideo;
+
+typedef Short typeDCStore[6]; /* ACDC */
+typedef Short typeDCACStore[4][8];
+
+typedef struct tagMOT
+{
+ Int x; /* half-pel resolution x component */
+ Int y; /* half-pel resolution y component */
+ Int sad; /* SAD */
+} MOT;
+
+typedef struct tagHintTrackInfo
+{
+ UChar MTB;
+ UChar LayerID;
+ UChar CodeType;
+ UChar RefSelCode;
+
+} HintTrackInfo;
+
+
+typedef struct tagVideoEncParams
+{
+ //Int Width; /* Input Width */
+ //Int Height; /* Input Height */
+ //float FrameRate; /* Input Frame Rate */
+ UInt TimeIncrementRes; /* timeIncrementRes */
+
+ /*VOL Parameters */
+ Int nLayers;
+ Int LayerWidth[4]; /* Encoded Width */
+ Int LayerHeight[4]; /* Encoded Height */
+ float LayerFrameRate[4]; /* Encoded Frame Rate */
+ Int LayerBitRate[4]; /* Encoded BitRate */
+ Int LayerMaxBitRate[4]; /* Maximum Encoded BitRate */
+ float LayerMaxFrameRate[4]; /* Maximum Encoded Frame Rate */
+ Int LayerMaxMbsPerSec[4]; /* Maximum mbs per second, according to the specified profile and level */
+ Int LayerMaxBufferSize[4]; /* Maximum buffer size, according to the specified profile and level */
+
+ Bool ResyncMarkerDisable; /* Disable Resync Marker */
+ Bool DataPartitioning; /* Base Layer Data Partitioning */
+ Bool ReversibleVLC; /* RVLC when Data Partitioning */
+ Bool ACDCPrediction; /* AC/DC Prediction */
+ Int QuantType[4]; /* H263, MPEG2 */
+ Int InitQuantBvop[4];
+ Int InitQuantPvop[4];
+ Int InitQuantIvop[4];
+ Int ResyncPacketsize;
+
+ Int RoundingType;
+ Int IntraDCVlcThr;
+
+ /* Rate Control Parameters */
+ MP4RateControlType RC_Type; /*Constant Q, M4 constantRate, VM5+, M4RC,MPEG2TM5 */
+
+ /* Intra Refresh Parameters */
+ Int IntraPeriod; /* Intra update period */
+ Int Refresh; /* Number of MBs refresh in each frame */
+ /* Other Parameters */
+ Bool SceneChange_Det; /* scene change detection */
+ Bool FineFrameSkip_Enabled; /* src rate resolution frame skipping */
+ Bool VBR_Enabled; /* VBR rate control */
+ Bool NoFrameSkip_Enabled; /* do not allow frame skip */
+ Bool NoPreSkip_Enabled; /* do not allow pre-skip */
+
+ Bool H263_Enabled; /* H263 Short Header */
+ Bool GOV_Enabled; /* GOV Header Enabled */
+ Bool SequenceStartCode; /* This probably should be removed */
+ Bool FullSearch_Enabled; /* full-pel exhaustive search motion estimation */
+ Bool HalfPel_Enabled; /* Turn Halfpel ME on or off */
+ Bool MV8x8_Enabled; /* Enable 8x8 motion vectors */
+ Bool RD_opt_Enabled; /* Enable operational R-D optimization */
+ Int GOB_Header_Interval; /* Enable encoding GOB header in H263_WITH_ERR_RES and SHORT_HERDER_WITH_ERR_RES */
+ Int SearchRange; /* Search range for 16x16 motion vector */
+ Int MemoryUsage; /* Amount of memory allocated */
+ Int GetVolHeader[2]; /* Flag to check if Vol Header has been retrieved */
+ Int BufferSize[2]; /* Buffer Size for Base and Enhance Layers */
+ Int ProfileLevel[2]; /* Profile and Level for encoding purposes */
+ float VBV_delay; /* VBV buffer size in the form of delay */
+ Int maxFrameSize; /* maximum frame size(bits) for H263/Short header mode, k*16384 */
+ Int profile_table_index; /* index for profile and level tables given the specified profile and level */
+
+} VideoEncParams;
+
+/* platform dependent functions */
+typedef struct tagFuncPtr
+{
+// Int (*SAD_MB_HalfPel)(UChar *ref,UChar *blk,Int dmin_lx,Int xh,Int yh,void *extra_info);
+ Int(*SAD_MB_HalfPel[4])(UChar*, UChar*, Int, void *);
+ Int(*SAD_Blk_HalfPel)(UChar *ref, UChar *blk, Int dmin, Int lx, Int rx, Int xh, Int yh, void *extra_info);
+ Int(*SAD_Macroblock)(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info);
+ Int(*SAD_Block)(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info);
+ Int(*SAD_MB_PADDING)(UChar *ref, UChar *blk, Int dmin, Int lx, void *extra_info); /*, 4/21/01 */
+ void (*ComputeMBSum)(UChar *cur, Int lx, MOT *mot_mb);
+ void (*ChooseMode)(UChar *Mode, UChar *cur, Int lx, Int min_SAD);
+ void (*GetHalfPelMBRegion)(UChar *cand, UChar *hmem, Int lx);
+ void (*blockIdct)(Int *block);
+
+
+} FuncPtr;
+
+/* 04/09/01, for multipass rate control */
+
+typedef struct tagRDInfo
+{
+ Int QP;
+ Int actual_bits;
+ float mad;
+ float R_D;
+} RDInfo;
+
+typedef struct tagMultiPass
+{
+ /* multipass rate control data */
+ Int target_bits; /* target bits for current frame, = rc->T */
+ Int actual_bits; /* actual bits for current frame obtained after encoding, = rc->Rc*/
+ Int QP; /* quantization level for current frame, = rc->Qc*/
+ Int prev_QP; /* quantization level for previous frame */
+ Int prev_prev_QP; /* quantization level for previous frame before last*/
+ float mad; /* mad for current frame, = video->avgMAD*/
+ Int bitrate; /* bitrate for current frame */
+ float framerate; /* framerate for current frame*/
+
+ Int nRe_Quantized; /* control variable for multipass encoding, */
+ /* 0 : first pass */
+ /* 1 : intermediate pass(quantization and VLC loop only) */
+ /* 2 : final pass(de-quantization, idct, etc) */
+ /* 3 : macroblock level rate control */
+
+ Int encoded_frames; /* counter for all encoded frames */
+ Int re_encoded_frames; /* counter for all multipass encoded frames*/
+ Int re_encoded_times; /* counter for all times of multipass frame encoding */
+
+ /* Multiple frame prediction*/
+ RDInfo **pRDSamples; /* pRDSamples[30][32], 30->30fps, 32 -> 5 bit quantizer, 32 candidates*/
+ Int framePos; /* specific position in previous multiple frames*/
+ Int frameRange; /* number of overall previous multiple frames */
+ Int samplesPerFrame[30]; /* number of samples per frame, 30->30fps */
+
+ /* Bit allocation for scene change frames and high motion frames */
+ float sum_mad;
+ Int counter_BTsrc; /* BT = Bit Transfer, bit transfer from low motion frames or less complicatedly compressed frames */
+ Int counter_BTdst; /* BT = Bit Transfer, bit transfer to scene change frames or high motion frames or more complicatedly compressed frames */
+ float sum_QP;
+ Int diff_counter; /* diff_counter = -diff_counter_BTdst, or diff_counter_BTsrc */
+
+ /* For target bitrate or framerate update */
+ float target_bits_per_frame; /* = C = bitrate/framerate */
+ float target_bits_per_frame_prev; /* previous C */
+ float aver_mad; /* so-far average mad could replace sum_mad */
+ float aver_mad_prev; /* previous average mad */
+ Int overlapped_win_size; /* transition period of time */
+ Int encoded_frames_prev; /* previous encoded_frames */
+} MultiPass;
+
+/* End */
+
+#ifdef HTFM
+typedef struct tagHTFM_Stat
+{
+ Int abs_dif_mad_avg;
+ UInt countbreak;
+ Int offsetArray[16];
+ Int offsetRef[16];
+} HTFM_Stat;
+#endif
+
+/* Global structure that can be passed around */
+typedef struct tagVideoEncData
+{
+ /* VOL Header Initialization */
+ UChar volInitialize[4]; /* Used to Write VOL Headers */
+ /* Data For Layers (Scalability) */
+ Int numberOfLayers; /* Number of Layers */
+ Vol **vol; /* Data stored for each VOL */
+
+ /* Data used for encoding frames */
+ VideoEncFrameIO *input; /* original input frame */
+ Vop *currVop; /* Current reconstructed VOP */
+ Vop *prevBaseVop; /* Previous reference Base Vop */
+ Vop *nextBaseVop; /* Next reference Base Vop */
+ Vop *prevEnhanceVop;/* Previous Enhancement Layer Vop */
+ Vop *forwardRefVop; /* Forward Reference VOP */
+ Vop *backwardRefVop; /* Backward Reference VOP */
+
+ /* scratch memory */
+ BitstreamEncVideo *bitstream1; /* Used for data partitioning */
+ BitstreamEncVideo *bitstream2; /* and combined modes as */
+ BitstreamEncVideo *bitstream3; /* intermediate storages */
+
+ UChar *overrunBuffer; /* extra output buffer to prevent current skip due to output buffer overrun*/
+ Int oBSize; /* size of allocated overrun buffer */
+
+ Int dc_scalar_1; /*dc scalar for Y block */
+ Int dc_scalar_2; /*dc scalar for U, V block*/
+
+ /* Annex L Rate Control */
+ rateControl *rc[4]; /* Pointer to Rate Control structure*/
+ /* 12/25/00, each R.C. for each layer */
+
+ /********* motion compensation related variables ****************/
+ MOT **mot; /* Motion vectors */
+ /* where [mbnum][0] = 1MV.
+ [mbnum][1...4] = 4MVs
+ [mbnum][5] = backward MV.
+ [mbnum][6] = delta MV for direct mode.
+ [mbnum][7] = nothing yet. */
+ UChar *intraArray; /* Intra Update Arrary */
+ float sumMAD; /* SAD/MAD for frame */
+
+ /* to speedup the SAD calculation */
+ void *sad_extra_info;
+#ifdef HTFM
+ Int nrmlz_th[48]; /* Threshold for fast SAD calculation using HTFM */
+ HTFM_Stat htfm_stat; /* For statistics collection */
+#endif
+
+ /*Tao 04/09/00 For DCT routine */
+ UChar currYMB[256]; /* interleaved current macroblock in HTFM order */
+ MacroBlock *outputMB; /* Output MB to VLC encode */
+ UChar predictedMB[384]; /* scrath memory for predicted value */
+ RunLevelBlock RLB[6]; /* Run and Level of coefficients! */
+ Short dataBlock[128]; /* DCT block data before and after quant/dequant*/
+
+ UChar bitmaprow[8]; /* Need to keep it for ACDCPrediction, 8 bytes for alignment, need only 6 */
+ UChar bitmapcol[6][8];
+ UInt bitmapzz[6][2]; /* for zigzag bitmap */
+ Int zeroMV; /* flag for zero MV */
+
+ Int usePrevQP; /* flag for intraDCVlcThreshold switch decision */
+ Int QP_prev; /* use for DQUANT calculation */
+ Int *acPredFlag; /* */
+ typeDCStore *predDC; /* The DC coeffs for each MB */
+ typeDCACStore *predDCAC_row;
+ typeDCACStore *predDCAC_col;
+
+
+ UChar *sliceNo; /* Slice Number for each MB */
+
+ Int header_bits; /* header bits in frmae */
+ HeaderInfoEncVideo headerInfo; /* MB Header information */
+ UChar zz_direction; /* direction of zigzag scan */
+ UChar *QPMB; /* Quantizer value for each MB */
+
+ /* Miscellaneous data points to be passed */
+ float FrameRate; /* Src frame Rate */
+
+ ULong nextModTime; /* expected next frame time */
+ UInt prevFrameNum[4]; /* previous frame number starting from modTimeRef */
+ UInt modTimeRef; /* Reference modTime update every I-Vop*/
+ UInt refTick[4]; /* second aligned referenc tick */
+ Int relLayerCodeTime[4];/* Next coding time for each Layer relative to highest layer */
+
+ ULong modTime; /* Input frame modTime */
+ Int currLayer; /* Current frame layer */
+ Int mbnum; /* Macroblock number */
+
+ /* slice coding, state variables */
+ Vop *tempForwRefVop;
+ Int tempRefSelCode;
+ Int end_of_buf; /* end of bitstream buffer flag */
+ Int slice_coding; /* flag for slice based coding */
+ Int totalSAD; /* So far total SAD for a frame */
+ Int numIntra; /* So far number of Intra MB */
+ Int offset; /* So far MB offset */
+ Int ind_x, ind_y; /* So far MB coordinate */
+ Int collect;
+ Int hp_guess;
+ /*********************************/
+
+ HintTrackInfo hintTrackInfo; /* hintTrackInfo */
+ /* IntraPeriod, Timestamp, etc. */
+ float nextEncIVop; /* counter til the next I-Vop */
+ float numVopsInGOP; /* value at the beginning of nextEncIVop */
+
+ /* platform dependent functions */
+ FuncPtr *functionPointer; /* structure containing platform dependent functions */
+
+ /* Application controls */
+ VideoEncControls *videoEncControls;
+ VideoEncParams *encParams;
+
+ MultiPass *pMP[4]; /* for multipass encoding, 4 represents 4 layer encoding */
+
+} VideoEncData;
+
+/*************************************************************/
+/* VLC structures */
+/*************************************************************/
+
+typedef struct tagVLCtable
+{
+ unsigned int code; /* right justified */
+ int len;
+} VLCtable, *LPVLCtable;
+
+
+/*************************************************************/
+/* Approx DCT */
+/*************************************************************/
+typedef struct struct_approxDCT approxDCT;
+struct struct_approxDCT
+{
+ Void(*BlockDCT8x8)(Int *, Int *, UChar *, UChar *, Int, Int);
+ Void(*BlockDCT8x8Intra)(Int *, Int *, UChar *, UChar *, Int, Int);
+ Void(*BlockDCT8x8wSub)(Int *, Int *, UChar *, UChar *, Int, Int);
+};
+
+/*************************************************************/
+/* QP structure */
+/*************************************************************/
+
+struct QPstruct
+{
+ Int QPx2 ;
+ Int QP;
+ Int QPdiv2;
+ Int QPx2plus;
+ Int Addition;
+};
+
+
+#endif /* _MP4LIB_INT_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
new file mode 100644
index 0000000..53149c1
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.cpp
@@ -0,0 +1,885 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "rate_control.h"
+#include "mp4enc_lib.h"
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+
+void targetBitCalculation(void *input);
+void calculateQuantizer_Multipass(void *video);
+void updateRateControl(rateControl *rc, VideoEncData *video);
+void updateRC_PostProc(rateControl *rc, VideoEncData *video);
+
+/***************************************************************************
+************** RC APIs to core encoding modules *******************
+
+PV_STATUS RC_Initialize(void *video);
+PV_STATUS RC_Cleanup(rateControl *rc[],Int numLayers);
+PV_STATUS RC_VopQPSetting(VideoEncData *video,rateControl *rc[]);
+PV_STATUS RC_VopUpdateStat(VideoEncData *video,rateControl *rc[]);
+PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip);
+Int RC_GetSkipNextFrame(VideoEncData *video,Int currLayer);
+void RC_ResetSkipNextFrame(void *video,Int currLayer);
+
+PV_STATUS RC_UpdateBXRCParams(void *input); Parameters update for target bitrate or framerate change
+
+****************************************************************************/
+
+
+/************************************************************************/
+/************ API part **************************************************/
+/* must be called before each sequence*/
+
+PV_STATUS RC_Initialize(void *input)
+{
+ VideoEncData *video = (VideoEncData *) input;
+ VideoEncParams *encParams = video->encParams;
+ rateControl **rc = video->rc;
+ Int numLayers = encParams->nLayers;
+ Int *LayerBitRate = encParams->LayerBitRate;
+ float *LayerFrameRate = encParams->LayerFrameRate;
+ MultiPass **pMP = video->pMP;
+
+ Int n;
+
+ for (n = 0; n < numLayers; n++)
+ {
+ /* rate control */
+ rc[n]->fine_frame_skip = encParams->FineFrameSkip_Enabled;
+ rc[n]->no_frame_skip = encParams->NoFrameSkip_Enabled;
+ rc[n]->no_pre_skip = encParams->NoPreSkip_Enabled;
+ rc[n]->skip_next_frame = 0; /* must be initialized */
+
+ //rc[n]->TMN_TH = (Int)((float)LayerBitRate[n]/LayerFrameRate[n]);
+ rc[n]->Bs = video->encParams->BufferSize[n];
+ rc[n]->TMN_W = 0;
+ rc[n]->VBV_fullness = (Int)(rc[n]->Bs * 0.5); /* rc[n]->Bs */
+ rc[n]->encoded_frames = 0;
+ rc[n]->framerate = LayerFrameRate[n];
+ if (n == 0)
+ {
+ rc[n]->TMN_TH = (Int)((float)LayerBitRate[n] / LayerFrameRate[n]);
+ rc[n]->bitrate = LayerBitRate[n];
+ rc[n]->framerate = LayerFrameRate[n];
+
+ // For h263 or short header mode, the bit variation is within (-2*Rmax*1001/3000, 2*Rmax*1001/3000)
+ if (video->encParams->H263_Enabled)
+ {
+ rc[n]->max_BitVariance_num = (Int)((rc[n]->Bs - video->encParams->maxFrameSize) / 2 / (rc[n]->bitrate / rc[n]->framerate / 10.0)) - 5;
+ if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+ }
+ else // MPEG-4 normal modes
+ {
+ rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - rc[n]->VBV_fullness) / ((float)LayerBitRate[n] / LayerFrameRate[n] / 10.0)) - 5;
+ if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+ }
+ }
+ else
+ {
+ if (LayerFrameRate[n] - LayerFrameRate[n-1] > 0) /* 7/31/03 */
+ {
+ rc[n]->TMN_TH = (Int)((float)(LayerBitRate[n] - LayerBitRate[n-1]) / (LayerFrameRate[n] - LayerFrameRate[n-1]));
+ rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - rc[n]->VBV_fullness) * 10 / ((float)rc[n]->TMN_TH)) - 5;
+ if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+ }
+ else /* 7/31/03 */
+ {
+ rc[n]->TMN_TH = 1 << 30;
+ rc[n]->max_BitVariance_num = 0;
+ }
+ rc[n]->bitrate = LayerBitRate[n] - LayerBitRate[n-1];
+ rc[n]->framerate = LayerFrameRate[n] - LayerFrameRate[n-1];
+ }
+
+ // Set the initial buffer fullness
+ if (1) //!video->encParams->H263_Enabled) { // MPEG-4
+ {
+ /* According to the spec, the initial buffer fullness needs to be set to 1/3 */
+ rc[n]->VBV_fullness = (Int)(rc[n]->Bs / 3.0 - rc[n]->Bs / 2.0); /* the buffer range is [-Bs/2, Bs/2] */
+ pMP[n]->counter_BTsrc = (Int)((rc[n]->Bs / 2.0 - rc[n]->Bs / 3.0) / (rc[n]->bitrate / rc[n]->framerate / 10.0));
+ rc[n]->TMN_W = (Int)(rc[n]->VBV_fullness + pMP[n]->counter_BTsrc * (rc[n]->bitrate / rc[n]->framerate / 10.0));
+
+ rc[n]->low_bound = -rc[n]->Bs / 2;
+ rc[n]-> VBV_fullness_offset = 0;
+ }
+ else /* this part doesn't work in some cases, the low_bound is too high, Jan 4,2006 */
+ {
+ rc[n]->VBV_fullness = rc[n]->Bs - (Int)(video->encParams->VBV_delay * rc[n]->bitrate);
+ if (rc[n]->VBV_fullness < 0) rc[n]->VBV_fullness = 0;
+ //rc[n]->VBV_fullness = (rc[n]->Bs-video->encParams->maxFrameSize)/2 + video->encParams->maxFrameSize;
+
+ rc[n]->VBV_fullness -= rc[n]->Bs / 2; /* the buffer range is [-Bs/2, Bs/2] */
+ rc[n]->low_bound = -rc[n]->Bs / 2 + video->encParams->maxFrameSize; /* too high */
+ rc[n]->VBV_fullness_offset = video->encParams->maxFrameSize / 2; /* don't understand the meaning of this */
+ pMP[n]->counter_BTdst = pMP[n]->counter_BTsrc = 0;
+
+ }
+
+ /* Setting the bitrate and framerate */
+ pMP[n]->bitrate = rc[n]->bitrate;
+ pMP[n]->framerate = rc[n]->framerate;
+ pMP[n]->target_bits_per_frame = pMP[n]->bitrate / pMP[n]->framerate;
+
+ }
+
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : RC_Cleanup */
+/* Date : 12/20/2000 */
+/* Purpose : free Rate Control memory */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+
+PV_STATUS RC_Cleanup(rateControl *rc[], Int numLayers)
+{
+ OSCL_UNUSED_ARG(rc);
+ OSCL_UNUSED_ARG(numLayers);
+
+ return PV_SUCCESS;
+}
+
+
+
+/* ======================================================================== */
+/* Function : RC_VopQPSetting */
+/* Date : 4/11/2001 */
+/* Purpose : Reset rate control before coding VOP, moved from vop.c */
+/* Compute QP for the whole VOP and initialize MB-based RC
+ reset QPMB[], currVop->quantizer, rc->Ec, video->header_bits */
+/* to In order to work RC_VopQPSetting has to do the followings
+ 1. Set video->QPMB of all macroblocks.
+ 2. Set currVop->quantizer
+ 3. Reset video->header_bits to zero.
+ 4. Initialize internal RC parameters for Vop cooding */
+/* In/out : */
+/* Return : PV_STATUS */
+/* Modified : */
+/* ======================================================================== */
+/* To be moved to rate_control.c and separate between BX_RC and ANNEX_L */
+
+PV_STATUS RC_VopQPSetting(VideoEncData *video, rateControl *prc[])
+{
+ Int currLayer = video->currLayer;
+ Vol *currVol = video->vol[currLayer];
+ Vop *currVop = video->currVop;
+#ifdef TEST_MBBASED_QP
+ int i;
+#endif
+
+ rateControl *rc = video->rc[currLayer];
+ MultiPass *pMP = video->pMP[currLayer];
+
+ OSCL_UNUSED_ARG(prc);
+
+ if (video->encParams->RC_Type == CONSTANT_Q)
+ {
+ M4VENC_MEMSET(video->QPMB, currVop->quantizer, sizeof(UChar)*currVol->nTotalMB);
+ return PV_SUCCESS;
+ }
+ else
+ {
+
+ if (video->rc[currLayer]->encoded_frames == 0) /* rc[currLayer]->totalFrameNumber*/
+ {
+ M4VENC_MEMSET(video->QPMB, currVop->quantizer, sizeof(UChar)*currVol->nTotalMB);
+ video->rc[currLayer]->Qc = video->encParams->InitQuantIvop[currLayer];
+ }
+ else
+ {
+ calculateQuantizer_Multipass((void*) video);
+ currVop->quantizer = video->rc[currLayer]->Qc;
+#ifdef TEST_MBBASED_QP
+ i = currVol->nTotalMB; /* testing changing QP at MB level */
+ while (i)
+ {
+ i--;
+ video->QPMB[i] = (i & 1) ? currVop->quantizer - 1 : currVop->quantizer + 1;
+ }
+#else
+ M4VENC_MEMSET(video->QPMB, currVop->quantizer, sizeof(UChar)*currVol->nTotalMB);
+#endif
+ }
+
+ video->header_bits = 0;
+ }
+
+ /* update pMP->framePos */
+ if (++pMP->framePos == pMP->frameRange) pMP->framePos = 0;
+
+ if (rc->T == 0)
+ {
+ pMP->counter_BTdst = (Int)(video->encParams->LayerFrameRate[video->currLayer] * 7.5 + 0.5); /* 0.75s time frame */
+ pMP->counter_BTdst = PV_MIN(pMP->counter_BTdst, (Int)(rc->max_BitVariance_num / 2 * 0.40)); /* 0.75s time frame may go beyond VBV buffer if we set the buffer size smaller than 0.75s */
+ pMP->counter_BTdst = PV_MAX(pMP->counter_BTdst, (Int)((rc->Bs / 2 - rc->VBV_fullness) * 0.30 / (rc->TMN_TH / 10.0) + 0.5)); /* At least 30% of VBV buffer size/2 */
+ pMP->counter_BTdst = PV_MIN(pMP->counter_BTdst, 20); /* Limit the target to be smaller than 3C */
+
+ pMP->target_bits = rc->T = rc->TMN_TH = (Int)(rc->TMN_TH * (1.0 + pMP->counter_BTdst * 0.1));
+ pMP->diff_counter = pMP->counter_BTdst;
+ }
+
+ /* collect the necessary data: target bits, actual bits, mad and QP */
+ pMP->target_bits = rc->T;
+ pMP->QP = currVop->quantizer;
+
+ pMP->mad = video->sumMAD / (float)currVol->nTotalMB;
+ if (pMP->mad < MAD_MIN) pMP->mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+
+ pMP->bitrate = rc->bitrate; /* calculated in RCVopQPSetting */
+ pMP->framerate = rc->framerate;
+
+ /* first pass encoding */
+ pMP->nRe_Quantized = 0;
+
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : SaveRDSamples() */
+/* Date : 08/29/2001 */
+/* History : */
+/* Purpose : Save QP, actual_bits, mad and R_D of the current iteration */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+Void SaveRDSamples(MultiPass *pMP, Int counter_samples)
+{
+ /* for pMP->pRDSamples */
+ pMP->pRDSamples[pMP->framePos][counter_samples].QP = pMP->QP;
+ pMP->pRDSamples[pMP->framePos][counter_samples].actual_bits = pMP->actual_bits;
+ pMP->pRDSamples[pMP->framePos][counter_samples].mad = pMP->mad;
+ pMP->pRDSamples[pMP->framePos][counter_samples].R_D = (float)(pMP->actual_bits / (pMP->mad + 0.0001));
+
+ return ;
+}
+/* ======================================================================== */
+/* Function : RC_VopUpdateStat */
+/* Date : 12/20/2000 */
+/* Purpose : Update statistics for rate control after encoding each VOP. */
+/* No need to change anything in VideoEncData structure. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS RC_VopUpdateStat(VideoEncData *video, rateControl *rc)
+{
+ Int currLayer = video->currLayer;
+ Vol *currVol = video->vol[currLayer];
+ MultiPass *pMP = video->pMP[currLayer];
+ Int diff_BTCounter;
+
+ switch (video->encParams->RC_Type)
+ {
+ case CONSTANT_Q:
+ break;
+
+ case CBR_1:
+ case CBR_2:
+ case VBR_1:
+ case VBR_2:
+ case CBR_LOWDELAY:
+
+ pMP->actual_bits = currVol->stream->byteCount << 3;
+
+ SaveRDSamples(pMP, 0);
+
+ pMP->encoded_frames++;
+
+ /* for pMP->samplesPerFrame */
+ pMP->samplesPerFrame[pMP->framePos] = 0;
+
+ pMP->sum_QP += pMP->QP;
+
+
+ /* update pMP->counter_BTsrc, pMP->counter_BTdst */
+ /* re-allocate the target bit again and then stop encoding */
+ diff_BTCounter = (Int)((float)(rc->TMN_TH - rc->TMN_W - pMP->actual_bits) /
+ (pMP->bitrate / (pMP->framerate + 0.0001) + 0.0001) / 0.1);
+ if (diff_BTCounter >= 0)
+ pMP->counter_BTsrc += diff_BTCounter; /* pMP->actual_bits is smaller */
+ else
+ pMP->counter_BTdst -= diff_BTCounter; /* pMP->actual_bits is bigger */
+
+ rc->TMN_TH -= (Int)((float)pMP->bitrate / (pMP->framerate + 0.0001) * (diff_BTCounter * 0.1));
+ rc->T = pMP->target_bits = rc->TMN_TH - rc->TMN_W;
+ pMP->diff_counter -= diff_BTCounter;
+
+ rc->Rc = currVol->stream->byteCount << 3; /* Total Bits for current frame */
+ rc->Hc = video->header_bits; /* Total Bits in Header and Motion Vector */
+
+ /* BX_RC */
+ updateRateControl(rc, video);
+
+ break;
+
+ default: /* for case CBR_1/2, VBR_1/2 */
+
+ return PV_FAIL;
+ }
+
+
+ return PV_SUCCESS;
+}
+
+/* ======================================================================== */
+/* Function : RC_GetSkipNextFrame, RC_GetRemainingVops */
+/* Date : 2/20/2001 */
+/* Purpose : To access RC parameters from other parts of the code. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+Int RC_GetSkipNextFrame(VideoEncData *video, Int currLayer)
+{
+ return video->rc[currLayer]->skip_next_frame;
+}
+
+void RC_ResetSkipNextFrame(VideoEncData *video, Int currLayer)
+{
+
+ video->rc[currLayer]->skip_next_frame = 0;
+ return ;
+}
+
+/* ======================================================================== */
+/* Function : RC_UpdateBuffer */
+/* Date : 2/20/2001 */
+/* Purpose : Update RC in case of there are frames skipped (camera freeze)*/
+/* from the application level in addition to what RC requested */
+/* In/out : Nr, B, Rr */
+/* Return : Void */
+/* Modified : */
+/* ======================================================================== */
+
+
+PV_STATUS RC_UpdateBuffer(VideoEncData *video, Int currLayer, Int num_skip)
+{
+ rateControl *rc = video->rc[currLayer];
+ MultiPass *pMP = video->pMP[currLayer];
+
+ if (video == NULL || rc == NULL || pMP == NULL)
+ return PV_FAIL;
+
+ rc->VBV_fullness -= (Int)(rc->bitrate / rc->framerate * num_skip); //rc[currLayer]->Rp;
+ pMP->counter_BTsrc += 10 * num_skip;
+
+ /* Check buffer underflow */
+ if (rc->VBV_fullness < rc->low_bound)
+ {
+ rc->VBV_fullness = rc->low_bound; // -rc->Bs/2;
+ rc->TMN_W = rc->VBV_fullness - rc->low_bound;
+ pMP->counter_BTsrc = pMP->counter_BTdst + (Int)((float)(rc->Bs / 2 - rc->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+ }
+
+ return PV_SUCCESS;
+}
+
+
+/* ======================================================================== */
+/* Function : RC_UpdateBXRCParams */
+/* Date : 4/08/2002 */
+/* Purpose : Update RC parameters specifically for target bitrate or */
+/* framerate update during an encoding session */
+/* In/out : */
+/* Return : PV_TRUE if successed, PV_FALSE if failed. */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS RC_UpdateBXRCParams(void *input)
+{
+ VideoEncData *video = (VideoEncData *) input;
+ VideoEncParams *encParams = video->encParams;
+ rateControl **rc = video->rc;
+ Int numLayers = encParams->nLayers;
+ Int *LayerBitRate = encParams->LayerBitRate;
+ float *LayerFrameRate = encParams->LayerFrameRate;
+ MultiPass **pMP = video->pMP;
+
+ Int n, VBV_fullness;
+ Int diff_counter;
+
+ extern Bool SetProfile_BufferSize(VideoEncData *video, float delay, Int bInitialized);
+
+
+ /* Reset video buffer size due to target bitrate change */
+ SetProfile_BufferSize(video, video->encParams->VBV_delay, 0); /* output: video->encParams->BufferSize[] */
+
+ for (n = 0; n < numLayers; n++)
+ {
+ /* Remaining stuff about frame dropping and underflow check in update RC */
+ updateRC_PostProc(rc[n], video);
+ rc[n]->skip_next_frame = 0; /* must be initialized */
+
+ /* New changes: bitrate and framerate, Bs, max_BitVariance_num, TMN_TH(optional), encoded_frames(optional) */
+ rc[n]->Bs = video->encParams->BufferSize[n];
+ VBV_fullness = (Int)(rc[n]->Bs * 0.5);
+
+ if (n == 0)
+ {
+ rc[n]->TMN_TH = (Int)((float)LayerBitRate[n] / LayerFrameRate[n]);
+ rc[n]->bitrate = pMP[n]->bitrate = LayerBitRate[n];
+ rc[n]->framerate = pMP[n]->framerate = LayerFrameRate[n];
+
+ // For h263 or short header mode, the bit variation is within (-2*Rmax*1001/3000, 2*Rmax*1001/3000)
+ if (video->encParams->H263_Enabled)
+ {
+ rc[n]->max_BitVariance_num = (Int)((rc[n]->Bs - video->encParams->maxFrameSize) / 2 / (rc[n]->bitrate / rc[n]->framerate / 10.0)) - 5;
+ //rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - rc[n]->VBV_fullness)/((float)LayerBitRate[n]/LayerFrameRate[n]/10.0))-5;
+ }
+ else // MPEG-4 normal modes
+ {
+ rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - VBV_fullness) * 10 / ((float)LayerBitRate[n] / LayerFrameRate[n])) - 5;
+ }
+ }
+ else
+ {
+ if (LayerFrameRate[n] - LayerFrameRate[n-1] > 0) /* 7/31/03 */
+ {
+ rc[n]->TMN_TH = (Int)((float)(LayerBitRate[n] - LayerBitRate[n-1]) / (LayerFrameRate[n] - LayerFrameRate[n-1]));
+ rc[n]->max_BitVariance_num = (Int)((float)(rc[n]->Bs - VBV_fullness) * 10 / ((float)rc[n]->TMN_TH)) - 5;
+ if (rc[n]->max_BitVariance_num < 0) rc[n]->max_BitVariance_num += 5;
+ }
+ else /* 7/31/03 */
+ {
+ rc[n]->TMN_TH = 1 << 30;
+ rc[n]->max_BitVariance_num = 0;
+ }
+ rc[n]->bitrate = pMP[n]->bitrate = LayerBitRate[n] - LayerBitRate[n-1];
+ rc[n]->framerate = pMP[n]->framerate = LayerFrameRate[n] - LayerFrameRate[n-1];
+ }
+
+ pMP[n]->target_bits_per_frame_prev = pMP[n]->target_bits_per_frame;
+ pMP[n]->target_bits_per_frame = pMP[n]->bitrate / (float)(pMP[n]->framerate + 0.0001); /* 7/31/03 */
+
+ /* rc[n]->VBV_fullness and rc[n]->TMN_W should be kept same */
+ /* update pMP[n]->counter_BTdst and pMP[n]->counter_BTsrc */
+ diff_counter = (Int)((float)(rc[n]->VBV_fullness - rc[n]->TMN_W) /
+ (pMP[n]->target_bits_per_frame / 10 + 0.0001)); /* 7/31/03 */
+
+ pMP[n]->counter_BTdst = pMP[n]->counter_BTsrc = 0;
+ if (diff_counter > 0)
+ pMP[n]->counter_BTdst = diff_counter;
+
+ else if (diff_counter < 0)
+ pMP[n]->counter_BTsrc = -diff_counter;
+
+ rc[n]->TMN_W = (Int)(rc[n]->VBV_fullness - /* re-calculate rc[n]->TMN_W in order for higher accuracy */
+ (pMP[n]->target_bits_per_frame / 10) * (pMP[n]->counter_BTdst - pMP[n]->counter_BTsrc));
+
+ /* Keep the current average mad */
+ if (pMP[n]->aver_mad != 0)
+ {
+ pMP[n]->aver_mad_prev = pMP[n]->aver_mad;
+ pMP[n]->encoded_frames_prev = pMP[n]->encoded_frames;
+ }
+
+ pMP[n]->aver_mad = 0;
+ pMP[n]->overlapped_win_size = 4;
+
+ /* Misc */
+ pMP[n]->sum_mad = pMP[n]->sum_QP = 0;
+ //pMP[n]->encoded_frames_prev = pMP[n]->encoded_frames;
+ pMP[n]->encoded_frames = pMP[n]->re_encoded_frames = pMP[n]->re_encoded_times = 0;
+
+ } /* end of: for(n=0; n<numLayers; n++) */
+
+ return PV_SUCCESS;
+
+}
+
+
+/* ================================================================================ */
+/* Function : targetBitCalculation */
+/* Date : 10/01/2001 */
+/* Purpose : quadratic bit allocation model: T(n) = C*sqrt(mad(n)/aver_mad(n-1)) */
+/* */
+/* In/out : rc->T */
+/* Return : Void */
+/* Modified : */
+/* ================================================================================ */
+
+void targetBitCalculation(void *input)
+{
+ VideoEncData *video = (VideoEncData *) input;
+ MultiPass *pMP = video->pMP[video->currLayer];
+ Vol *currVol = video->vol[video->currLayer];
+ rateControl *rc = video->rc[video->currLayer];
+
+ float curr_mad;//, average_mad;
+ Int diff_counter_BTsrc, diff_counter_BTdst, prev_counter_diff, curr_counter_diff, bound;
+ /* BT = Bit Transfer, for pMP->counter_BTsrc, pMP->counter_BTdst */
+
+ if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+ return;
+
+ /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/
+ updateRC_PostProc(rc, video);
+
+ /* update pMP->counter_BTsrc and pMP->counter_BTdst to avoid interger overflow */
+ if (pMP->counter_BTsrc > 1000 && pMP->counter_BTdst > 1000)
+ {
+ pMP->counter_BTsrc -= 1000;
+ pMP->counter_BTdst -= 1000;
+ }
+
+ /* ---------------------------------------------------------------------------------------------------*/
+ /* target calculation */
+ curr_mad = video->sumMAD / (float)currVol->nTotalMB;
+ if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+ diff_counter_BTsrc = diff_counter_BTdst = 0;
+ pMP->diff_counter = 0;
+
+
+ /*1.calculate average mad */
+ pMP->sum_mad += curr_mad;
+ //average_mad = (pMP->encoded_frames < 1 ? curr_mad : pMP->sum_mad/(float)(pMP->encoded_frames+1)); /* this function is called from the scond encoded frame*/
+ //pMP->aver_mad = average_mad;
+ if (pMP->encoded_frames >= 0) /* pMP->encoded_frames is set to -1 initially, so forget about the very first I frame */
+ pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames + curr_mad) / (pMP->encoded_frames + 1);
+
+ if (pMP->overlapped_win_size > 0 && pMP->encoded_frames_prev >= 0) /* 7/31/03 */
+ pMP->aver_mad_prev = (pMP->aver_mad_prev * pMP->encoded_frames_prev + curr_mad) / (pMP->encoded_frames_prev + 1);
+
+ /*2.average_mad, mad ==> diff_counter_BTsrc, diff_counter_BTdst */
+ if (pMP->overlapped_win_size == 0)
+ {
+ /* original verison */
+ if (curr_mad > pMP->aver_mad*1.1)
+ {
+ if (curr_mad / (pMP->aver_mad + 0.0001) > 2)
+ diff_counter_BTdst = (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.4) - 10;
+ //diff_counter_BTdst = (Int)((sqrt(curr_mad/pMP->aver_mad)*2+curr_mad/pMP->aver_mad)/(3*0.1) + 0.4) - 10;
+ else
+ diff_counter_BTdst = (Int)(curr_mad / (pMP->aver_mad + 0.0001) * 10 + 0.4) - 10;
+ }
+ else /* curr_mad <= average_mad*1.1 */
+ //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad) + pow(curr_mad/pMP->aver_mad, 1.0/3.0))/(2.0*0.1) + 0.4);
+ diff_counter_BTsrc = 10 - (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad + 0.0001)) * 10 + 0.5);
+ //diff_counter_BTsrc = 10 - (Int)(curr_mad/pMP->aver_mad/0.1 + 0.5)
+
+ /* actively fill in the possible gap */
+ if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+ curr_mad <= pMP->aver_mad*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+ diff_counter_BTsrc = 1;
+
+ }
+ else if (pMP->overlapped_win_size > 0)
+ {
+ /* transition time: use previous average mad "pMP->aver_mad_prev" instead of the current average mad "pMP->aver_mad" */
+ if (curr_mad > pMP->aver_mad_prev*1.1)
+ {
+ if (curr_mad / pMP->aver_mad_prev > 2)
+ diff_counter_BTdst = (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.4) - 10;
+ //diff_counter_BTdst = (Int)((M4VENC_SQRT(curr_mad/pMP->aver_mad_prev)*2+curr_mad/pMP->aver_mad_prev)/(3*0.1) + 0.4) - 10;
+ else
+ diff_counter_BTdst = (Int)(curr_mad / (pMP->aver_mad_prev + 0.0001) * 10 + 0.4) - 10;
+ }
+ else /* curr_mad <= average_mad*1.1 */
+ //diff_counter_BTsrc = 10 - (Int)((sqrt(curr_mad/pMP->aver_mad_prev) + pow(curr_mad/pMP->aver_mad_prev, 1.0/3.0))/(2.0*0.1) + 0.4);
+ diff_counter_BTsrc = 10 - (Int)(M4VENC_SQRT(curr_mad / (pMP->aver_mad_prev + 0.0001)) * 10 + 0.5);
+ //diff_counter_BTsrc = 10 - (Int)(curr_mad/pMP->aver_mad_prev/0.1 + 0.5)
+
+ /* actively fill in the possible gap */
+ if (diff_counter_BTsrc == 0 && diff_counter_BTdst == 0 &&
+ curr_mad <= pMP->aver_mad_prev*1.1 && pMP->counter_BTsrc < pMP->counter_BTdst)
+ diff_counter_BTsrc = 1;
+
+ if (--pMP->overlapped_win_size <= 0) pMP->overlapped_win_size = 0;
+ }
+
+
+ /* if difference is too much, do clipping */
+ /* First, set the upper bound for current bit allocation variance: 80% of available buffer */
+ bound = (Int)((rc->Bs / 2 - rc->VBV_fullness) * 0.6 / (pMP->target_bits_per_frame / 10)); /* rc->Bs */
+ diff_counter_BTsrc = PV_MIN(diff_counter_BTsrc, bound);
+ diff_counter_BTdst = PV_MIN(diff_counter_BTdst, bound);
+
+ /* Second, set another upper bound for current bit allocation: 4-5*bitrate/framerate */
+ bound = 50;
+// if(video->encParams->RC_Type == CBR_LOWDELAY)
+// not necessary bound = 10; /* 1/17/02 -- For Low delay */
+
+ diff_counter_BTsrc = PV_MIN(diff_counter_BTsrc, bound);
+ diff_counter_BTdst = PV_MIN(diff_counter_BTdst, bound);
+
+
+ /* Third, check the buffer */
+ prev_counter_diff = pMP->counter_BTdst - pMP->counter_BTsrc;
+ curr_counter_diff = prev_counter_diff + (diff_counter_BTdst - diff_counter_BTsrc);
+
+ if (PV_ABS(prev_counter_diff) >= rc->max_BitVariance_num || PV_ABS(curr_counter_diff) >= rc->max_BitVariance_num) // PV_ABS(curr_counter_diff) >= PV_ABS(prev_counter_diff) )
+ { //diff_counter_BTsrc = diff_counter_BTdst = 0;
+
+ if (curr_counter_diff > rc->max_BitVariance_num && diff_counter_BTdst)
+ {
+ diff_counter_BTdst = (rc->max_BitVariance_num - prev_counter_diff) + diff_counter_BTsrc;
+ if (diff_counter_BTdst < 0) diff_counter_BTdst = 0;
+ }
+
+ else if (curr_counter_diff < -rc->max_BitVariance_num && diff_counter_BTsrc)
+ {
+ diff_counter_BTsrc = diff_counter_BTdst - (-rc->max_BitVariance_num - prev_counter_diff);
+ if (diff_counter_BTsrc < 0) diff_counter_BTsrc = 0;
+ }
+ }
+
+
+ /*3.diff_counter_BTsrc, diff_counter_BTdst ==> TMN_TH */
+ //rc->TMN_TH = (Int)((float)pMP->bitrate/pMP->framerate);
+ rc->TMN_TH = (Int)(pMP->target_bits_per_frame);
+ pMP->diff_counter = 0;
+
+ if (diff_counter_BTsrc)
+ {
+ rc->TMN_TH -= (Int)(pMP->target_bits_per_frame * diff_counter_BTsrc * 0.1);
+ pMP->diff_counter = -diff_counter_BTsrc;
+ }
+ else if (diff_counter_BTdst)
+ {
+ rc->TMN_TH += (Int)(pMP->target_bits_per_frame * diff_counter_BTdst * 0.1);
+ pMP->diff_counter = diff_counter_BTdst;
+ }
+
+
+ /*4.update pMP->counter_BTsrc, pMP->counter_BTdst */
+ pMP->counter_BTsrc += diff_counter_BTsrc;
+ pMP->counter_BTdst += diff_counter_BTdst;
+
+
+ /*5.target bit calculation */
+ rc->T = rc->TMN_TH - rc->TMN_W;
+ //rc->T = rc->TMN_TH - (Int)((float)rc->TMN_W/rc->frameRate);
+
+ if (video->encParams->H263_Enabled && rc->T > video->encParams->maxFrameSize)
+ {
+ rc->T = video->encParams->maxFrameSize; // added this 11/07/05
+ }
+
+}
+
+/* ================================================================================ */
+/* Function : calculateQuantizer_Multipass */
+/* Date : 10/01/2001 */
+/* Purpose : variable rate bit allocation + new QP determination scheme */
+/* */
+/* In/out : rc->T and rc->Qc */
+/* Return : Void */
+/* Modified : */
+/* ================================================================================ */
+
+/* Mad based variable bit allocation + QP calculation with a new quadratic method */
+void calculateQuantizer_Multipass(void *input)
+{
+ VideoEncData *video = (VideoEncData *) input;
+ MultiPass *pMP = video->pMP[video->currLayer];
+ Vol *currVol = video->vol[video->currLayer];
+ rateControl *rc = video->rc[video->currLayer];
+
+ Int prev_QP, prev_actual_bits, curr_target, i, j;
+
+ float curr_mad, prev_mad, curr_RD, prev_RD, average_mad, aver_QP;
+
+
+ if (video == NULL || currVol == NULL || pMP == NULL || rc == NULL)
+ return;
+
+ /* Mad based variable bit allocation */
+ targetBitCalculation((void*) video);
+
+ if (rc->T <= 0 || video->sumMAD == 0)
+ {
+ if (rc->T < 0) rc->Qc = 31;
+ return;
+ }
+
+ /* ---------------------------------------------------------------------------------------------------*/
+ /* current frame QP estimation */
+ curr_target = rc->T;
+ curr_mad = video->sumMAD / (float)currVol->nTotalMB;
+ if (curr_mad < MAD_MIN) curr_mad = MAD_MIN; /* MAD_MIN is defined as 1 in mp4def.h */
+ curr_RD = (float)curr_target / curr_mad;
+
+ /* Another version of search the optimal point */
+ prev_actual_bits = pMP->pRDSamples[0][0].actual_bits;
+ prev_mad = pMP->pRDSamples[0][0].mad;
+
+ for (i = 0, j = 0; i < pMP->frameRange; i++)
+ {
+ if (pMP->pRDSamples[i][0].mad != 0 && prev_mad != 0 &&
+ PV_ABS(prev_mad - curr_mad) > PV_ABS(pMP->pRDSamples[i][0].mad - curr_mad))
+ {
+ prev_mad = pMP->pRDSamples[i][0].mad;
+ prev_actual_bits = pMP->pRDSamples[i][0].actual_bits;
+ j = i;
+ }
+ }
+ prev_QP = pMP->pRDSamples[j][0].QP;
+ for (i = 1; i < pMP->samplesPerFrame[j]; i++)
+ {
+ if (PV_ABS(prev_actual_bits - curr_target) > PV_ABS(pMP->pRDSamples[j][i].actual_bits - curr_target))
+ {
+ prev_actual_bits = pMP->pRDSamples[j][i].actual_bits;
+ prev_QP = pMP->pRDSamples[j][i].QP;
+ }
+ }
+
+ // quadratic approximation
+ prev_RD = (float)prev_actual_bits / prev_mad;
+ //rc->Qc = (Int)(prev_QP * sqrt(prev_actual_bits/curr_target) + 0.4);
+ if (prev_QP == 1) // 11/14/05, added this to allow getting out of QP = 1 easily
+ {
+ rc->Qc = (Int)(prev_RD / curr_RD + 0.5);
+ }
+ else
+ {
+ rc->Qc = (Int)(prev_QP * M4VENC_SQRT(prev_RD / curr_RD) + 0.9);
+
+ if (prev_RD / curr_RD > 0.5 && prev_RD / curr_RD < 2.0)
+ rc->Qc = (Int)(prev_QP * (M4VENC_SQRT(prev_RD / curr_RD) + prev_RD / curr_RD) / 2.0 + 0.9); /* Quadratic and linear approximation */
+ else
+ rc->Qc = (Int)(prev_QP * (M4VENC_SQRT(prev_RD / curr_RD) + M4VENC_POW(prev_RD / curr_RD, 1.0 / 3.0)) / 2.0 + 0.9);
+ }
+ //rc->Qc =(Int)(prev_QP * sqrt(prev_RD/curr_RD) + 0.4);
+ // 11/08/05
+ // lower bound on Qc should be a function of curr_mad
+ // When mad is already low, lower bound on Qc doesn't have to be small.
+ // Note, this doesn't work well for low complexity clip encoded at high bit rate
+ // it doesn't hit the target bit rate due to this QP lower bound.
+/// if((curr_mad < 8) && (rc->Qc < 12)) rc->Qc = 12;
+// else if((curr_mad < 128) && (rc->Qc < 3)) rc->Qc = 3;
+
+ if (rc->Qc < 1) rc->Qc = 1;
+ if (rc->Qc > 31) rc->Qc = 31;
+
+
+ /* active bit resource protection */
+ aver_QP = (pMP->encoded_frames == 0 ? 0 : pMP->sum_QP / (float)pMP->encoded_frames);
+ average_mad = (pMP->encoded_frames == 0 ? 0 : pMP->sum_mad / (float)pMP->encoded_frames); /* this function is called from the scond encoded frame*/
+ if (pMP->diff_counter == 0 &&
+ ((float)rc->Qc <= aver_QP*1.1 || curr_mad <= average_mad*1.1) &&
+ pMP->counter_BTsrc <= (pMP->counter_BTdst + (Int)(pMP->framerate*1.0 + 0.5)))
+ {
+ rc->TMN_TH -= (Int)(pMP->target_bits_per_frame / 10.0);
+ rc->T = rc->TMN_TH - rc->TMN_W;
+ pMP->counter_BTsrc++;
+ pMP->diff_counter--;
+ }
+
+}
+
+
+/* ======================================================================== */
+/* Function : updateRateControl */
+/* Date : 11/17/2000 */
+/* Purpose :Update the RD Modal (After Encoding the Current Frame) */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+void updateRateControl(rateControl *rc, VideoEncData *video)
+{
+ Int frame_bits;
+
+
+ /* rate contro\l */
+ frame_bits = (Int)(rc->bitrate / rc->framerate);
+ rc->TMN_W += (rc->Rc - rc->TMN_TH);
+ rc->VBV_fullness += (rc->Rc - frame_bits); //rc->Rp);
+ //if(rc->VBV_fullness < 0) rc->VBV_fullness = -1;
+
+ rc->encoded_frames++;
+
+ /* frame dropping */
+ rc->skip_next_frame = 0;
+
+ if ((video->encParams->H263_Enabled && rc->Rc > video->encParams->maxFrameSize) || /* For H263/short header mode, drop the frame if the actual frame size exceeds the bound */
+ (rc->VBV_fullness > rc->Bs / 2 && !rc->no_pre_skip)) /* skip the current frame */ /* rc->Bs */
+ {
+ rc->TMN_W -= (rc->Rc - rc->TMN_TH);
+ rc->VBV_fullness -= rc->Rc;
+ rc->skip_next_frame = -1;
+ }
+ else if ((float)(rc->VBV_fullness - rc->VBV_fullness_offset) > (rc->Bs / 2 - rc->VBV_fullness_offset)*0.95 &&
+ !rc->no_frame_skip) /* skip next frame */
+ {
+ rc->VBV_fullness -= frame_bits; //rc->Rp;
+ rc->skip_next_frame = 1;
+ /* skip more than 1 frames */
+ //while(rc->VBV_fullness > rc->Bs*0.475)
+ while ((rc->VBV_fullness - rc->VBV_fullness_offset) > (rc->Bs / 2 - rc->VBV_fullness_offset)*0.95)
+ {
+ rc->VBV_fullness -= frame_bits; //rc->Rp;
+ rc->skip_next_frame++;
+ }
+ /* END */
+ }
+
+}
+
+/* ======================================================================== */
+/* Function : updateRC_PostProc */
+/* Date : 04/08/2002 */
+/* Purpose : Remaing RC update stuff for frame skip and buffer underflow */
+/* check */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+void updateRC_PostProc(rateControl *rc, VideoEncData *video)
+{
+ MultiPass *pMP = video->pMP[video->currLayer];
+
+ if (rc->skip_next_frame == 1 && !rc->no_frame_skip) /* skip next frame */
+ {
+ pMP->counter_BTsrc += 10 * rc->skip_next_frame;
+
+ }
+ else if (rc->skip_next_frame == -1 && !rc->no_pre_skip) /* skip current frame */
+ {
+ pMP->counter_BTdst -= pMP->diff_counter;
+ pMP->counter_BTsrc += 10;
+
+ pMP->sum_mad -= pMP->mad;
+ pMP->aver_mad = (pMP->aver_mad * pMP->encoded_frames - pMP->mad) / (float)(pMP->encoded_frames - 1 + 0.0001);
+ pMP->sum_QP -= pMP->QP;
+ pMP->encoded_frames --;
+ }
+ /* some stuff in update VBV_fullness remains here */
+ //if(rc->VBV_fullness < -rc->Bs/2) /* rc->Bs */
+ if (rc->VBV_fullness < rc->low_bound)
+ {
+ rc->VBV_fullness = rc->low_bound; // -rc->Bs/2;
+ rc->TMN_W = rc->VBV_fullness - rc->low_bound;
+ pMP->counter_BTsrc = pMP->counter_BTdst + (Int)((float)(rc->Bs / 2 - rc->low_bound) / 2.0 / (pMP->target_bits_per_frame / 10));
+ }
+}
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h
new file mode 100644
index 0000000..ad29549
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/rate_control.h
@@ -0,0 +1,96 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _RATE_CONTROL_H_
+#define _RATE_CONTROL_H_
+
+#include "mp4def.h"
+
+typedef struct tagdataPointArray
+{
+ Int Qp;
+ Int Rp;
+ float Mp; /* for MB-based RC, 3/14/01 */
+ struct tagdataPointArray *next;
+ struct tagdataPointArray *prev;
+} dataPointArray;
+
+
+typedef struct
+{
+ Int alpha; /* weight for I frame */
+ Int Rs; /*bit rate for the sequence (or segment) e.g., 24000 bits/sec */
+ Int Rc; /*bits used for the current frame. It is the bit count obtained after encoding. */
+ Int Rp; /*bits to be removed from the buffer per picture. */
+ /*? is this the average one, or just the bits coded for the previous frame */
+ Int Rps; /*bit to be removed from buffer per src frame */
+ float Ts; /*number of seconds for the sequence (or segment). e.g., 10 sec */
+ float Ep;
+ float Ec; /*mean absolute difference for the current frame after motion compensation.*/
+ /*If the macroblock is intra coded, the original spatial pixel values are summed.*/
+ Int Qc; /*quantization level used for the current frame. */
+ Int Nr; /*number of P frames remaining for encoding.*/
+ Int Rr; /*number of bits remaining for encoding this sequence (or segment).*/
+ Int Rr_Old;/* 12/24/00 */
+ Int T; /*target bit to be used for the current frame.*/
+ Int S; /*number of bits used for encoding the previous frame.*/
+ Int Hc; /*header and motion vector bits used in the current frame. It includes all the information except to the residual information.*/
+ Int Hp; /*header and motion vector bits used in the previous frame. It includes all the information except to the residual information.*/
+ Int Ql; /*quantization level used in the previous frame */
+ Int Bs; /*buffer size e.g., R/2 */
+ Int B; /*current buffer level e.g., R/4 - start from the middle of the buffer */
+ float X1;
+ float X2;
+ float X11;
+ float M; /*safe margin for the buffer */
+ float smTick; /*ratio of src versus enc frame rate */
+ double remnant; /*remainder frame of src/enc frame for fine frame skipping */
+ Int timeIncRes; /* vol->timeIncrementResolution */
+
+ dataPointArray *end; /*quantization levels for the past (20) frames */
+
+ Int frameNumber; /* ranging from 0 to 20 nodes*/
+ Int w;
+ Int Nr_Original;
+ Int Nr_Old, Nr_Old2;
+ Int skip_next_frame;
+ Int Qdep; /* smooth Q adjustment */
+ Int fine_frame_skip;
+ Int VBR_Enabled;
+ Int no_frame_skip;
+ Int no_pre_skip;
+
+ Int totalFrameNumber; /* total coded frames, for debugging!!*/
+
+ char oFirstTime;
+
+ /* BX rate control */
+ Int TMN_W;
+ Int TMN_TH;
+ Int VBV_fullness;
+ Int max_BitVariance_num; /* the number of the maximum bit variance within the given buffer with the unit of 10% of bitrate/framerate*/
+ Int encoded_frames; /* counter for all encoded frames */
+ float framerate;
+ Int bitrate;
+ Int low_bound; /* bound for underflow detection, usually low_bound=-Bs/2, but could be changed in H.263 mode */
+ Int VBV_fullness_offset; /* offset of VBV_fullness, usually is zero, but can be changed in H.263 mode*/
+ /* End BX */
+
+} rateControl;
+
+
+#endif /* _RATE_CONTROL_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp
new file mode 100644
index 0000000..8d18f45
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad.cpp
@@ -0,0 +1,375 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+
+#include "sad_inline.h"
+
+#define Cached_lx 176
+
+#ifdef _SAD_STAT
+ULong num_sad_MB = 0;
+ULong num_sad_Blk = 0;
+ULong num_sad_MB_call = 0;
+ULong num_sad_Blk_call = 0;
+
+#define NUM_SAD_MB_CALL() num_sad_MB_call++
+#define NUM_SAD_MB() num_sad_MB++
+#define NUM_SAD_BLK_CALL() num_sad_Blk_call++
+#define NUM_SAD_BLK() num_sad_Blk++
+
+#else
+
+#define NUM_SAD_MB_CALL()
+#define NUM_SAD_MB()
+#define NUM_SAD_BLK_CALL()
+#define NUM_SAD_BLK()
+
+#endif
+
+
+/* consist of
+Int SAD_Macroblock_C(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_HTFM_Collect(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_HTFM(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_Block_C(UChar *ref,UChar *blk,Int dmin,Int lx,void *extra_info)
+Int SAD_Blk_PADDING(UChar *ref,UChar *cur,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_PADDING(UChar *ref,UChar *cur,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_PAD1(UChar *ref,UChar *cur,Int dmin,Int lx,Int *rep);
+Int SAD_MB_PADDING_HTFM_Collect(UChar *ref,UChar *cur,Int dmin,Int lx,void *extra_info)
+Int SAD_MB_PADDING_HTFM(UChar *ref,UChar *cur,Int dmin,Int lx,void *vptr)
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int SAD_MB_PAD1(UChar *ref, UChar *cur, Int dmin, Int lx, Int *rep);
+
+
+ /*==================================================================
+ Function: SAD_Macroblock
+ Date: 09/07/2000
+ Purpose: Compute SAD 16x16 between blk and ref.
+ To do: Uniform subsampling will be inserted later!
+ Hypothesis Testing Fast Matching to be used later!
+ Changes:
+ 11/7/00: implemented MMX
+ 1/24/01: implemented SSE
+ ==================================================================*/
+ /********** C ************/
+ Int SAD_Macroblock_C(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info)
+ {
+ int32 x10;
+ Int dmin = (ULong)dmin_lx >> 16;
+ Int lx = dmin_lx & 0xFFFF;
+
+ OSCL_UNUSED_ARG(extra_info);
+
+ NUM_SAD_MB_CALL();
+
+ x10 = simd_sad_mb(ref, blk, dmin, lx);
+
+ return x10;
+ }
+
+#ifdef HTFM /* HTFM with uniform subsampling implementation, 2/28/01 */
+ /*===============================================================
+ Function: SAD_MB_HTFM_Collect and SAD_MB_HTFM
+ Date: 3/2/1
+ Purpose: Compute the SAD on a 16x16 block using
+ uniform subsampling and hypothesis testing fast matching
+ for early dropout. SAD_MB_HP_HTFM_Collect is to collect
+ the statistics to compute the thresholds to be used in
+ SAD_MB_HP_HTFM.
+ Input/Output:
+ Changes:
+ ===============================================================*/
+
+ Int SAD_MB_HTFM_Collect(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info)
+ {
+ Int i;
+ Int sad = 0;
+ UChar *p1;
+ Int lx4 = (dmin_lx << 2) & 0x3FFFC;
+ ULong cur_word;
+ Int saddata[16], tmp, tmp2; /* used when collecting flag (global) is on */
+ Int difmad;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ Int *offsetRef = htfm_stat->offsetRef;
+
+ NUM_SAD_MB_CALL();
+
+ blk -= 4;
+ for (i = 0; i < 16; i++)
+ {
+ p1 = ref + offsetRef[i];
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ NUM_SAD_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if ((ULong)sad > ((ULong)dmin_lx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+
+ Int SAD_MB_HTFM(UChar *ref, UChar *blk, Int dmin_lx, void *extra_info)
+ {
+ Int sad = 0;
+ UChar *p1;
+
+ Int i;
+ Int tmp, tmp2;
+ Int lx4 = (dmin_lx << 2) & 0x3FFFC;
+ Int sadstar = 0, madstar;
+ Int *nrmlz_th = (Int*) extra_info;
+ Int *offsetRef = (Int*) extra_info + 32;
+ ULong cur_word;
+
+ madstar = (ULong)dmin_lx >> 20;
+
+ NUM_SAD_MB_CALL();
+
+ blk -= 4;
+ for (i = 0; i < 16; i++)
+ {
+ p1 = ref + offsetRef[i];
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = (cur_word >> 24) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[8];
+ tmp2 = (cur_word >> 16) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[4];
+ tmp2 = (cur_word >> 8) & 0xFF;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = p1[0];
+ p1 += lx4;
+ tmp2 = (cur_word & 0xFF);
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ NUM_SAD_MB();
+
+ sadstar += madstar;
+ if (((ULong)sad <= ((ULong)dmin_lx >> 16)) && (sad <= (sadstar - *nrmlz_th++)))
+ ;
+ else
+ return 65536;
+ }
+
+ return sad;
+ }
+#endif /* HTFM */
+
+#ifndef NO_INTER4V
+ /*==================================================================
+ Function: SAD_Block
+ Date: 09/07/2000
+ Purpose: Compute SAD 16x16 between blk and ref.
+ To do: Uniform subsampling will be inserted later!
+ Hypothesis Testing Fast Matching to be used later!
+ Changes:
+ 11/7/00: implemented MMX
+ 1/24/01: implemented SSE
+ ==================================================================*/
+ /********** C ************/
+ Int SAD_Block_C(UChar *ref, UChar *blk, Int dmin, Int lx, void *)
+ {
+ Int sad = 0;
+
+ Int i;
+ UChar *ii;
+ Int *kk;
+ Int tmp, tmp2, tmp3, mask = 0xFF;
+ Int width = (lx - 32);
+
+ NUM_SAD_BLK_CALL();
+
+ ii = ref;
+ kk = (Int*)blk; /* assuming word-align for blk */
+ for (i = 0; i < 8; i++)
+ {
+ tmp3 = kk[1];
+ tmp = ii[7];
+ tmp2 = (UInt)tmp3 >> 24;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = ii[6];
+ tmp2 = (tmp3 >> 16) & mask;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = ii[5];
+ tmp2 = (tmp3 >> 8) & mask;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = ii[4];
+ tmp2 = tmp3 & mask;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp3 = *kk;
+ kk += (width >> 2);
+ tmp = ii[3];
+ tmp2 = (UInt)tmp3 >> 24;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = ii[2];
+ tmp2 = (tmp3 >> 16) & mask;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = ii[1];
+ tmp2 = (tmp3 >> 8) & mask;
+ sad = SUB_SAD(sad, tmp, tmp2);
+ tmp = *ii;
+ ii += lx;
+ tmp2 = tmp3 & mask;
+ sad = SUB_SAD(sad, tmp, tmp2);
+
+ NUM_SAD_BLK();
+
+ if (sad > dmin)
+ return sad;
+ }
+
+ return sad;
+ }
+
+#endif /* NO_INTER4V */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp
new file mode 100644
index 0000000..f05697c
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel.cpp
@@ -0,0 +1,855 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/* contains
+Int HalfPel1_SAD_MB(UChar *ref,UChar *blk,Int dmin,Int width,Int ih,Int jh)
+Int HalfPel2_SAD_MB(UChar *ref,UChar *blk,Int dmin,Int width)
+Int HalfPel1_SAD_Blk(UChar *ref,UChar *blk,Int dmin,Int width,Int ih,Int jh)
+Int HalfPel2_SAD_Blk(UChar *ref,UChar *blk,Int dmin,Int width)
+
+Int SAD_MB_HalfPel_C(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+Int SAD_MB_HP_HTFM_Collect(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+Int SAD_MB_HP_HTFM(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+Int SAD_Blk_HalfPel_C(UChar *ref,UChar *blk,Int dmin,Int width,Int rx,Int xh,Int yh,void *extra_info)
+*/
+
+//#include <stdlib.h> /* for RAND_MAX */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "sad_halfpel_inline.h"
+
+#ifdef _SAD_STAT
+ULong num_sad_HP_MB = 0;
+ULong num_sad_HP_Blk = 0;
+ULong num_sad_HP_MB_call = 0;
+ULong num_sad_HP_Blk_call = 0;
+#define NUM_SAD_HP_MB_CALL() num_sad_HP_MB_call++
+#define NUM_SAD_HP_MB() num_sad_HP_MB++
+#define NUM_SAD_HP_BLK_CALL() num_sad_HP_Blk_call++
+#define NUM_SAD_HP_BLK() num_sad_HP_Blk++
+#else
+#define NUM_SAD_HP_MB_CALL()
+#define NUM_SAD_HP_MB()
+#define NUM_SAD_HP_BLK_CALL()
+#define NUM_SAD_HP_BLK()
+#endif
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /*==================================================================
+ Function: HalfPel1_SAD_MB
+ Date: 03/27/2001
+ Purpose: Compute SAD 16x16 between blk and ref in halfpel
+ resolution,
+ Changes:
+ ==================================================================*/
+ /* One component is half-pel */
+ Int HalfPel1_SAD_MB(UChar *ref, UChar *blk, Int dmin, Int width, Int ih, Int jh)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2;
+ Int temp;
+
+ OSCL_UNUSED_ARG(jh);
+
+ p1 = ref;
+ if (ih) p2 = ref + 1;
+ else p2 = ref + width;
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ if (sad > dmin)
+ return sad;
+ p1 += width;
+ p2 += width;
+ }
+ return sad;
+ }
+
+ /* Two components need half-pel */
+ Int HalfPel2_SAD_MB(UChar *ref, UChar *blk, Int dmin, Int width)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2, *p3, *p4;
+ Int temp;
+
+ p1 = ref;
+ p2 = ref + 1;
+ p3 = ref + width;
+ p4 = ref + width + 1;
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ if (sad > dmin)
+ return sad;
+
+ p1 += width;
+ p3 += width;
+ p2 += width;
+ p4 += width;
+ }
+ return sad;
+ }
+
+#ifndef NO_INTER4V
+ /*==================================================================
+ Function: HalfPel1_SAD_Blk
+ Date: 03/27/2001
+ Purpose: Compute SAD 8x8 between blk and ref in halfpel
+ resolution.
+ Changes:
+ ==================================================================*/
+ /* One component needs half-pel */
+ Int HalfPel1_SAD_Blk(UChar *ref, UChar *blk, Int dmin, Int width, Int ih, Int jh)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2;
+ Int temp;
+
+ OSCL_UNUSED_ARG(jh);
+
+ p1 = ref;
+ if (ih) p2 = ref + 1;
+ else p2 = ref + width;
+ kk = blk;
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ if (sad > dmin)
+ return sad;
+ p1 += width;
+ p2 += width;
+ kk += 8;
+ }
+ return sad;
+ }
+ /* Two components need half-pel */
+ Int HalfPel2_SAD_Blk(UChar *ref, UChar *blk, Int dmin, Int width)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2, *p3, *p4;
+ Int temp;
+
+ p1 = ref;
+ p2 = ref + 1;
+ p3 = ref + width;
+ p4 = ref + width + 1;
+ kk = blk;
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ if (sad > dmin)
+ return sad;
+
+ p1 += width;
+ p3 += width;
+ p2 += width;
+ p4 += width;
+ kk += 8;
+ }
+ return sad;
+ }
+#endif // NO_INTER4V
+ /*===============================================================
+ Function: SAD_MB_HalfPel
+ Date: 09/17/2000
+ Purpose: Compute the SAD on the half-pel resolution
+ Input/Output: hmem is assumed to be a pointer to the starting
+ point of the search in the 33x33 matrix search region
+ Changes:
+ 11/7/00: implemented MMX
+ ===============================================================*/
+ /*==================================================================
+ Function: SAD_MB_HalfPel_C
+ Date: 04/30/2001
+ Purpose: Compute SAD 16x16 between blk and ref in halfpel
+ resolution,
+ Changes:
+ ==================================================================*/
+ /* One component is half-pel */
+ Int SAD_MB_HalfPel_Cxhyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2, *p3, *p4;
+// Int sumref=0;
+ Int temp;
+ Int rx = dmin_rx & 0xFFFF;
+
+ OSCL_UNUSED_ARG(extra_info);
+
+ NUM_SAD_HP_MB_CALL();
+
+ p1 = ref;
+ p2 = ref + 1;
+ p3 = ref + rx;
+ p4 = ref + rx + 1;
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ NUM_SAD_HP_MB();
+
+ if (sad > (Int)((ULong)dmin_rx >> 16))
+ return sad;
+
+ p1 += rx;
+ p3 += rx;
+ p2 += rx;
+ p4 += rx;
+ }
+ return sad;
+ }
+
+ Int SAD_MB_HalfPel_Cyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2;
+// Int sumref=0;
+ Int temp;
+ Int rx = dmin_rx & 0xFFFF;
+
+ OSCL_UNUSED_ARG(extra_info);
+
+ NUM_SAD_HP_MB_CALL();
+
+ p1 = ref;
+ p2 = ref + rx; /* either left/right or top/bottom pixel */
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + 1) >> 1) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ NUM_SAD_HP_MB();
+
+ if (sad > (Int)((ULong)dmin_rx >> 16))
+ return sad;
+ p1 += rx;
+ p2 += rx;
+ }
+ return sad;
+ }
+
+ Int SAD_MB_HalfPel_Cxh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1;
+// Int sumref=0;
+ Int temp;
+ Int rx = dmin_rx & 0xFFFF;
+
+ OSCL_UNUSED_ARG(extra_info);
+
+ NUM_SAD_HP_MB_CALL();
+
+ p1 = ref;
+ kk = blk;
+
+ for (i = 0; i < 16; i++)
+ {
+ for (j = 0; j < 16; j++)
+ {
+
+ temp = ((p1[j] + p1[j+1] + 1) >> 1) - *kk++;
+ sad += PV_ABS(temp);
+ }
+
+ NUM_SAD_HP_MB();
+
+ if (sad > (Int)((ULong)dmin_rx >> 16))
+ return sad;
+ p1 += rx;
+ }
+ return sad;
+ }
+
+#ifdef HTFM /* HTFM with uniform subsampling implementation, 2/28/01 */
+
+//Checheck here
+ Int SAD_MB_HP_HTFM_Collectxhyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *p1, *p2;
+ Int rx = dmin_rx & 0xFFFF;
+ Int refwx4 = rx << 2;
+ Int saddata[16]; /* used when collecting flag (global) is on */
+ Int difmad, tmp, tmp2;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ Int *offsetRef = htfm_stat->offsetRef;
+ ULong cur_word;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+
+ j = 4;/* 4 lines */
+ do
+ {
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12] + p2[12];
+ tmp2 = p1[13] + p2[13];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 24) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8] + p2[8];
+ tmp2 = p1[9] + p2[9];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 16) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4] + p2[4];
+ tmp2 = p1[5] + p2[5];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 8) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp2 = p1[1] + p2[1];
+ tmp = p1[0] + p2[0];
+ p1 += refwx4;
+ p2 += refwx4;
+ tmp += tmp2;
+ tmp2 = (cur_word & 0xFF);
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if (sad > (Int)((ULong)dmin_rx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+
+ return sad;
+ }
+
+ Int SAD_MB_HP_HTFM_Collectyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *p1, *p2;
+ Int rx = dmin_rx & 0xFFFF;
+ Int refwx4 = rx << 2;
+ Int saddata[16]; /* used when collecting flag (global) is on */
+ Int difmad, tmp, tmp2;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ Int *offsetRef = htfm_stat->offsetRef;
+ ULong cur_word;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+ j = 4;
+ do
+ {
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p2[12];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p2[8];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p2[4];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ p1 += refwx4;
+ tmp2 = p2[0];
+ p2 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if (sad > (Int)((ULong)dmin_rx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+
+ return sad;
+ }
+
+ Int SAD_MB_HP_HTFM_Collectxh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *p1;
+ Int rx = dmin_rx & 0xFFFF;
+ Int refwx4 = rx << 2;
+ Int saddata[16]; /* used when collecting flag (global) is on */
+ Int difmad, tmp, tmp2;
+ HTFM_Stat *htfm_stat = (HTFM_Stat*) extra_info;
+ Int *abs_dif_mad_avg = &(htfm_stat->abs_dif_mad_avg);
+ UInt *countbreak = &(htfm_stat->countbreak);
+ Int *offsetRef = htfm_stat->offsetRef;
+ ULong cur_word;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+
+ j = 4; /* 4 lines */
+ do
+ {
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p1[13];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p1[9];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p1[5];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ tmp2 = p1[1];
+ p1 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ saddata[i] = sad;
+
+ if (i > 0)
+ {
+ if (sad > (Int)((ULong)dmin_rx >> 16))
+ {
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+ return sad;
+ }
+ }
+ }
+ difmad = saddata[0] - ((saddata[1] + 1) >> 1);
+ (*abs_dif_mad_avg) += ((difmad > 0) ? difmad : -difmad);
+ (*countbreak)++;
+
+ return sad;
+ }
+
+ Int SAD_MB_HP_HTFMxhyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0, tmp, tmp2;
+ UChar *p1, *p2;
+ Int rx = dmin_rx & 0xFFFF;
+ Int refwx4 = rx << 2;
+ Int sadstar = 0, madstar;
+ Int *nrmlz_th = (Int*) extra_info;
+ Int *offsetRef = nrmlz_th + 32;
+ ULong cur_word;
+
+ madstar = (ULong)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+
+ j = 4; /* 4 lines */
+ do
+ {
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12] + p2[12];
+ tmp2 = p1[13] + p2[13];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 24) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8] + p2[8];
+ tmp2 = p1[9] + p2[9];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 16) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4] + p2[4];
+ tmp2 = p1[5] + p2[5];
+ tmp += tmp2;
+ tmp2 = (cur_word >> 8) & 0xFF;
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ tmp2 = p1[1] + p2[1];
+ tmp = p1[0] + p2[0];
+ p1 += refwx4;
+ p2 += refwx4;
+ tmp += tmp2;
+ tmp2 = (cur_word & 0xFF);
+ tmp += 2;
+ sad = INTERP2_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ sadstar += madstar;
+ if (sad > sadstar - nrmlz_th[i] || sad > (Int)((ULong)dmin_rx >> 16))
+ {
+ return 65536;
+ }
+ }
+
+ return sad;
+ }
+
+ Int SAD_MB_HP_HTFMyh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0, tmp, tmp2;
+ UChar *p1, *p2;
+ Int rx = dmin_rx & 0xFFFF;
+ Int refwx4 = rx << 2;
+ Int sadstar = 0, madstar;
+ Int *nrmlz_th = (Int*) extra_info;
+ Int *offsetRef = nrmlz_th + 32;
+ ULong cur_word;
+
+ madstar = (ULong)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+ p2 = p1 + rx;
+ j = 4;
+ do
+ {
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p2[12];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p2[8];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p2[4];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ p1 += refwx4;
+ tmp2 = p2[0];
+ p2 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+ sadstar += madstar;
+ if (sad > sadstar - nrmlz_th[i] || sad > (Int)((ULong)dmin_rx >> 16))
+ {
+ return 65536;
+ }
+ }
+
+ return sad;
+ }
+
+ Int SAD_MB_HP_HTFMxh(UChar *ref, UChar *blk, Int dmin_rx, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0, tmp, tmp2;
+ UChar *p1;
+ Int rx = dmin_rx & 0xFFFF;
+ Int refwx4 = rx << 2;
+ Int sadstar = 0, madstar;
+ Int *nrmlz_th = (Int*) extra_info;
+ Int *offsetRef = nrmlz_th + 32;
+ ULong cur_word;
+
+ madstar = (ULong)dmin_rx >> 20;
+
+ NUM_SAD_HP_MB_CALL();
+
+ blk -= 4;
+
+ for (i = 0; i < 16; i++) /* 16 stages */
+ {
+ p1 = ref + offsetRef[i];
+
+ j = 4;/* 4 lines */
+ do
+ {
+ cur_word = *((ULong*)(blk += 4));
+ tmp = p1[12];
+ tmp2 = p1[13];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 24) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[8];
+ tmp2 = p1[9];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 16) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[4];
+ tmp2 = p1[5];
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word >> 8) & 0xFF;
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ tmp = p1[0];
+ tmp2 = p1[1];
+ p1 += refwx4;
+ tmp++;
+ tmp2 += tmp;
+ tmp = (cur_word & 0xFF);
+ sad = INTERP1_SUB_SAD(sad, tmp, tmp2);;
+ }
+ while (--j);
+
+ NUM_SAD_HP_MB();
+
+ sadstar += madstar;
+ if (sad > sadstar - nrmlz_th[i] || sad > (Int)((ULong)dmin_rx >> 16))
+ {
+ return 65536;
+ }
+ }
+
+ return sad;
+ }
+
+#endif /* HTFM */
+
+#ifndef NO_INTER4V
+ /*==================================================================
+ Function: SAD_Blk_HalfPel_C
+ Date: 04/30/2001
+ Purpose: Compute SAD 16x16 between blk and ref in halfpel
+ resolution,
+ Changes:
+ ==================================================================*/
+ /* One component is half-pel */
+ Int SAD_Blk_HalfPel_C(UChar *ref, UChar *blk, Int dmin, Int width, Int rx, Int xh, Int yh, void *extra_info)
+ {
+ Int i, j;
+ Int sad = 0;
+ UChar *kk, *p1, *p2, *p3, *p4;
+ Int temp;
+
+ OSCL_UNUSED_ARG(extra_info);
+
+ NUM_SAD_HP_BLK_CALL();
+
+ if (xh && yh)
+ {
+ p1 = ref;
+ p2 = ref + xh;
+ p3 = ref + yh * rx;
+ p4 = ref + yh * rx + xh;
+ kk = blk;
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + p3[j] + p4[j] + 2) >> 2) - kk[j];
+ sad += PV_ABS(temp);
+ }
+
+ NUM_SAD_HP_BLK();
+
+ if (sad > dmin)
+ return sad;
+
+ p1 += rx;
+ p3 += rx;
+ p2 += rx;
+ p4 += rx;
+ kk += width;
+ }
+ return sad;
+ }
+ else
+ {
+ p1 = ref;
+ p2 = ref + xh + yh * rx; /* either left/right or top/bottom pixel */
+
+ kk = blk;
+
+ for (i = 0; i < 8; i++)
+ {
+ for (j = 0; j < 8; j++)
+ {
+
+ temp = ((p1[j] + p2[j] + 1) >> 1) - kk[j];
+ sad += PV_ABS(temp);
+ }
+
+ NUM_SAD_HP_BLK();
+
+ if (sad > dmin)
+ return sad;
+ p1 += rx;
+ p2 += rx;
+ kk += width;
+ }
+ return sad;
+ }
+ }
+#endif /* NO_INTER4V */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
new file mode 100644
index 0000000..d55778f
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
@@ -0,0 +1,130 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/* Filename: sad_halfpel_inline.h */
+/* Description: Implementation for in-line functions used in dct.cpp */
+/* Modified: */
+/*********************************************************************************/
+
+#ifndef _SAD_HALFPEL_INLINE_H_
+#define _SAD_HALFPEL_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER */
+
+ __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ tmp = (tmp2 >> 1) - tmp;
+ if (tmp > 0) sad += tmp;
+ else sad -= tmp;
+
+ return sad;
+ }
+
+ __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ tmp = (tmp >> 2) - tmp2;
+ if (tmp > 0) sad += tmp;
+ else sad -= tmp;
+
+ return sad;
+ }
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+ __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ __asm
+ {
+ rsbs tmp, tmp, tmp2, asr #1 ;
+ rsbmi tmp, tmp, #0 ;
+ add sad, sad, tmp ;
+ }
+
+ return sad;
+ }
+
+ __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ __asm
+ {
+ rsbs tmp, tmp2, tmp, asr #2 ;
+ rsbmi tmp, tmp, #0 ;
+ add sad, sad, tmp ;
+ }
+
+ return sad;
+ }
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER */
+
+
+ __inline int32 INTERP1_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ register int32 out;
+ register int32 temp1;
+ register int32 ss = sad;
+ register int32 tt = tmp;
+ register int32 uu = tmp2;
+
+ asm volatile("rsbs %1, %3, %4, asr #1\n\t"
+ "rsbmi %1, %1, #0\n\t"
+ "add %0, %2, %1"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(ss),
+ "r"(tt),
+ "r"(uu));
+ return out;
+ }
+
+
+ __inline int32 INTERP2_SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 ss = sad;
+ register int32 tt = tmp;
+ register int32 uu = tmp2;
+
+ asm volatile("rsbs %1, %4, %3, asr #2\n\t"
+ "rsbmi %1, %1, #0\n\t"
+ "add %0, %2, %1"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(ss),
+ "r"(tt),
+ "r"(uu));
+ return out;
+ }
+
+
+#endif // Diff OS
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //_SAD_HALFPEL_INLINE_H_
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h
new file mode 100644
index 0000000..ba77dfd
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_inline.h
@@ -0,0 +1,539 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/* Filename: sad_inline.h */
+/* Description: Implementation for in-line functions used in dct.cpp */
+/* Modified: */
+/*********************************************************************************/
+#ifndef _SAD_INLINE_H_
+#define _SAD_INLINE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4) /* ARM GNU COMPILER */
+
+ __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ tmp = tmp - tmp2;
+ if (tmp > 0) sad += tmp;
+ else sad -= tmp;
+
+ return sad;
+ }
+
+ __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+ x7 = src2 ^ src1; /* check odd/even combination */
+ if ((uint32)src2 >= (uint32)src1)
+ {
+ src1 = src2 - src1; /* subs */
+ }
+ else
+ {
+ src1 = src1 - src2;
+ }
+ x7 = x7 ^ src1; /* only odd bytes need to add carry */
+ x7 = mask & ((uint32)x7 >> 1);
+ x7 = (x7 << 8) - x7;
+ src1 = src1 + (x7 >> 7); /* add 0xFF to the negative byte, add back carry */
+ src1 = src1 ^(x7 >> 7); /* take absolute value of negative byte */
+
+ return src1;
+ }
+
+#define NUMBER 3
+#define SHIFT 24
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#include "sad_mb_offset.h"
+
+
+ __inline int32 simd_sad_mb(UChar *ref, UChar *blk, Int dmin, Int lx)
+ {
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+
+ x8 = (uint32)ref & 0x3;
+ if (x8 == 3)
+ goto SadMBOffset3;
+ if (x8 == 2)
+ goto SadMBOffset2;
+ if (x8 == 1)
+ goto SadMBOffset1;
+
+// x5 = (x4<<8)-x4; /* x5 = x4*255; */
+ x4 = x5 = 0;
+
+ x6 = 0xFFFF00FF;
+
+ ref -= lx;
+ blk -= 16;
+
+ x8 = 16;
+
+LOOP_SAD0:
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref += lx));
+ x11 = *((uint32*)(ref + 4));
+ x12 = *((uint32*)(blk += 16));
+ x14 = *((uint32*)(blk + 4));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref + 8));
+ x11 = *((uint32*)(ref + 12));
+ x12 = *((uint32*)(blk + 8));
+ x14 = *((uint32*)(blk + 12));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+ goto LOOP_SAD0;
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+ return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+ return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+ return sad_mb_offset1(ref, blk, lx, dmin);
+
+ }
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+ __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ __asm
+ {
+ rsbs tmp, tmp, tmp2 ;
+ rsbmi tmp, tmp, #0 ;
+ add sad, sad, tmp ;
+ }
+
+ return sad;
+ }
+
+ __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+ __asm
+ {
+ EOR x7, src2, src1; /* check odd/even combination */
+ SUBS src1, src2, src1;
+ EOR x7, x7, src1;
+ AND x7, mask, x7, lsr #1;
+ ORRCC x7, x7, #0x80000000;
+ RSB x7, x7, x7, lsl #8;
+ ADD src1, src1, x7, asr #7; /* add 0xFF to the negative byte, add back carry */
+ EOR src1, src1, x7, asr #7; /* take absolute value of negative byte */
+ }
+
+ return src1;
+ }
+
+ __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+ {
+ int32 x7;
+
+ __asm
+ {
+ EOR x7, src2, src1; /* check odd/even combination */
+ ADDS src1, src2, src1;
+ EOR x7, x7, src1; /* only odd bytes need to add carry */
+ ANDS x7, mask, x7, rrx;
+ RSB x7, x7, x7, lsl #8;
+ SUB src1, src1, x7, asr #7; /* add 0xFF to the negative byte, add back carry */
+ EOR src1, src1, x7, asr #7; /* take absolute value of negative byte */
+ }
+
+ return src1;
+ }
+
+#define sum_accumulate __asm{ SBC x5, x5, x10; /* accumulate low bytes */ \
+ BIC x10, x6, x10; /* x10 & 0xFF00FF00 */ \
+ ADD x4, x4, x10,lsr #8; /* accumulate high bytes */ \
+ SBC x5, x5, x11; /* accumulate low bytes */ \
+ BIC x11, x6, x11; /* x11 & 0xFF00FF00 */ \
+ ADD x4, x4, x11,lsr #8; } /* accumulate high bytes */
+
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+ __inline int32 simd_sad_mb(UChar *ref, UChar *blk, Int dmin, Int lx)
+ {
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+
+ __asm
+ {
+ MOVS x8, ref, lsl #31 ;
+ BHI SadMBOffset3;
+ BCS SadMBOffset2;
+ BMI SadMBOffset1;
+
+ MVN x6, #0xFF00;
+ }
+LOOP_SAD0:
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+ x12 = *((int32*)(blk + 8));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ __asm
+ {
+ /****** process 8 pixels ******/
+ LDR x11, [ref, #4];
+ LDR x10, [ref], lx ;
+ LDR x14, [blk, #4];
+ LDR x12, [blk], #16 ;
+ }
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ __asm
+ {
+ /****************/
+ RSBS x11, dmin, x10, lsr #16;
+ ADDLSS x8, x8, #0x10000001;
+ BLS LOOP_SAD0;
+ }
+
+ return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+ return sad_mb_offset3(ref, blk, lx, dmin, x8);
+
+SadMBOffset2:
+
+ return sad_mb_offset2(ref, blk, lx, dmin, x8);
+
+SadMBOffset1:
+
+ return sad_mb_offset1(ref, blk, lx, dmin, x8);
+ }
+
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER */
+
+ __inline int32 SUB_SAD(int32 sad, int32 tmp, int32 tmp2)
+ {
+ register int32 out;
+ register int32 temp1;
+ register int32 ss = sad;
+ register int32 tt = tmp;
+ register int32 uu = tmp2;
+
+ asm volatile("rsbs %1, %4, %3\n\t"
+ "rsbmi %1, %1, #0\n\t"
+ "add %0, %2, %1"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(ss),
+ "r"(tt),
+ "r"(uu));
+ return out;
+ }
+
+ __inline int32 sad_4pixel(int32 src1, int32 src2, int32 mask)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 s1 = src1;
+ register int32 s2 = src2;
+ register int32 mm = mask;
+
+ asm volatile("eor %0, %3, %2\n\t"
+ "subs %1, %3, %2\n\t"
+ "eor %0, %0, %1\n\t"
+ "and %0, %4, %0, lsr #1\n\t"
+ "orrcc %0, %0, #0x80000000\n\t"
+ "rsb %0, %0, %0, lsl #8\n\t"
+ "add %1, %1, %0, asr #7\n\t"
+ "eor %1, %1, %0, asr #7"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(s1),
+ "r"(s2),
+ "r"(mm));
+
+ return temp1;
+ }
+
+ __inline int32 sad_4pixelN(int32 src1, int32 src2, int32 mask)
+{
+ register int32 out;
+ register int32 temp1;
+ register int32 s1 = src1;
+ register int32 s2 = src2;
+ register int32 mm = mask;
+
+ asm volatile("eor %1, %3, %2\n\t"
+ "adds %0, %3, %2\n\t"
+ "eor %1, %1, %0\n\t"
+ "ands %1, %4, %1,rrx\n\t"
+ "rsb %1, %1, %1, lsl #8\n\t"
+ "sub %0, %0, %1, asr #7\n\t"
+ "eor %0, %0, %1, asr #7"
+ : "=&r"(out),
+ "=&r"(temp1)
+ : "r"(s1),
+ "r"(s2),
+ "r"(mm));
+
+ return (out);
+ }
+
+#define sum_accumulate asm volatile("sbc %0, %0, %1\n\t" \
+ "bic %1, %4, %1\n\t" \
+ "add %2, %2, %1, lsr #8\n\t" \
+ "sbc %0, %0, %3\n\t" \
+ "bic %3, %4, %3\n\t" \
+ "add %2, %2, %3, lsr #8" \
+ :"+r"(x5), "+r"(x10), "+r"(x4), "+r"(x11) \
+ :"r"(x6));
+
+#define NUMBER 3
+#define SHIFT 24
+#define INC_X8 0x08000001
+
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 2
+#undef SHIFT
+#define SHIFT 16
+#undef INC_X8
+#define INC_X8 0x10000001
+#include "sad_mb_offset.h"
+
+#undef NUMBER
+#define NUMBER 1
+#undef SHIFT
+#define SHIFT 8
+#undef INC_X8
+#define INC_X8 0x08000001
+#include "sad_mb_offset.h"
+
+
+ __inline int32 simd_sad_mb(UChar *ref, UChar *blk, Int dmin, Int lx)
+{
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+
+ x8 = (uint32)ref & 0x3;
+ if (x8 == 3)
+ goto SadMBOffset3;
+ if (x8 == 2)
+ goto SadMBOffset2;
+ if (x8 == 1)
+ goto SadMBOffset1;
+
+asm volatile("mvn %0, #0xFF00": "=r"(x6));
+
+LOOP_SAD0:
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+ x12 = *((int32*)(blk + 8));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ asm volatile("ldr %0, [%4, #4]\n\t"
+ "ldr %1, [%4], %6\n\t"
+ "ldr %2, [%5, #4]\n\t"
+ "ldr %3, [%5], #16"
+ : "=r"(x11), "=r"(x10), "=r"(x14), "=r"(x12), "+r"(ref), "+r"(blk)
+ : "r"(lx));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+ goto LOOP_SAD0;
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+
+SadMBOffset3:
+
+ return sad_mb_offset3(ref, blk, lx, dmin);
+
+SadMBOffset2:
+
+ return sad_mb_offset2(ref, blk, lx, dmin);
+
+SadMBOffset1:
+
+ return sad_mb_offset1(ref, blk, lx, dmin);
+ }
+
+#endif // OS
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _SAD_INLINE_H_
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h b/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h
new file mode 100644
index 0000000..4c7b929
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/sad_mb_offset.h
@@ -0,0 +1,317 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/*********************************************************************************/
+/* Filename: sad_mb_offset.h */
+/* Description: Implementation for in-line functions used in dct.cpp */
+/* Modified: */
+/*********************************************************************************/
+
+#if !defined(PV_ARM_GCC_V4) && !defined(PV_ARM_GCC_V5) /* ARM GNU COMPILER */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(UChar *ref, UChar *blk, Int lx, Int dmin)
+#endif
+{
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ // x5 = (x4<<8) - x4;
+ x4 = x5 = 0;
+ x6 = 0xFFFF00FF;
+ x9 = 0x80808080; /* const. */
+ ref -= NUMBER; /* bic ref, ref, #3 */
+ ref -= lx;
+ blk -= 16;
+ x8 = 16;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref += lx)); /* D C B A */
+ x11 = *((uint32*)(ref + 4)); /* H G F E */
+ x12 = *((uint32*)(ref + 8)); /* L K J I */
+
+ x10 = ((uint32)x10 >> SHIFT); /* 0 0 0 D */
+ x10 = x10 | (x11 << (32 - SHIFT)); /* G F E D */
+ x11 = ((uint32)x11 >> SHIFT); /* 0 0 0 H */
+ x11 = x11 | (x12 << (32 - SHIFT)); /* K J I H */
+
+ x12 = *((uint32*)(blk += 16));
+ x14 = *((uint32*)(blk + 4));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref + 8)); /* D C B A */
+ x11 = *((uint32*)(ref + 12)); /* H G F E */
+ x12 = *((uint32*)(ref + 16)); /* L K J I */
+
+ x10 = ((uint32)x10 >> SHIFT); /* mvn x10, x10, lsr #24 = 0xFF 0xFF 0xFF ~D */
+ x10 = x10 | (x11 << (32 - SHIFT)); /* bic x10, x10, x11, lsl #8 = ~G ~F ~E ~D */
+ x11 = ((uint32)x11 >> SHIFT); /* 0xFF 0xFF 0xFF ~H */
+ x11 = x11 | (x12 << (32 - SHIFT)); /* ~K ~J ~I ~H */
+
+ x12 = *((uint32*)(blk + 8));
+ x14 = *((uint32*)(blk + 12));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ x5 = x5 + x10; /* accumulate low bytes */
+ x10 = x10 & (x6 << 8); /* x10 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x10 >> 8); /* accumulate high bytes */
+ x5 = x5 + x11; /* accumulate low bytes */
+ x11 = x11 & (x6 << 8); /* x11 & 0xFF00FF00 */
+ x4 = x4 + ((uint32)x11 >> 8); /* accumulate high bytes */
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+#if (NUMBER==3)
+ goto LOOP_SAD3;
+#elif (NUMBER==2)
+ goto LOOP_SAD2;
+#elif (NUMBER==1)
+ goto LOOP_SAD1;
+#endif
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+}
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(UChar *ref, UChar *blk, Int lx, Int dmin, int32 x8)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(UChar *ref, UChar *blk, Int lx, Int dmin, int32 x8)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(UChar *ref, UChar *blk, Int lx, Int dmin, int32 x8)
+#endif
+{
+ int32 x4, x5, x6, x9, x10, x11, x12, x14;
+
+ x9 = 0x80808080; /* const. */
+ x4 = x5 = 0;
+
+ __asm{
+ MVN x6, #0xff0000;
+ BIC ref, ref, #3;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+ }
+ /****** process 8 pixels ******/
+ x11 = *((int32*)(ref + 12));
+ x12 = *((int32*)(ref + 16));
+ x10 = *((int32*)(ref + 8));
+ x14 = *((int32*)(blk + 12));
+
+ __asm{
+ MVN x10, x10, lsr #SHIFT;
+ BIC x10, x10, x11, lsl #(32-SHIFT);
+ MVN x11, x11, lsr #SHIFT;
+ BIC x11, x11, x12, lsl #(32-SHIFT);
+
+ LDR x12, [blk, #8];
+ }
+
+ /* process x11 & x14 */
+ x11 = sad_4pixelN(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixelN(x10, x12, x9);
+
+ sum_accumulate;
+
+ __asm{
+ /****** process 8 pixels ******/
+ LDR x11, [ref, #4];
+ LDR x12, [ref, #8];
+ LDR x10, [ref], lx ;
+ LDR x14, [blk, #4];
+
+ MVN x10, x10, lsr #SHIFT;
+ BIC x10, x10, x11, lsl #(32-SHIFT);
+ MVN x11, x11, lsr #SHIFT;
+ BIC x11, x11, x12, lsl #(32-SHIFT);
+
+ LDR x12, [blk], #16;
+ }
+
+ /* process x11 & x14 */
+ x11 = sad_4pixelN(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixelN(x10, x12, x9);
+
+ sum_accumulate;
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ __asm{
+ RSBS x11, dmin, x10, lsr #16
+ ADDLSS x8, x8, #INC_X8
+#if (NUMBER==3)
+ BLS LOOP_SAD3;
+#elif (NUMBER==2)
+BLS LOOP_SAD2;
+#elif (NUMBER==1)
+BLS LOOP_SAD1;
+#endif
+ }
+
+ return ((uint32)x10 >> 16);
+}
+
+#elif ( defined(PV_ARM_GCC_V5) || defined(PV_ARM_GCC_V4) ) /* ARM GNU COMPILER */
+
+#if (NUMBER==3)
+__inline int32 sad_mb_offset3(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==2)
+__inline int32 sad_mb_offset2(UChar *ref, UChar *blk, Int lx, Int dmin)
+#elif (NUMBER==1)
+__inline int32 sad_mb_offset1(UChar *ref, UChar *blk, Int lx, Int dmin)
+#endif
+{
+ int32 x4, x5, x6, x8, x9, x10, x11, x12, x14;
+
+ // x5 = (x4<<8) - x4;
+ x4 = x5 = 0;
+ x6 = 0xFFFF00FF;
+ x9 = 0x80808080; /* const. */
+ ref -= NUMBER; /* bic ref, ref, #3 */
+ ref -= lx;
+ x8 = 16;
+
+#if (NUMBER==3)
+LOOP_SAD3:
+#elif (NUMBER==2)
+LOOP_SAD2:
+#elif (NUMBER==1)
+LOOP_SAD1:
+#endif
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref += lx)); /* D C B A */
+ x11 = *((uint32*)(ref + 4)); /* H G F E */
+ x12 = *((uint32*)(ref + 8)); /* L K J I */
+
+ int32 shift = SHIFT;
+ int32 shift2 = 32 - SHIFT;
+ asm volatile("ldr %3, [%4, #4]\n\t"
+ "mvn %0, %0, lsr %5\n\t"
+ "bic %0, %0, %1, lsl %6\n\t"
+ "mvn %1, %1, lsr %5\n\t"
+ "bic %1, %1, %2, lsl %6\n\t"
+ "ldr %2, [%4, #8]"
+ : "+r"(x10), "+r"(x11), "+r"(x12), "=r"(x14)
+ : "r"(blk), "r"(shift), "r"(shift2));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ sum_accumulate;
+
+ /****** process 8 pixels ******/
+ x10 = *((uint32*)(ref + 8)); /* D C B A */
+ x11 = *((uint32*)(ref + 12)); /* H G F E */
+ x12 = *((uint32*)(ref + 16)); /* L K J I */
+
+ asm volatile("ldr %3, [%4, #4]\n\t"
+ "mvn %0, %0, lsr %5\n\t"
+ "bic %0, %0, %1, lsl %6\n\t"
+ "mvn %1, %1, lsr %5\n\t"
+ "bic %1, %1, %2, lsl %6\n\t"
+ "ldr %2, [%4, #8]"
+ : "+r"(x10), "+r"(x11), "+r"(x12), "=r"(x14)
+ : "r"(blk), "r"(shift), "r"(shift2));
+
+ /* process x11 & x14 */
+ x11 = sad_4pixel(x11, x14, x9);
+
+ /* process x12 & x10 */
+ x10 = sad_4pixel(x10, x12, x9);
+
+ sum_accumulate;
+
+ /****************/
+ x10 = x5 - (x4 << 8); /* extract low bytes */
+ x10 = x10 + x4; /* add with high bytes */
+ x10 = x10 + (x10 << 16); /* add with lower half word */
+
+ if (((uint32)x10 >> 16) <= (uint32)dmin) /* compare with dmin */
+ {
+ if (--x8)
+ {
+#if (NUMBER==3)
+ goto LOOP_SAD3;
+#elif (NUMBER==2)
+goto LOOP_SAD2;
+#elif (NUMBER==1)
+goto LOOP_SAD1;
+#endif
+ }
+
+ }
+
+ return ((uint32)x10 >> 16);
+}
+
+#endif
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h
new file mode 100644
index 0000000..79d62e4
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_enc_tab.h
@@ -0,0 +1,1146 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/******************************************************************************
+ *
+ * This software module was originally developed by
+ *
+ * Robert Danielsen (Telenor / ACTS-MoMuSys).
+ *
+ * and edited by
+ *
+ * Minhua Zhou (HHI / ACTS-MoMuSys).
+ * Luis Ducla-Soares (IST / ACTS-MoMuSys).
+ *
+ * in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
+ * This software module is an implementation of a part of one or more MPEG-4
+ * Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
+ * 14496-2) standard.
+ *
+ * ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
+ * license to this software module or modifications thereof for use in hardware
+ * or software products claiming conformance to the MPEG-4 Video (ISO/IEC
+ * 14496-2) standard.
+ *
+ * Those intending to use this software module in hardware or software products
+ * are advised that its use may infringe existing patents. The original
+ * developer of this software module and his/her company, the subsequent
+ * editors and their companies, and ISO/IEC have no liability for use of this
+ * software module or modifications thereof in an implementation. Copyright is
+ * not released for non MPEG-4 Video (ISO/IEC 14496-2) standard conforming
+ * products.
+ *
+ * ACTS-MoMuSys partners retain full right to use the code for his/her own
+ * purpose, assign or donate the code to a third party and to inhibit third
+ * parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) standard
+ * conforming products. This copyright notice must be included in all copies or
+ * derivative works.
+ *
+ * Copyright (c) 1997
+ *
+ *****************************************************************************/
+
+
+/***********************************************************HeaderBegin*******
+ *
+ * File: vlc.h
+ *
+ * Author: Robert Danielsen
+ * Created: 07.06.96
+ *
+ * Description: vlc tables for encoder
+ *
+ * Notes: Idea taken from MPEG-2 software simulation group
+ *
+ * Modified:
+ * 28.10.96 Robert Danielsen: Added tables for Intra luminance
+ * coefficients
+ * 01.05.97 Luis Ducla-Soares: added VM7.0 Reversible VLC tables (RVLC).
+ * 13.05.97 Minhua Zhou: added cbpy_tab3,cbpy_tab2
+ *
+ ***********************************************************HeaderEnd*********/
+
+/************************ INCLUDE FILES ********************************/
+
+#ifndef _VLC_ENC_TAB_H_
+#define _VLC_ENC_TAB_H_
+
+
+#include "mp4def.h"
+/* type definitions for variable length code table entries */
+
+
+
+static const Int intra_max_level[2][64] =
+{
+ {27, 10, 5, 4, 3, 3, 3, 3,
+ 2, 2, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ },
+
+ {8, 3, 2, 2, 2, 2, 2, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ }
+};
+
+
+static const Int inter_max_level[2][64] =
+{
+ {12, 6, 4, 3, 3, 3, 3, 2,
+ 2, 2, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0},
+
+ {3, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+
+static const Int intra_max_run0[28] = { 999, 14, 9, 7, 3, 2, 1,
+ 1, 1, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+ };
+
+
+static const Int intra_max_run1[9] = { 999, 20, 6,
+ 1, 0, 0,
+ 0, 0, 0
+ };
+
+static const Int inter_max_run0[13] = { 999,
+ 26, 10, 6, 2, 1, 1,
+ 0, 0, 0, 0, 0, 0
+ };
+
+
+static const Int inter_max_run1[4] = { 999, 40, 1, 0 };
+
+
+
+/* DC prediction sizes */
+
+static const VLCtable DCtab_lum[13] =
+{
+ {3, 3}, {3, 2}, {2, 2}, {2, 3}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7},
+ {1, 8}, {1, 9}, {1, 10}, {1, 11}
+};
+
+static const VLCtable DCtab_chrom[13] =
+{
+ {3, 2}, {2, 2}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8},
+ {1, 9}, {1, 10}, {1, 11}, {1, 12}
+};
+
+/* Motion vectors */
+
+static const VLCtable mvtab[33] =
+{
+ {1, 1}, {1, 2}, {1, 3}, {1, 4}, {3, 6}, {5, 7}, {4, 7}, {3, 7},
+ {11, 9}, {10, 9}, {9, 9}, {17, 10}, {16, 10}, {15, 10}, {14, 10}, {13, 10},
+ {12, 10}, {11, 10}, {10, 10}, {9, 10}, {8, 10}, {7, 10}, {6, 10}, {5, 10},
+ {4, 10}, {7, 11}, {6, 11}, {5, 11}, {4, 11}, {3, 11}, {2, 11}, {3, 12},
+ {2, 12}
+};
+
+
+/* MCBPC Indexing by cbpc in first two bits, mode in last two.
+ CBPC as in table 4/H.263, MB type (mode): 3 = 01, 4 = 10.
+ Example: cbpc = 01 and mode = 4 gives index = 0110 = 6. */
+
+static const VLCtable mcbpc_intra_tab[15] =
+{
+ {0x01, 9}, {0x01, 1}, {0x01, 4}, {0x00, 0},
+ {0x00, 0}, {0x01, 3}, {0x01, 6}, {0x00, 0},
+ {0x00, 0}, {0x02, 3}, {0x02, 6}, {0x00, 0},
+ {0x00, 0}, {0x03, 3}, {0x03, 6}
+};
+
+
+/* MCBPC inter.
+ Addressing: 5 bit ccmmm (cc = CBPC, mmm = mode (1-4 binary)) */
+
+static const VLCtable mcbpc_inter_tab[29] =
+{
+ {1, 1}, {3, 3}, {2, 3}, {3, 5}, {4, 6}, {1, 9}, {0, 0}, {0, 0},
+ {3, 4}, {7, 7}, {5, 7}, {4, 8}, {4, 9}, {0, 0}, {0, 0}, {0, 0},
+ {2, 4}, {6, 7}, {4, 7}, {3, 8}, {3, 9}, {0, 0}, {0, 0}, {0, 0},
+ {5, 6}, {5, 9}, {5, 8}, {3, 7}, {2, 9}
+};
+
+
+
+/* CBPY. Straightforward indexing */
+
+static const VLCtable cbpy_tab[16] =
+{
+ {3, 4}, {5, 5}, {4, 5}, {9, 4}, {3, 5}, {7, 4}, {2, 6}, {11, 4},
+ {2, 5}, {3, 6}, {5, 4}, {10, 4}, {4, 4}, {8, 4}, {6, 4}, {3, 2}
+};
+
+static const VLCtable cbpy_tab3[8] =
+{
+ {3, 3}, {1, 6}, {1, 5}, {2, 3}, {2, 5}, {3, 5}, {1, 3}, {1, 1}
+};
+static const VLCtable cbpy_tab2[4] =
+{
+ {1, 4}, {1, 3}, {1, 2}, {1, 1}
+};
+
+/* DCT coefficients. Four tables, two for last = 0, two for last = 1.
+ the sign bit must be added afterwards. */
+
+/* first part of coeffs for last = 0. Indexed by [run][level-1] */
+
+static const VLCtable coeff_tab0[2][12] =
+{
+ /* run = 0 */
+ {
+ {0x02, 2}, {0x0f, 4}, {0x15, 6}, {0x17, 7},
+ {0x1f, 8}, {0x25, 9}, {0x24, 9}, {0x21, 10},
+ {0x20, 10}, {0x07, 11}, {0x06, 11}, {0x20, 11}
+ },
+ /* run = 1 */
+ {
+ {0x06, 3}, {0x14, 6}, {0x1e, 8}, {0x0f, 10},
+ {0x21, 11}, {0x50, 12}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ }
+};
+
+/* rest of coeffs for last = 0. indexing by [run-2][level-1] */
+
+static const VLCtable coeff_tab1[25][4] =
+{
+ /* run = 2 */
+ {
+ {0x0e, 4}, {0x1d, 8}, {0x0e, 10}, {0x51, 12}
+ },
+ /* run = 3 */
+ {
+ {0x0d, 5}, {0x23, 9}, {0x0d, 10}, {0x00, 0}
+ },
+ /* run = 4-26 */
+ {
+ {0x0c, 5}, {0x22, 9}, {0x52, 12}, {0x00, 0}
+ },
+ {
+ {0x0b, 5}, {0x0c, 10}, {0x53, 12}, {0x00, 0}
+ },
+ {
+ {0x13, 6}, {0x0b, 10}, {0x54, 12}, {0x00, 0}
+ },
+ {
+ {0x12, 6}, {0x0a, 10}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x11, 6}, {0x09, 10}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x10, 6}, {0x08, 10}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x16, 7}, {0x55, 12}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x15, 7}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x14, 7}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1c, 8}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1b, 8}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x21, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x20, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1f, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1e, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1d, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1c, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1b, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x1a, 9}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x22, 11}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x23, 11}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x56, 12}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ },
+ {
+ {0x57, 12}, {0x00, 0}, {0x00, 0}, {0x00, 0}
+ }
+};
+
+/* first coeffs of last = 1. indexing by [run][level-1] */
+
+static const VLCtable coeff_tab2[2][3] =
+{
+ /* run = 0 */
+ {
+ {0x07, 4}, {0x19, 9}, {0x05, 11}
+ },
+ /* run = 1 */
+ {
+ {0x0f, 6}, {0x04, 11}, {0x00, 0}
+ }
+};
+
+/* rest of coeffs for last = 1. indexing by [run-2] */
+
+static const VLCtable coeff_tab3[40] =
+{
+ {0x0e, 6}, {0x0d, 6}, {0x0c, 6},
+ {0x13, 7}, {0x12, 7}, {0x11, 7}, {0x10, 7},
+ {0x1a, 8}, {0x19, 8}, {0x18, 8}, {0x17, 8},
+ {0x16, 8}, {0x15, 8}, {0x14, 8}, {0x13, 8},
+ {0x18, 9}, {0x17, 9}, {0x16, 9}, {0x15, 9},
+ {0x14, 9}, {0x13, 9}, {0x12, 9}, {0x11, 9},
+ {0x07, 10}, {0x06, 10}, {0x05, 10}, {0x04, 10},
+ {0x24, 11}, {0x25, 11}, {0x26, 11}, {0x27, 11},
+ {0x58, 12}, {0x59, 12}, {0x5a, 12}, {0x5b, 12},
+ {0x5c, 12}, {0x5d, 12}, {0x5e, 12}, {0x5f, 12},
+ {0x00, 0}
+};
+
+/* New tables for Intra luminance coefficients. Same codewords,
+ different meaning */
+
+/* Coeffs for last = 0, run = 0. Indexed by [level-1] */
+
+static const VLCtable coeff_tab4[27] =
+{
+ /* run = 0 */
+ {0x02, 2}, {0x06, 3}, {0x0f, 4}, {0x0d, 5},
+ {0x0c, 5}, {0x15, 6}, {0x13, 6}, {0x12, 6},
+ {0x17, 7}, {0x1f, 8}, {0x1e, 8}, {0x1d, 8},
+ {0x25, 9}, {0x24, 9}, {0x23, 9}, {0x21, 9},
+ {0x21, 10}, {0x20, 10}, {0x0f, 10}, {0x0e, 10},
+ {0x07, 11}, {0x06, 11}, {0x20, 11}, {0x21, 11},
+ {0x50, 12}, {0x51, 12}, {0x52, 12}
+};
+
+/* Coeffs for last = 0, run = 1. Indexed by [level-1] */
+
+static const VLCtable coeff_tab5[10] =
+{
+ {0x0e, 4}, {0x14, 6}, {0x16, 7}, {0x1c, 8},
+ {0x20, 9}, {0x1f, 9}, {0x0d, 10}, {0x22, 11},
+ {0x53, 12}, {0x55, 12}
+};
+
+/* Coeffs for last = 0, run = 2 -> 9. Indexed by [run-2][level-1] */
+
+static const VLCtable coeff_tab6[8][5] =
+{
+ /* run = 2 */
+ {
+ {0x0b, 5}, {0x15, 7}, {0x1e, 9}, {0x0c, 10},
+ {0x56, 12}
+ },
+ /* run = 3 */
+ {
+ {0x11, 6}, {0x1b, 8}, {0x1d, 9}, {0x0b, 10},
+ {0x00, 0}
+ },
+ /* run = 4 */
+ {
+ {0x10, 6}, {0x22, 9}, {0x0a, 10}, {0x00, 0},
+ {0x00, 0}
+ },
+ /* run = 5 */
+ {
+ {0x0d, 6}, {0x1c, 9}, {0x08, 10}, {0x00, 0},
+ {0x00, 0}
+ },
+ /* run = 6 */
+ {
+ {0x12, 7}, {0x1b, 9}, {0x54, 12}, {0x00, 0},
+ {0x00, 0}
+ },
+ /* run = 7 */
+ {
+ {0x14, 7}, {0x1a, 9}, {0x57, 12}, {0x00, 0},
+ {0x00, 0}
+ },
+ /* run = 8 */
+ {
+ {0x19, 8}, {0x09, 10}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}
+ },
+ /* run = 9 */
+ {
+ {0x18, 8}, {0x23, 11}, {0x00, 0}, {0x00, 0},
+ {0x00, 0}
+ }
+};
+
+/* Coeffs for last = 0, run = 10 -> 14. Indexed by [run-10] */
+
+static const VLCtable coeff_tab7[5] =
+{
+ {0x17, 8}, {0x19, 9}, {0x18, 9}, {0x07, 10},
+ {0x58, 12}
+};
+
+/* Coeffs for last = 1, run = 0. Indexed by [level-1] */
+
+static const VLCtable coeff_tab8[8] =
+{
+ {0x07, 4}, {0x0c, 6}, {0x16, 8}, {0x17, 9},
+ {0x06, 10}, {0x05, 11}, {0x04, 11}, {0x59, 12}
+};
+
+/* Coeffs for last = 1, run = 1 -> 6. Indexed by [run-1][level-1] */
+
+static const VLCtable coeff_tab9[6][3] =
+{
+ /* run = 1 */
+ {
+ {0x0f, 6}, {0x16, 9}, {0x05, 10}
+ },
+ /* run = 2 */
+ {
+ {0x0e, 6}, {0x04, 10}, {0x00, 0}
+ },
+ /* run = 3 */
+ {
+ {0x11, 7}, {0x24, 11}, {0x00, 0}
+ },
+ /* run = 4 */
+ {
+ {0x10, 7}, {0x25, 11}, {0x00, 0}
+ },
+ /* run = 5 */
+ {
+ {0x13, 7}, {0x5a, 12}, {0x00, 0}
+ },
+ /* run = 6 */
+ {
+ {0x15, 8}, {0x5b, 12}, {0x00, 0}
+ }
+};
+
+/* Coeffs for last = 1, run = 7 -> 20. Indexed by [run-7] */
+
+static const VLCtable coeff_tab10[14] =
+{
+ {0x14, 8}, {0x13, 8}, {0x1a, 8}, {0x15, 9},
+ {0x14, 9}, {0x13, 9}, {0x12, 9}, {0x11, 9},
+ {0x26, 11}, {0x27, 11}, {0x5c, 12}, {0x5d, 12},
+ {0x5e, 12}, {0x5f, 12}
+};
+
+
+#ifndef NO_RVLC
+/* RVLC tables */
+/* DCT coefficients. Four tables, two for last = 0, two for last = 1.
+ the sign bit must be added afterwards. */
+
+/* DCT coeffs (intra) for last = 0. */
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab1[27] =
+{
+ /* run = 0 */
+ { 0x6, 3},
+ { 0x7, 3},
+ { 0xa, 4},
+ { 0x9, 5},
+ { 0x14, 6},
+ { 0x15, 6},
+ { 0x34, 7},
+ { 0x74, 8},
+ { 0x75, 8},
+ { 0xdd, 9},
+ { 0xec, 9},
+ { 0x1ec, 10},
+ { 0x1ed, 10},
+ { 0x1f4, 10},
+ { 0x3ec, 11},
+ { 0x3ed, 11},
+ { 0x3f4, 11},
+ { 0x77d, 12},
+ { 0x7bc, 12},
+ { 0xfbd, 13},
+ { 0xfdc, 13},
+ { 0x7bd, 12},
+ { 0xfdd, 13},
+ { 0x1fbd, 14},
+ { 0x1fdc, 14},
+ { 0x1fdd, 14},
+ { 0x1ffc, 15}
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab2[13] =
+{
+ /* run = 1 */
+ { 0x1, 4},
+ { 0x8, 5},
+ { 0x2d, 7},
+ { 0x6c, 8},
+ { 0x6d, 8},
+ { 0xdc, 9},
+ { 0x1dd, 10},
+ { 0x3dc, 11},
+ { 0x3dd, 11},
+ { 0x77c, 12},
+ { 0xfbc, 13},
+ { 0x1f7d, 14},
+ { 0x1fbc, 14}
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab3[11] =
+{
+ /* run = 2 */
+
+ { 0x4, 5},
+ { 0x2c, 7},
+ { 0xbc, 9},
+ { 0x1dc, 10},
+ { 0x3bc, 11},
+ { 0x3bd, 11},
+ { 0xefd, 13},
+ { 0xf7c, 13},
+ { 0xf7d, 13},
+ { 0x1efd, 14},
+ { 0x1f7c, 14}
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab4[9] =
+{
+ /* run = 3 */
+ { 0x5, 5},
+ { 0x5c, 8},
+ { 0xbd, 9},
+ { 0x37d, 11},
+ { 0x6fc, 12},
+ { 0xefc, 13},
+ { 0x1dfd, 14},
+ { 0x1efc, 14},
+ { 0x1ffd, 15}
+};
+
+
+/* Indexed by [run-4][level-1] */
+
+static const VLCtable coeff_RVLCtab5[2][6] =
+{
+ /* run = 4 */
+ {
+ { 0xc, 6},
+ { 0x5d, 8},
+ { 0x1bd, 10},
+ { 0x3fd, 12},
+ { 0x6fd, 12},
+ { 0x1bfd, 14}
+ },
+ /* run = 5 */
+ {
+ { 0xd, 6},
+ { 0x7d, 9},
+ { 0x2fc, 11},
+ { 0x5fc, 12},
+ { 0x1bfc, 14},
+ { 0x1dfc, 14}
+ }
+};
+
+
+/* Indexed by [run-6][level-1] */
+
+static const VLCtable coeff_RVLCtab6[2][5] =
+{
+
+ /* run = 6 */
+ {
+ { 0x1c, 7},
+ { 0x17c, 10},
+ { 0x2fd, 11},
+ { 0x5fd, 12},
+ { 0x2ffc, 15}
+ },
+ /* run = 7 */
+ {
+ { 0x1d, 7},
+ { 0x17d, 10},
+ { 0x37c, 11},
+ { 0xdfd, 13},
+ { 0x2ffd, 15}
+ }
+
+};
+/* Indexed by [run-8][level-1] */
+
+static const VLCtable coeff_RVLCtab7[2][4] =
+{
+ /* run = 8 */
+ {
+ { 0x3c, 8},
+ { 0x1bc, 10},
+ { 0xbfd, 13},
+ { 0x17fd, 14}
+ },
+ /* run = 9 */
+ {
+ { 0x3d, 8},
+ { 0x1fd, 11},
+ { 0xdfc, 13},
+ { 0x37fc, 15},
+ }
+};
+
+
+
+/* Indexed by [run-10][level-1] */
+
+static const VLCtable coeff_RVLCtab8[3][2] =
+{
+ /* run = 10 */
+ {
+ { 0x7c, 9},
+ { 0x3fc, 12}
+ },
+ /* run = 11 */
+ {
+ { 0xfc, 10},
+ { 0xbfc, 13}
+ },
+ /* run = 12 */
+ {
+ { 0xfd, 10},
+ { 0x37fd, 15}
+ }
+};
+
+
+/* Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab9[7] =
+{
+ /* run = 13 -> 19 */
+ { 0x1fc, 11},
+ { 0x7fc, 13},
+ { 0x7fd, 13},
+ { 0xffc, 14},
+ { 0xffd, 14},
+ { 0x17fc, 14},
+ { 0x3bfc, 15}
+};
+
+
+
+/* first coeffs of last = 1. indexing by [run][level-1] */
+
+static const VLCtable coeff_RVLCtab10[2][5] =
+{
+ /* run = 0 */
+ {
+ { 0xb, 4},
+ { 0x78, 8},
+ { 0x3f5, 11},
+ { 0xfec, 13},
+ { 0x1fec, 14}
+ },
+ /* run = 1 */
+ {
+ { 0x12, 5},
+ { 0xed, 9},
+ { 0x7dc, 12},
+ { 0x1fed, 14},
+ { 0x3bfd, 15}
+ }
+
+};
+
+static const VLCtable coeff_RVLCtab11[3] =
+{
+ /* run = 2 */
+ { 0x13, 5},
+ { 0x3f8, 11},
+ { 0x3dfc, 15}
+
+};
+
+static const VLCtable coeff_RVLCtab12[11][2] =
+{
+ /* run = 3 */
+ {
+ { 0x18, 6},
+ { 0x7dd, 12}
+ },
+ /* run = 4 */
+ {
+ { 0x19, 6},
+ { 0x7ec, 12}
+ },
+ /* run = 5 */
+ {
+ { 0x22, 6},
+ { 0xfed, 13}
+ },
+ /* run = 6 */
+ {
+ { 0x23, 6},
+ { 0xff4, 13}
+ },
+ /* run = 7 */
+ {
+ { 0x35, 7},
+ { 0xff5, 13}
+ },
+ /* run = 8 */
+ {
+ { 0x38, 7},
+ { 0xff8, 13}
+ },
+ /* run = 9 */
+ {
+ { 0x39, 7},
+ { 0xff9, 13}
+ },
+ /* run = 10 */
+ {
+ { 0x42, 7},
+ { 0x1ff4, 14}
+ },
+ /* run = 11 */
+ {
+ { 0x43, 7},
+ { 0x1ff5, 14}
+ },
+ /* run = 12 */
+ {
+ { 0x79, 8},
+ { 0x1ff8, 14}
+ },
+ /* run = 13 */
+ {
+ { 0x82, 8},
+ { 0x3dfd, 15}
+ }
+
+};
+
+static const VLCtable coeff_RVLCtab13[32] =
+{
+ /* run = 14 -> 44 */
+ { 0x83, 8},
+ { 0xf4, 9},
+ { 0xf5, 9},
+ { 0xf8, 9},
+ { 0xf9, 9},
+ { 0x102, 9},
+ { 0x103, 9},
+ { 0x1f5, 10},
+ { 0x1f8, 10},
+ { 0x1f9, 10},
+ { 0x202, 10},
+ { 0x203, 10},
+ { 0x3f9, 11},
+ { 0x402, 11},
+ { 0x403, 11},
+ { 0x7ed, 12},
+ { 0x7f4, 12},
+ { 0x7f5, 12},
+ { 0x7f8, 12},
+ { 0x7f9, 12},
+ { 0x802, 12},
+ { 0x803, 12},
+ { 0x1002, 13},
+ { 0x1003, 13},
+ { 0x1ff9, 14},
+ { 0x2002, 14},
+ { 0x2003, 14},
+ { 0x3efc, 15},
+ { 0x3efd, 15},
+ { 0x3f7c, 15},
+ { 0x3f7d, 15}
+};
+
+
+
+/* Coeffs for last = 0, run = 0. Indexed by [level-1] */
+
+static const VLCtable coeff_RVLCtab14[19] =
+{
+ /* run = 0 */
+ { 0x6, 3},
+ { 0x1, 4},
+ { 0x4, 5},
+ { 0x1c, 7},
+ { 0x3c, 8},
+ { 0x3d, 8},
+ { 0x7c, 9},
+ { 0xfc, 10},
+ { 0xfd, 10},
+ { 0x1fc, 11},
+ { 0x1fd, 11},
+ { 0x3fc, 12},
+ { 0x7fc, 13},
+ { 0x7fd, 13},
+ { 0xbfc, 13},
+ { 0xbfd, 13},
+ { 0xffc, 14},
+ { 0xffd, 14},
+ { 0x1ffc, 15}
+};
+
+static const VLCtable coeff_RVLCtab15[10] =
+{
+ /* run = 1 */
+ { 0x7, 3},
+ { 0xc, 6},
+ { 0x5c, 8},
+ { 0x7d, 9},
+ { 0x17c, 10},
+ { 0x2fc, 11},
+ { 0x3fd, 12},
+ { 0xdfc, 13},
+ { 0x17fc, 14},
+ { 0x17fd, 14}
+};
+
+static const VLCtable coeff_RVLCtab16[2][7] =
+{
+ /* run = 2 */
+ {
+ { 0xa, 4},
+ { 0x1d, 7},
+ { 0xbc, 9},
+ { 0x2fd, 11},
+ { 0x5fc, 12},
+ { 0x1bfc, 14},
+ { 0x1bfd, 14}
+ },
+ /* run = 3 */
+ {
+ { 0x5, 5},
+ { 0x5d, 8},
+ { 0x17d, 10},
+ { 0x5fd, 12},
+ { 0xdfd, 13},
+ { 0x1dfc, 14},
+ { 0x1ffd, 15}
+ }
+};
+
+static const VLCtable coeff_RVLCtab17[5] =
+{
+ /* run = 4 */
+ { 0x8, 5},
+ { 0x6c, 8},
+ { 0x37c, 11},
+ { 0xefc, 13},
+ { 0x2ffc, 15}
+};
+
+static const VLCtable coeff_RVLCtab18[3][4] =
+{
+ /* run = 5 */
+ {
+ { 0x9, 5},
+ { 0xbd, 9},
+ { 0x37d, 11},
+ { 0xefd, 13}
+ },
+ /* run = 6 */
+ {
+ { 0xd, 6},
+ { 0x1bc, 10},
+ { 0x6fc, 12},
+ { 0x1dfd, 14}
+ },
+ /* run = 7 */
+ {
+ { 0x14, 6},
+ { 0x1bd, 10},
+ { 0x6fd, 12},
+ { 0x2ffd, 15}
+ }
+};
+
+static const VLCtable coeff_RVLCtab19[2][3] =
+{
+ /* run = 8 */
+ {
+ { 0x15, 6},
+ { 0x1dc, 10},
+ { 0xf7c, 13}
+ },
+ /* run = 9 */
+ {
+ { 0x2c, 7},
+ { 0x1dd, 10},
+ { 0x1efc, 14}
+ }
+};
+
+static const VLCtable coeff_RVLCtab20[8][2] =
+{
+ /* run = 10 */
+ {
+ { 0x2d, 7},
+ { 0x3bc, 11}
+ },
+ /* run = 11 */
+ {
+ { 0x34, 7},
+ { 0x77c, 12}
+ },
+ /* run = 12 */
+ {
+ { 0x6d, 8},
+ { 0xf7d, 13}
+ },
+ /* run = 13 */
+ {
+ { 0x74, 8},
+ { 0x1efd, 14}
+ },
+ /* run = 14 */
+ {
+ { 0x75, 8},
+ { 0x1f7c, 14}
+ },
+ /* run = 15 */
+ {
+ { 0xdc, 9},
+ { 0x1f7d, 14}
+ },
+ /* run = 16 */
+ {
+ { 0xdd, 9},
+ { 0x1fbc, 14}
+ },
+ /* run = 17 */
+ {
+ { 0xec, 9},
+ { 0x37fc, 15}
+ }
+};
+
+static const VLCtable coeff_RVLCtab21[21] =
+{
+ /* run = 18 -> 38 */
+ { 0x1ec, 10},
+ { 0x1ed, 10},
+ { 0x1f4, 10},
+ { 0x3bd, 11},
+ { 0x3dc, 11},
+ { 0x3dd, 11},
+ { 0x3ec, 11},
+ { 0x3ed, 11},
+ { 0x3f4, 11},
+ { 0x77d, 12},
+ { 0x7bc, 12},
+ { 0x7bd, 12},
+ { 0xfbc, 13},
+ { 0xfbd, 13},
+ { 0xfdc, 13},
+ { 0xfdd, 13},
+ { 0x1fbd, 14},
+ { 0x1fdc, 14},
+ { 0x1fdd, 14},
+ { 0x37fd, 15},
+ { 0x3bfc, 15}
+};
+
+
+/* first coeffs of last = 1. indexing by [run][level-1] */
+
+static const VLCtable coeff_RVLCtab22[2][5] =
+{
+ /* run = 0 */
+ {
+ { 0xb, 4},
+ { 0x78, 8},
+ { 0x3f5, 11},
+ { 0xfec, 13},
+ { 0x1fec, 14}
+ },
+ /* run = 1 */
+ {
+ { 0x12, 5},
+ { 0xed, 9},
+ { 0x7dc, 12},
+ { 0x1fed, 14},
+ { 0x3bfd, 15}
+ }
+
+};
+
+static const VLCtable coeff_RVLCtab23[3] =
+{
+ /* run = 2 */
+ { 0x13, 5},
+ { 0x3f8, 11},
+ { 0x3dfc, 15}
+
+};
+
+static const VLCtable coeff_RVLCtab24[11][2] =
+{
+ /* run = 3 */
+ {
+ { 0x18, 6},
+ { 0x7dd, 12}
+ },
+ /* run = 4 */
+ {
+ { 0x19, 6},
+ { 0x7ec, 12}
+ },
+ /* run = 5 */
+ {
+ { 0x22, 6},
+ { 0xfed, 13}
+ },
+ /* run = 6 */
+ {
+ { 0x23, 6},
+ { 0xff4, 13}
+ },
+ /* run = 7 */
+ {
+ { 0x35, 7},
+ { 0xff5, 13}
+ },
+ /* run = 8 */
+ {
+ { 0x38, 7},
+ { 0xff8, 13}
+ },
+ /* run = 9 */
+ {
+ { 0x39, 7},
+ { 0xff9, 13}
+ },
+ /* run = 10 */
+ {
+ { 0x42, 7},
+ { 0x1ff4, 14}
+ },
+ /* run = 11 */
+ {
+ { 0x43, 7},
+ { 0x1ff5, 14}
+ },
+ /* run = 12 */
+ {
+ { 0x79, 8},
+ { 0x1ff8, 14}
+ },
+ /* run = 13 */
+ {
+ { 0x82, 8},
+ { 0x3dfd, 15}
+ }
+
+};
+
+static const VLCtable coeff_RVLCtab25[32] =
+{
+ /* run = 14 -> 44 */
+ { 0x83, 8},
+ { 0xf4, 9},
+ { 0xf5, 9},
+ { 0xf8, 9},
+ { 0xf9, 9},
+ { 0x102, 9},
+ { 0x103, 9},
+ { 0x1f5, 10},
+ { 0x1f8, 10},
+ { 0x1f9, 10},
+ { 0x202, 10},
+ { 0x203, 10},
+ { 0x3f9, 11},
+ { 0x402, 11},
+ { 0x403, 11},
+ { 0x7ed, 12},
+ { 0x7f4, 12},
+ { 0x7f5, 12},
+ { 0x7f8, 12},
+ { 0x7f9, 12},
+ { 0x802, 12},
+ { 0x803, 12},
+ { 0x1002, 13},
+ { 0x1003, 13},
+ { 0x1ff9, 14},
+ { 0x2002, 14},
+ { 0x2003, 14},
+ { 0x3efc, 15},
+ { 0x3efd, 15},
+ { 0x3f7c, 15},
+ { 0x3f7d, 15}
+};
+
+#endif /* NO_RVLC */
+
+#endif /* _VLC_ENC_TAB_H_ */
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
new file mode 100644
index 0000000..7ea5dc4
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
@@ -0,0 +1,2799 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+/******************************************************************************
+*
+* This software module was originally developed by
+*
+* Robert Danielsen (Telenor / ACTS-MoMuSys).
+*
+* and edited by
+*
+* Luis Ducla-Soares (IST / ACTS-MoMuSys).
+* Cor Quist (KPN / ACTS-MoMuSys).
+*
+* in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
+* This software module is an implementation of a part of one or more MPEG-4
+* Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
+* 14496-2) standard.
+*
+* ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
+* license to this software module or modifications thereof for use in hardware
+* or software products claiming conformance to the MPEG-4 Video (ISO/IEC
+* 14496-2) standard.
+*
+* Those intending to use this software module in hardware or software products
+* are advised that its use may infringe existing patents. The original
+* developer of this software module and his/her company, the subsequent
+* editors and their companies, and ISO/IEC have no liability for use of this
+* software module or modifications thereof in an implementation. Copyright is
+* not released for non MPEG-4 Video (ISO/IEC 14496-2) standard conforming
+* products.
+*
+* ACTS-MoMuSys partners retain full right to use the code for his/her own
+* purpose, assign or donate the code to a third party and to inhibit third
+* parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) standard
+* conforming products. This copyright notice must be included in all copies or
+* derivative works.
+*
+* Copyright (c) 1997
+*
+*****************************************************************************/
+
+/***********************************************************HeaderBegin*******
+*
+* File: putvlc.c
+*
+* Author: Robert Danielsen, Telenor R&D
+* Created: 07.07.96
+*
+* Description: Functions for writing to bitstream
+*
+* Notes: Same kind of tables as in the MPEG-2 software simulation
+* group software.
+*
+* Modified:
+* 28.10.96 Robert Danielsen: Added PutCoeff_Intra(), renamed
+* PutCoeff() to PutCoeff_Inter().
+* 06.11.96 Robert Danielsen: Added PutMCBPC_sep()
+* 01.05.97 Luis Ducla-Soares: added PutCoeff_Intra_RVLC() and
+* PutCoeff_Inter_RVLC().
+*
+***********************************************************HeaderEnd*********/
+
+/************************ INCLUDE FILES ********************************/
+
+
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+#include "vlc_enc_tab.h"
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+#include "vlc_encode_inline.h"
+
+typedef void (*BlockCodeCoeffPtr)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar) ;
+
+const static Int mode_MBtype[] =
+{
+ 3,
+ 0,
+ 4,
+ 1,
+ 2,
+};
+
+const static Int zigzag_inv[NCOEFF_BLOCK] =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+/* Horizontal zigzag inverse */
+const static Int zigzag_h_inv[NCOEFF_BLOCK] =
+{
+ 0, 1, 2, 3, 8, 9, 16, 17,
+ 10, 11, 4, 5, 6, 7, 15, 14,
+ 13, 12, 19, 18, 24, 25, 32, 33,
+ 26, 27, 20, 21, 22, 23, 28, 29,
+ 30, 31, 34, 35, 40, 41, 48, 49,
+ 42, 43, 36, 37, 38, 39, 44, 45,
+ 46, 47, 50, 51, 56, 57, 58, 59,
+ 52, 53, 54, 55, 60, 61, 62, 63
+};
+
+/* Vertical zigzag inverse */
+const static Int zigzag_v_inv[NCOEFF_BLOCK] =
+{
+ 0, 8, 16, 24, 1, 9, 2, 10,
+ 17, 25, 32, 40, 48, 56, 57, 49,
+ 41, 33, 26, 18, 3, 11, 4, 12,
+ 19, 27, 34, 42, 50, 58, 35, 43,
+ 51, 59, 20, 28, 5, 13, 6, 14,
+ 21, 29, 36, 44, 52, 60, 37, 45,
+ 53, 61, 22, 30, 7, 15, 23, 31,
+ 38, 46, 54, 62, 39, 47, 55, 63
+};
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ Int PutCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream);
+ Int PutMCBPC_Inter(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+ Int PutMCBPC_Intra(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+ Int PutMV(Int mvint, BitstreamEncVideo *bitstream);
+ Int PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream);
+ Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+ Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+#ifndef NO_RVLC
+ Int PutCoeff_Inter_RVLC(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCoeff_Inter_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCoeff_Intra_RVLC(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutCoeff_Intra_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+#endif
+ Int PutRunCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutRunCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutRunCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutRunCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutLevelCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutLevelCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutLevelCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
+ Int PutLevelCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
+
+ void RunLevel(VideoEncData *video, Int intra, Int intraDC_decision, Int ncoefblck[]);
+ Int IntraDC_dpcm(Int val, Int lum, BitstreamEncVideo *bitstream);
+ Void DCACPred(VideoEncData *video, UChar Mode, Int *intraDC_decision, Int intraDCVlcQP);
+ Void find_pmvs(VideoEncData *video, Int block, Int *mvx, Int *mvy);
+ Void WriteMVcomponent(Int f_code, Int dmv, BitstreamEncVideo *bs);
+ static Bool IntraDCSwitch_Decision(Int Mode, Int intra_dc_vlc_threshold, Int intraDCVlcQP);
+
+ Void ScaleMVD(Int f_code, Int diff_vector, Int *residual, Int *vlc_code_mag);
+
+#ifdef __cplusplus
+}
+#endif
+
+Int
+PutDCsize_lum(Int size, BitstreamEncVideo *bitstream)
+{
+ Int length;
+
+ if (!(size >= 0 && size < 13))
+ return -1;
+
+ length = DCtab_lum[size].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, DCtab_lum[size].code);
+
+ return length;
+}
+
+Int
+PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream)
+{
+ Int length;
+
+ if (!(size >= 0 && size < 13))
+ return -1;
+ length = DCtab_chrom[size].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, DCtab_chrom[size].code);
+
+ return length;
+}
+
+Int
+PutMV(Int mvint, BitstreamEncVideo *bitstream)
+{
+ Int sign = 0;
+ Int absmv;
+ Int length;
+
+ if (mvint > 32)
+ {
+ absmv = -mvint + 65;
+ sign = 1;
+ }
+ else
+ absmv = mvint;
+
+ length = mvtab[absmv].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, mvtab[absmv].code);
+
+ if (mvint != 0)
+ {
+ BitstreamPut1Bits(bitstream, sign);
+ return (length + 1);
+ }
+ else
+ return length;
+}
+
+Int
+PutMCBPC_Intra(Int cbp, Int mode, BitstreamEncVideo *bitstream)
+{
+ Int ind;
+ Int length;
+
+ ind = ((mode_MBtype[mode] >> 1) & 3) | ((cbp & 3) << 2);
+
+ length = mcbpc_intra_tab[ind].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, mcbpc_intra_tab[ind].code);
+
+ return length;
+}
+
+Int
+PutMCBPC_Inter(Int cbp, Int mode, BitstreamEncVideo *bitstream)
+{
+ Int ind;
+ Int length;
+
+ ind = (mode_MBtype[mode] & 7) | ((cbp & 3) << 3);
+
+ length = mcbpc_inter_tab[ind].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, mcbpc_inter_tab[ind].code);
+
+ return length;
+}
+
+Int
+PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream)
+{
+ Int ind;
+ Int length;
+
+ if ((intra == 0))
+ cbpy = 15 - cbpy;
+
+ ind = cbpy;
+
+ length = cbpy_tab[ind].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)cbpy_tab[ind].code);
+
+ return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+/* Note:::: I checked the ARM assembly for if( run > x && run < y) type
+ of code, they do a really good job compiling it to if( (UInt)(run-x) < y-x).
+ No need to hand-code it!!!!!, 6/1/2001 */
+
+Int PutCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run < 2 && level < 13)
+ {
+ length = coeff_tab0[run][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
+ }
+ else if (run > 1 && run < 27 && level < 5)
+ {
+ length = coeff_tab1[run-2][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
+ }
+
+ return length;
+}
+
+Int PutCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run < 2 && level < 4)
+ {
+ length = coeff_tab2[run][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
+ }
+ else if (run > 1 && run < 42 && level == 1)
+ {
+ length = coeff_tab3[run-2].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
+ }
+
+ return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+
+Int PutCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 28)
+ {
+ length = coeff_tab4[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
+ }
+ else if (run == 1 && level < 11)
+ {
+ length = coeff_tab5[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
+ }
+ else if (run > 1 && run < 10 && level < 6)
+ {
+ length = coeff_tab6[run-2][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
+ }
+ else if (run > 9 && run < 15 && level == 1)
+ {
+ length = coeff_tab7[run-10].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
+ }
+
+ return length;
+}
+
+Int PutCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 9)
+ {
+ length = coeff_tab8[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
+ }
+ else if (run > 0 && run < 7 && level < 4)
+ {
+ length = coeff_tab9[run-1][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
+ }
+ else if (run > 6 && run < 21 && level == 1)
+ {
+ length = coeff_tab10[run-7].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
+ }
+
+ return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+#ifndef NO_RVLC
+Int PutCoeff_Inter_RVLC(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 20)
+ {
+ length = coeff_RVLCtab14[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab14[level-1].code);
+ }
+ else if (run == 1 && level < 11)
+ {
+ length = coeff_RVLCtab15[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab15[level-1].code);
+ }
+ else if (run > 1 && run < 4 && level < 8)
+ {
+ length = coeff_RVLCtab16[run-2][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab16[run-2][level-1].code);
+ }
+ else if (run == 4 && level < 6)
+ {
+ length = coeff_RVLCtab17[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab17[level-1].code);
+ }
+ else if (run > 4 && run < 8 && level < 5)
+ {
+ length = coeff_RVLCtab18[run-5][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab18[run-5][level-1].code);
+ }
+ else if (run > 7 && run < 10 && level < 4)
+ {
+ length = coeff_RVLCtab19[run-8][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab19[run-8][level-1].code);
+ }
+ else if (run > 9 && run < 18 && level < 3)
+ {
+ length = coeff_RVLCtab20[run-10][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab20[run-10][level-1].code);
+ }
+ else if (run > 17 && run < 39 && level == 1)
+ {
+ length = coeff_RVLCtab21[run-18].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab21[run-18].code);
+ }
+
+ return length;
+}
+
+Int PutCoeff_Inter_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run >= 0 && run < 2 && level < 6)
+ {
+ length = coeff_RVLCtab22[run][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab22[run][level-1].code);
+ }
+ else if (run == 2 && level < 4)
+ {
+ length = coeff_RVLCtab23[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab23[level-1].code);
+ }
+ else if (run > 2 && run < 14 && level < 3)
+ {
+ length = coeff_RVLCtab24[run-3][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab24[run-3][level-1].code);
+ }
+ else if (run > 13 && run < 45 && level == 1)
+ {
+ length = coeff_RVLCtab25[run-14].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab25[run-14].code);
+ }
+
+ return length;
+}
+
+/* 5/16/01, break up function for last and not-last coefficient */
+
+Int PutCoeff_Intra_RVLC(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 28)
+ {
+ length = coeff_RVLCtab1[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab1[level-1].code);
+ }
+ else if (run == 1 && level < 14)
+ {
+ length = coeff_RVLCtab2[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab2[level-1].code);
+ }
+ else if (run == 2 && level < 12)
+ {
+ length = coeff_RVLCtab3[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab3[level-1].code);
+ }
+ else if (run == 3 && level < 10)
+ {
+ length = coeff_RVLCtab4[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab4[level-1].code);
+ }
+ else if (run > 3 && run < 6 && level < 7)
+ {
+ length = coeff_RVLCtab5[run-4][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab5[run-4][level-1].code);
+ }
+ else if (run > 5 && run < 8 && level < 6)
+ {
+ length = coeff_RVLCtab6[run-6][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab6[run-6][level-1].code);
+ }
+ else if (run > 7 && run < 10 && level < 5)
+ {
+ length = coeff_RVLCtab7[run-8][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab7[run-8][level-1].code);
+
+ }
+ else if (run > 9 && run < 13 && level < 3)
+ {
+ length = coeff_RVLCtab8[run-10][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab8[run-10][level-1].code);
+ }
+ else if (run > 12 && run < 20 && level == 1)
+ {
+ length = coeff_RVLCtab9[run-13].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab9[run-13].code);
+ }
+ return length;
+}
+
+Int PutCoeff_Intra_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run >= 0 && run < 2 && level < 6)
+ {
+ length = coeff_RVLCtab10[run][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab10[run][level-1].code);
+ }
+ else if (run == 2 && level < 4)
+ {
+ length = coeff_RVLCtab11[level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab11[level-1].code);
+ }
+ else if (run > 2 && run < 14 && level < 3)
+ {
+ length = coeff_RVLCtab12[run-3][level-1].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab12[run-3][level-1].code);
+ }
+ else if (run > 13 && run < 45 && level == 1)
+ {
+ length = coeff_RVLCtab13[run-14].len;
+ if (length)
+ BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab13[run-14].code);
+ }
+ return length;
+}
+#endif
+
+/* The following is for 3-mode VLC */
+
+Int
+PutRunCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run < 2 && level < 13)
+ {
+ length = coeff_tab0[run][level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
+ length += 9;
+ }
+ }
+ else if (run > 1 && run < 27 && level < 5)
+ {
+ length = coeff_tab1[run-2][level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
+ length += 9;
+ }
+ }
+ return length;
+}
+
+Int PutRunCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run < 2 && level < 4)
+ {
+ length = coeff_tab2[run][level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
+ length += 9;
+ }
+ }
+ else if (run > 1 && run < 42 && level == 1)
+ {
+ length = coeff_tab3[run-2].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
+ length += 9;
+ }
+ }
+ return length;
+}
+
+Int PutRunCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 28)
+ {
+ length = coeff_tab4[level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
+ length += 9;
+ }
+ }
+ else if (run == 1 && level < 11)
+ {
+ length = coeff_tab5[level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
+ length += 9;
+ }
+ }
+ else if (run > 1 && run < 10 && level < 6)
+ {
+ length = coeff_tab6[run-2][level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
+ length += 9;
+ }
+ }
+ else if (run > 9 && run < 15 && level == 1)
+ {
+ length = coeff_tab7[run-10].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
+ length += 9;
+ }
+ }
+ return length;
+}
+Int PutRunCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 9)
+ {
+ length = coeff_tab8[level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
+ length += 9;
+ }
+ }
+ else if (run > 0 && run < 7 && level < 4)
+ {
+ length = coeff_tab9[run-1][level-1].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
+ length += 9;
+ }
+ }
+ else if (run > 6 && run < 21 && level == 1)
+ {
+ length = coeff_tab10[run-7].len;
+ if (length)
+ {
+ BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
+ //BitstreamPutBits(bitstream, 2, 2);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
+ length += 9;
+ }
+ }
+ return length;
+}
+
+Int
+PutLevelCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run < 2 && level < 13)
+ {
+ length = coeff_tab0[run][level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
+ length += 8;
+ }
+ }
+ else if (run > 1 && run < 27 && level < 5)
+ {
+ length = coeff_tab1[run-2][level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
+ length += 8;
+ }
+ }
+ return length;
+}
+
+Int PutLevelCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run < 2 && level < 4)
+ {
+ length = coeff_tab2[run][level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
+ length += 8;
+ }
+ }
+ else if (run > 1 && run < 42 && level == 1)
+ {
+ length = coeff_tab3[run-2].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
+ length += 8;
+ }
+ }
+ return length;
+}
+
+Int PutLevelCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 28)
+ {
+ length = coeff_tab4[level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
+ length += 8;
+ }
+ }
+ else if (run == 1 && level < 11)
+ {
+ length = coeff_tab5[level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
+ length += 8;
+ }
+ }
+ else if (run > 1 && run < 10 && level < 6)
+ {
+ length = coeff_tab6[run-2][level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
+ length += 8;
+ }
+ }
+ else if (run > 9 && run < 15 && level == 1)
+ {
+ length = coeff_tab7[run-10].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
+ length += 8;
+ }
+ }
+ return length;
+}
+Int PutLevelCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
+{
+ Int length = 0;
+
+ if (run == 0 && level < 9)
+ {
+ length = coeff_tab8[level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
+ length += 8;
+ }
+ }
+ else if (run > 0 && run < 7 && level < 4)
+ {
+ length = coeff_tab9[run-1][level-1].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
+ length += 8;
+ }
+ }
+ else if (run > 6 && run < 21 && level == 1)
+ {
+ length = coeff_tab10[run-7].len;
+ if (length)
+ {
+ BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
+ BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
+ length += 8;
+ }
+ }
+ return length;
+}
+
+
+
+/* ======================================================================== */
+/* Function : MBVlcEncode() */
+/* Date : 09/10/2000 */
+/* Purpose : Encode GOV Header */
+/* In/out : */
+/* Return : */
+/* Modified : 5/21/01, break up into smaller functions */
+/* ======================================================================== */
+#ifndef H263_ONLY
+/**************************************/
+/* Data Partitioning I-VOP Encoding */
+/**************************************/
+
+void MBVlcEncodeDataPar_I_VOP(
+ VideoEncData *video,
+ Int ncoefblck[],
+ void *blkCodePtr)
+{
+
+ BitstreamEncVideo *bs1 = video->bitstream1;
+ BitstreamEncVideo *bs2 = video->bitstream2;
+ BitstreamEncVideo *bs3 = video->bitstream3;
+ int i;
+ UChar Mode = video->headerInfo.Mode[video->mbnum];
+ UChar CBP;
+// MacroBlock *MB=video->outputMB;
+ Int mbnum = video->mbnum;
+ Int intraDC_decision, DC;
+// int temp;
+ Int dquant; /* 3/15/01 */
+ RunLevelBlock *RLB = video->RLB;
+ BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+ /* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
+ DCACPred(video, Mode, &intraDC_decision, video->QP_prev);
+
+ /* CBP, Run, Level, and Sign */
+ RunLevel(video, 1, intraDC_decision, ncoefblck);
+ CBP = video->headerInfo.CBP[mbnum];
+
+ /* Compute DQuant */
+ dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+
+ video->QP_prev = video->QPMB[mbnum];
+
+ if (dquant && Mode == MODE_INTRA)
+ {
+ Mode = MODE_INTRA_Q;
+ }
+
+ if (dquant >= 0)
+ dquant = (PV_ABS(dquant) + 1);
+ else
+ dquant = (PV_ABS(dquant) - 1);
+
+ /* FIRST PART: ALL TO BS1 */
+
+ PutMCBPC_Intra(CBP, Mode, bs1); /* MCBPC */
+
+ if (Mode == MODE_INTRA_Q)
+ /* MAY NEED TO CHANGE DQUANT HERE */
+ BitstreamPutBits(bs1, 2, dquant); /* dquant*/
+
+
+ if (intraDC_decision == 0)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ DC = video->RLB[i].level[0];
+ if (video->RLB[i].s[0])
+ DC = -DC;
+ if (i < 4)
+ /*temp =*/ IntraDC_dpcm(DC, 1, bs1); /* dct_dc_size_luminance, */
+ else /* dct_dc_differential, and */
+ /*temp =*/ IntraDC_dpcm(DC, 0, bs1); /* marker bit */
+ }
+ }
+
+ /* SECOND PART: ALL TO BS2*/
+
+ BitstreamPut1Bits(bs2, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
+
+ /*temp=*/
+ PutCBPY(CBP >> 2, (Char)(1), bs2); /* cbpy */
+
+
+ /* THIRD PART: ALL TO BS3*/
+ /* MB_CodeCoeff(video,bs3); */ /* 5/22/01, replaced with below */
+ for (i = 0; i < 6; i++)
+ {
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs3, 1 - intraDC_decision, ncoefblck[i], Mode);/* Code Intra AC*/
+ }
+
+ return ;
+}
+
+/************************************/
+/* Data Partitioning P-VOP Encoding */
+/************************************/
+
+void MBVlcEncodeDataPar_P_VOP(
+ VideoEncData *video,
+ Int ncoefblck[],
+ void *blkCodePtr)
+{
+
+ BitstreamEncVideo *bs1 = video->bitstream1;
+ BitstreamEncVideo *bs2 = video->bitstream2;
+ BitstreamEncVideo *bs3 = video->bitstream3;
+ int i;
+ Int mbnum = video->mbnum;
+ UChar Mode = video->headerInfo.Mode[mbnum];
+ Int QP_tmp = video->QPMB[mbnum];
+ UChar CBP;
+// MacroBlock *MB=video->outputMB;
+ Int intra, intraDC_decision, DC;
+ Int pmvx, pmvy;
+// int temp;
+ Int dquant; /* 3/15/01 */
+ RunLevelBlock *RLB = video->RLB;
+ BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+ intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+
+ /* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
+
+ if (intra)
+ {
+ if (video->usePrevQP)
+ {
+ QP_tmp = video->QPMB[mbnum-1];
+ }
+
+ DCACPred(video, Mode, &intraDC_decision, QP_tmp);
+ }
+ else
+ intraDC_decision = 0; /* used in RunLevel */
+
+ /* CBP, Run, Level, and Sign */
+ RunLevel(video, intra, intraDC_decision, ncoefblck);
+ CBP = video->headerInfo.CBP[mbnum];
+
+ /* Compute DQuant */
+ dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+
+ if (dquant && (Mode == MODE_INTRA || Mode == MODE_INTER))
+ {
+ Mode += 2; /* make it MODE_INTRA_Q and MODE_INTER_Q */
+ }
+
+ if (dquant >= 0)
+ dquant = (PV_ABS(dquant) + 1);
+ else
+ dquant = (PV_ABS(dquant) - 1);
+
+ /* FIRST PART: ALL TO BS1 */
+
+ if (CBP == 0 && intra == 0) /* Determine if Skipped MB */
+ {
+ if ((Mode == MODE_INTER) && (video->mot[mbnum][0].x == 0) && (video->mot[mbnum][0].y == 0))
+ Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+ else if ((Mode == MODE_INTER4V) && (video->mot[mbnum][1].x == 0) && (video->mot[mbnum][1].y == 0)
+ && (video->mot[mbnum][2].x == 0) && (video->mot[mbnum][2].y == 0)
+ && (video->mot[mbnum][3].x == 0) && (video->mot[mbnum][3].y == 0)
+ && (video->mot[mbnum][4].x == 0) && (video->mot[mbnum][4].y == 0))
+ Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+ }
+
+
+ if (Mode == MODE_SKIPPED)
+ {
+ BitstreamPut1Bits(bs1, 1); /* not_coded = 1 */
+ return;
+ }
+ else
+ BitstreamPut1Bits(bs1, 0); /* not_coded =0 */
+
+ video->QP_prev = video->QPMB[mbnum];
+ video->usePrevQP = 1;
+
+ PutMCBPC_Inter(CBP, Mode, bs1); /* MCBPC */
+
+ video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+
+ if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
+ {
+ find_pmvs(video, 0, &pmvx, &pmvy); /* Get predicted motion vectors */
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].x - pmvx, bs1); /* Write x to bitstream */
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].y - pmvy, bs1); /* Write y to bitstream */
+ }
+ else if (Mode == MODE_INTER4V)
+ {
+ for (i = 1; i < 5; i++)
+ {
+ find_pmvs(video, i, &pmvx, &pmvy);
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].x - pmvx, bs1);
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].y - pmvy, bs1);
+ }
+ }
+ video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+
+ /* SECOND PART: ALL TO BS2 */
+
+
+ if (intra)
+ {
+ BitstreamPut1Bits(bs2, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
+ /*temp=*/
+ PutCBPY(CBP >> 2, (Char)(Mode == MODE_INTRA || Mode == MODE_INTRA_Q), bs2); /* cbpy */
+
+ if (Mode == MODE_INTRA_Q)
+ BitstreamPutBits(bs2, 2, dquant); /* dquant, 3/15/01*/
+
+ if (intraDC_decision == 0)
+ {
+ for (i = 0; i < 6; i++)
+ {
+ DC = video->RLB[i].level[0];
+ if (video->RLB[i].s[0])
+ DC = -DC;
+ if (i < 4)
+ /*temp =*/ IntraDC_dpcm(DC, 1, bs2); /* dct_dc_size_luminance, */
+ else /* dct_dc_differential, and */
+ /*temp =*/ IntraDC_dpcm(DC, 0, bs2); /* marker bit */
+ }
+ }
+
+ /****************************/ /* THIRD PART: ALL TO BS3 */
+ for (i = 0; i < 6; i++)
+ {
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs3, 1 - intraDC_decision, ncoefblck[i], Mode);/* Code Intra AC*/
+ }
+ }
+ else
+ {
+ /*temp=*/
+ PutCBPY(CBP >> 2, (Char)(Mode == MODE_INTRA || Mode == MODE_INTRA_Q), bs2); /* cbpy */
+ if (Mode == MODE_INTER_Q)
+ /* MAY NEED TO CHANGE DQUANT HERE */
+ BitstreamPutBits(bs2, 2, dquant); /* dquant, 3/15/01*/
+
+ /****************************/ /* THIRD PART: ALL TO BS3 */
+ for (i = 0; i < 6; i++)
+ {
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs3, 0, ncoefblck[i], Mode);/* Code Intra AC*/
+ }
+ }
+
+ return ;
+}
+#endif /* H263_ONLY */
+/****************************************************************************************/
+/* Short Header/Combined Mode with or without Error Resilience I-VOP and P-VOP Encoding */
+/* 5/21/01, B-VOP is not implemented yet!!!! */
+/****************************************************************************************/
+
+void MBVlcEncodeCombined_I_VOP(
+ VideoEncData *video,
+ Int ncoefblck[],
+ void *blkCodePtr)
+{
+
+ BitstreamEncVideo *bs1 = video->bitstream1;
+// BitstreamEncVideo *bs2 = video->bitstream2;
+// BitstreamEncVideo *bs3 = video->bitstream3;
+ int i;
+ UChar Mode = video->headerInfo.Mode[video->mbnum];
+ UChar CBP = video->headerInfo.CBP[video->mbnum];
+// MacroBlock *MB=video->outputMB;
+ Int mbnum = video->mbnum;
+ Int intraDC_decision;
+// int temp;
+ Int dquant; /* 3/15/01 */
+ RunLevelBlock *RLB = video->RLB;
+ Int DC;
+ Int shortVideoHeader = video->vol[video->currLayer]->shortVideoHeader;
+ BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+ /* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
+
+#ifndef H263_ONLY
+ if (!shortVideoHeader)
+ DCACPred(video, Mode, &intraDC_decision, video->QP_prev);
+ else
+#endif
+ {
+ intraDC_decision = 0;
+ }
+
+ /* CBP, Run, Level, and Sign */
+
+ RunLevel(video, 1, intraDC_decision, ncoefblck);
+ CBP = video->headerInfo.CBP[mbnum];
+
+ /* Compute DQuant */
+ dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+
+ video->QP_prev = video->QPMB[mbnum];
+
+ if (dquant && Mode == MODE_INTRA)
+ {
+ Mode = MODE_INTRA_Q;
+ }
+
+ if (dquant >= 0)
+ dquant = (PV_ABS(dquant) + 1);
+ else
+ dquant = (PV_ABS(dquant) - 1);
+
+ PutMCBPC_Intra(CBP, Mode, bs1); /* mcbpc I_VOP */
+
+ if (!video->vol[video->currLayer]->shortVideoHeader)
+ {
+ BitstreamPut1Bits(bs1, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
+ }
+
+ /*temp=*/
+ PutCBPY(CBP >> 2, (Char)(1), bs1); /* cbpy */
+
+ if (Mode == MODE_INTRA_Q)
+ /* MAY NEED TO CHANGE DQUANT HERE */
+ BitstreamPutBits(bs1, 2, dquant); /* dquant, 3/15/01*/
+
+ /*MB_CodeCoeff(video,bs1); 5/21/01, replaced by below */
+ /*******************/
+#ifndef H263_ONLY
+ if (shortVideoHeader) /* Short Header DC coefficients */
+ {
+#endif
+ for (i = 0; i < 6; i++)
+ {
+ DC = RLB[i].level[0];
+ if (RLB[i].s[0])
+ DC = -DC;
+ if (DC != 128)
+ BitstreamPutBits(bs1, 8, DC); /* intra_dc_size_luminance */
+ else
+ BitstreamPutBits(bs1, 8, 255); /* intra_dc_size_luminance */
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode); /* Code short header Intra AC*/
+ }
+#ifndef H263_ONLY
+ }
+ else if (intraDC_decision == 0) /* Combined Intra Mode DC and AC coefficients */
+ {
+ for (i = 0; i < 6; i++)
+ {
+ DC = RLB[i].level[0];
+ if (RLB[i].s[0])
+ DC = -DC;
+
+ if (i < 4)
+ /*temp =*/ IntraDC_dpcm(DC, 1, bs1); /* dct_dc_size_luminance, */
+ else /* dct_dc_differential, and */
+ /*temp =*/ IntraDC_dpcm(DC, 0, bs1); /* marker bit */
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode);/* Code Intra AC */
+ }
+ }
+ else /* Combined Mode Intra DC/AC coefficients */
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Intra AC */
+ }
+ }
+#endif
+ /*******************/
+ return ;
+}
+
+void MBVlcEncodeCombined_P_VOP(
+ VideoEncData *video,
+ Int ncoefblck[],
+ void *blkCodePtr)
+{
+
+ BitstreamEncVideo *bs1 = video->bitstream1;
+// BitstreamEncVideo *bs2 = video->bitstream2;
+// BitstreamEncVideo *bs3 = video->bitstream3;
+ int i;
+ Int mbnum = video->mbnum;
+ UChar Mode = video->headerInfo.Mode[mbnum];
+ Int QP_tmp = video->QPMB[mbnum];
+ UChar CBP ;
+// MacroBlock *MB=video->outputMB;
+ Int intra, intraDC_decision;
+ Int pmvx, pmvy;
+// int temp;
+ Int dquant; /* 3/15/01 */
+ RunLevelBlock *RLB = video->RLB;
+ Int DC;
+ Int shortVideoHeader = video->vol[video->currLayer]->shortVideoHeader;
+ BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
+
+ intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+
+ /* DC and AC Prediction, 5/28/01, compute intraDC_decision*/
+#ifndef H263_ONLY
+ if (!shortVideoHeader && intra)
+ {
+ if (video->usePrevQP)
+ {
+ QP_tmp = video->QPMB[mbnum-1];
+ }
+ DCACPred(video, Mode, &intraDC_decision, QP_tmp);
+ }
+ else
+#endif
+ intraDC_decision = 0;
+
+ /* CBP, Run, Level, and Sign */
+
+ RunLevel(video, intra, intraDC_decision, ncoefblck);
+ CBP = video->headerInfo.CBP[mbnum];
+
+ /* Compute DQuant */
+ dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
+ if (dquant && (Mode == MODE_INTRA || Mode == MODE_INTER))
+ {
+ Mode += 2; /* make it MODE_INTRA_Q and MODE_INTER_Q */
+ }
+
+ if (dquant >= 0)
+ dquant = (PV_ABS(dquant) + 1);
+ else
+ dquant = (PV_ABS(dquant) - 1);
+
+ if (CBP == 0 && intra == 0) /* Determine if Skipped MB */
+ {
+ if ((Mode == MODE_INTER) && (video->mot[mbnum][0].x == 0) && (video->mot[mbnum][0].y == 0))
+ Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+ else if ((Mode == MODE_INTER4V) && (video->mot[mbnum][1].x == 0) && (video->mot[mbnum][1].y == 0)
+ && (video->mot[mbnum][2].x == 0) && (video->mot[mbnum][2].y == 0)
+ && (video->mot[mbnum][3].x == 0) && (video->mot[mbnum][3].y == 0)
+ && (video->mot[mbnum][4].x == 0) && (video->mot[mbnum][4].y == 0))
+ Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
+ }
+
+ if (Mode == MODE_SKIPPED)
+ {
+ BitstreamPut1Bits(bs1, 1); /* not_coded = 1 */
+ return;
+ }
+ else
+ BitstreamPut1Bits(bs1, 0); /* not_coded =0 */
+
+ video->QP_prev = video->QPMB[mbnum];
+ video->usePrevQP = 1;
+
+ PutMCBPC_Inter(CBP, Mode, bs1); /* mcbpc P_VOP */
+
+ if (!video->vol[video->currLayer]->shortVideoHeader && intra)
+ {
+ BitstreamPut1Bits(bs1, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
+ }
+
+ /*temp=*/
+ PutCBPY(CBP >> 2, (Char)(intra), bs1); /* cbpy */
+
+ if (Mode == MODE_INTRA_Q || Mode == MODE_INTER_Q)
+ /* MAY NEED TO CHANGE DQUANT HERE */
+ BitstreamPutBits(bs1, 2, dquant); /* dquant, 3/15/01*/
+
+ video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
+
+ if (!((video->vol[video->currLayer]->scalability) && (video->currVop->refSelectCode == 3)))
+ {
+ if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
+ {
+ find_pmvs(video, 0, &pmvx, &pmvy); /* Get predicted motion vectors */
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].x - pmvx, bs1); /* Write x to bitstream */
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].y - pmvy, bs1); /* Write y to bitstream */
+ }
+ else if (Mode == MODE_INTER4V)
+ {
+ for (i = 1; i < 5; i++)
+ {
+ find_pmvs(video, i, &pmvx, &pmvy);
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].x - pmvx, bs1);
+ WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].y - pmvy, bs1);
+ }
+ }
+ }
+ video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
+
+ /* MB_CodeCoeff(video,bs1); */ /* 5/22/01, replaced with below */
+ /****************************/
+ if (intra)
+ {
+#ifndef H263_ONLY
+ if (shortVideoHeader) /* Short Header DC coefficients */
+ {
+#endif
+ for (i = 0; i < 6; i++)
+ {
+ DC = RLB[i].level[0];
+ if (RLB[i].s[0])
+ DC = -DC;
+ if (DC != 128)
+ BitstreamPutBits(bs1, 8, DC); /* intra_dc_size_luminance */
+ else
+ BitstreamPutBits(bs1, 8, 255); /* intra_dc_size_luminance */
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode); /* Code short header Intra AC*/
+ }
+#ifndef H263_ONLY
+ }
+ else if (intraDC_decision == 0) /* Combined Intra Mode DC and AC coefficients */
+ {
+ for (i = 0; i < 6; i++)
+ {
+ DC = RLB[i].level[0];
+ if (RLB[i].s[0])
+ DC = -DC;
+
+ if (i < 4)
+ /*temp =*/ IntraDC_dpcm(DC, 1, bs1); /* dct_dc_size_luminance, */
+ else /* dct_dc_differential, and */
+ /*temp =*/ IntraDC_dpcm(DC, 0, bs1); /* marker bit */
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode);/* Code Intra AC */
+ }
+ }
+ else /* Combined Mode Intra DC/AC coefficients */
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Intra AC */
+ }
+ }
+#endif
+ }
+ else /* Shortheader or Combined INTER Mode AC coefficients */
+ {
+ for (i = 0; i < 6; i++)
+ {
+ if (CBP&(1 << (5 - i)))
+ (*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Inter AC*/
+ }
+ }
+ /****************************/
+
+ return ;
+}
+
+/* ======================================================================== */
+/* Function : BlockCodeCoeff() */
+/* Date : 09/18/2000 */
+/* Purpose : VLC Encode AC/DC coeffs */
+/* In/out : */
+/* Return : */
+/* Modified : 5/16/01 grouping BitstreamPutBits calls */
+/* 5/22/01 break up function */
+/* ======================================================================== */
+#ifndef NO_RVLC
+/*****************/
+/* RVLC ENCODING */
+/*****************/
+Void BlockCodeCoeff_RVLC(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
+{
+ int length = 0;
+ int i;
+ Int level;
+ Int run;
+ Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+
+ /* Not Last Coefficient */
+ for (i = j_start; i < j_stop - 1; i++)
+ {
+ run = RLB->run[i];
+ level = RLB->level[i];
+ //if(i==63||RLB->run[i+1] == -1) /* Don't Code Last Coefficient Here */
+ // break;
+ /*ENCODE RUN LENGTH */
+ if (level < 28 && run < 39)
+ {
+ if (intra)
+ length = PutCoeff_Intra_RVLC(run, level, bs);
+ else
+ length = PutCoeff_Inter_RVLC(run, level, bs);
+ }
+ else
+ length = 0;
+ /* ESCAPE CODING */
+ if (length == 0)
+ {
+ BitstreamPutBits(bs, 5 + 1, 2); /* ESCAPE + Not Last Coefficient */
+ //BitstreamPutBits(bs,1,0); /* Not Last Coefficient */
+ BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* RUN + MARKER BIT*/
+ //BitstreamPutBits(bs,1,1); /* MARKER BIT */
+ BitstreamPutGT8Bits(bs, 11, level); /* LEVEL */
+ BitstreamPutBits(bs, 1 + 4, 16); /* MARKER BIT */
+ //BitstreamPutBits(bs,4,0); /* RVLC TRAILING ESCAPE */
+ }
+ BitstreamPutBits(bs, 1, RLB->s[i]); /* SIGN BIT */
+ }
+ /* Last Coefficient!!! */
+ run = RLB->run[i];
+ level = RLB->level[i];
+
+ /*ENCODE RUN LENGTH */
+ if (level < 6 && run < 45)
+ {
+ if (intra)
+ length = PutCoeff_Intra_RVLC_Last(run, level, bs);
+ else
+ length = PutCoeff_Inter_RVLC_Last(run, level, bs);
+ }
+ else
+ length = 0;
+ /* ESCAPE CODING */
+ if (length == 0)
+ {
+ BitstreamPutBits(bs, 5 + 1, 3); /* ESCAPE CODE + Last Coefficient*/
+ //BitstreamPutBits(bs,1,1); /* Last Coefficient !*/
+ BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* RUN + MARKER BIT*/
+ //BitstreamPutBits(bs,1,1); /* MARKER BIT */
+ BitstreamPutGT8Bits(bs, 11, level); /* LEVEL */
+ BitstreamPutBits(bs, 1 + 4, 16); /* MARKER BIT + RVLC TRAILING ESCAPE */
+ //BitstreamPutBits(bs,4,0); /* */
+ }
+ BitstreamPut1Bits(bs, RLB->s[i]); /* SIGN BIT */
+
+ return ;
+}
+#endif
+/*******************************/
+/* SHORT VIDEO HEADER ENCODING */
+/*******************************/
+
+Void BlockCodeCoeff_ShortHeader(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
+{
+ int length = 0;
+ int i;
+// int temp;
+ Int level;
+ Int run;
+
+ OSCL_UNUSED_ARG(Mode);
+
+ /* Not Last Coefficient */
+ for (i = j_start; i < j_stop - 1; i++)
+ {
+ run = RLB->run[i];
+ level = RLB->level[i];
+// if(i==63 ||RLB->run[i+1] == -1) /* Don't Code Last Coefficient Here */
+// break;
+ /*ENCODE RUN LENGTH */
+ if (level < 13)
+ {
+ length = PutCoeff_Inter(run, level, bs);
+ if (length != 0)
+ /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
+ }
+ else
+ length = 0;
+ /* ESCAPE CODING */
+ if (length == 0)
+ {
+ if (RLB->s[i])
+ level = -level;
+ BitstreamPutBits(bs, 7 + 1, 6); /* ESCAPE CODE + Not Last Coefficient */
+ //BitstreamPutBits(bs,1,0); /* Not Last Coefficient */
+ BitstreamPutBits(bs, 6, run); /* RUN */
+ BitstreamPutBits(bs, 8, level&0xFF); /* LEVEL, mask to make sure length 8 */
+ }
+ }
+ /* Last Coefficient!!! */
+ run = RLB->run[i];
+ level = RLB->level[i];
+
+ /*ENCODE RUN LENGTH */
+ if (level < 13)
+ {
+ length = PutCoeff_Inter_Last(run, level, bs);
+ if (length != 0)
+ /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
+ }
+ else
+ length = 0;
+ /* ESCAPE CODING */
+ if (length == 0)
+ {
+ if (RLB->s[i])
+ level = -level;
+ BitstreamPutBits(bs, 7 + 1, 7); /* ESCAPE CODE + Last Coefficient */
+ //BitstreamPutBits(bs,1,1); /* Last Coefficient !!!*/
+ BitstreamPutBits(bs, 6, run); /* RUN */
+ BitstreamPutBits(bs, 8, level&0xFF); /* LEVEL, mask to make sure length 8 */
+ }
+
+ return ;
+
+}
+
+#ifndef H263_ONLY
+/****************/
+/* VLC ENCODING */
+/****************/
+Void BlockCodeCoeff_Normal(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
+{
+ int length = 0;
+ int i;
+ //int temp;
+ Int level;
+ Int run;
+ Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
+ Int level_minus_max;
+ Int run_minus_max;
+ Int(*PutCoeff)(Int, Int, BitstreamEncVideo *); /* pointer to functions, 5/28/01 */
+
+ /* Not Last Coefficient!!! */
+
+ if (intra)
+ PutCoeff = &PutCoeff_Intra;
+ else
+ PutCoeff = &PutCoeff_Inter;
+
+ for (i = j_start; i < j_stop - 1; i++)
+ {
+ run = RLB->run[i];
+ level = RLB->level[i];
+
+ /* Encode Run Length */
+ if (level < 28)
+ {
+ length = (*PutCoeff)(run, level, bs); /* 5/28/01 replaces above */
+ }
+ else
+ {
+ length = 0;
+ }
+
+ /* First escape mode: LEVEL OFFSET */
+ if (length == 0)
+ {
+ if (intra)
+ {
+ level_minus_max = level - intra_max_level[0][run];
+ if (level_minus_max < 28)
+ length = PutLevelCoeff_Intra(run, level_minus_max, bs);
+ else
+ length = 0;
+ }
+ else
+ {
+ level_minus_max = level - inter_max_level[0][run];
+ if (level_minus_max < 13)
+ length = PutLevelCoeff_Inter(run, level_minus_max, bs);
+ else
+ length = 0;
+ }
+
+ /* Second escape mode: RUN OFFSET */
+ if (length == 0)
+ {
+ if (level < 28)
+ {
+ if (intra)
+ {
+ run_minus_max = run - (intra_max_run0[level] + 1);
+ length = PutRunCoeff_Intra(run_minus_max, level, bs);
+ }
+ else if (level < 13)
+ {
+ run_minus_max = run - (inter_max_run0[level] + 1);
+ length = PutRunCoeff_Inter(run_minus_max, level, bs);
+ }
+ else
+ {
+ length = 0;
+ }
+ }
+ else
+ {
+ length = 0;
+ }
+
+ /* Third escape mode: FIXED LENGTH CODE */
+ if (length == 0)
+ {
+ if (RLB->s[i])
+ level = -level;
+ /*temp =*/
+ BitstreamPutBits(bs, 7 + 2 + 1, 30); /* ESCAPE CODE + Followed by 11 + Not Last Coefficient*/
+ //temp = BitstreamPutBits(bs,2,3); /* Followed by 11 */
+ //temp = BitstreamPutBits(bs, 1, 0); /* Not Last Coefficient*/
+ /*temp =*/
+ BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* Encode Run + Marker Bit */
+ //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+ /*temp =*/
+ BitstreamPutGT8Bits(bs, 12 + 1, ((level << 1) | 1)&0x1FFF); /* Encode Level, mask to make sure length 12 */
+ //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+ }
+ }
+ }
+
+ /* Encode Sign Bit */
+ if (length != 0)
+ /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
+
+ }
+ /* Last Coefficient */
+ run = RLB->run[i];
+ level = RLB->level[i];
+
+ /* Encode Run Length */
+ if (level < 9)
+ {
+ if (intra)
+ {
+ length = PutCoeff_Intra_Last(run, level, bs);
+ }
+ else if (level < 4)
+ {
+ length = PutCoeff_Inter_Last(run, level, bs);
+ }
+ else
+ {
+ length = 0;
+ }
+ }
+ else
+ {
+ length = 0;
+ }
+
+ /* First escape mode: LEVEL OFFSET */
+ if (length == 0)
+ {
+ if (intra)
+ {
+ level_minus_max = level - intra_max_level[1][run];
+ if (level_minus_max < 9)
+ length = PutLevelCoeff_Intra_Last(run, level_minus_max, bs);
+ else
+ length = 0;
+ }
+ else
+ {
+ level_minus_max = level - inter_max_level[1][run];
+ if (level_minus_max < 4)
+ length = PutLevelCoeff_Inter_Last(run, level_minus_max, bs);
+ else
+ length = 0;
+ }
+ /* Second escape mode: RUN OFFSET */
+ if (length == 0)
+ {
+ if (level < 9)
+ {
+ if (intra)
+ {
+ run_minus_max = run - (intra_max_run1[level] + 1);
+ length = PutRunCoeff_Intra_Last(run_minus_max, level, bs);
+ }
+ else if (level < 4)
+ {
+ run_minus_max = run - (inter_max_run1[level] + 1);
+ length = PutRunCoeff_Inter_Last(run_minus_max, level, bs);
+ }
+ else
+ {
+ length = 0;
+ }
+ }
+ else
+ {
+ length = 0;
+ }
+ /* Third escape mode: FIXED LENGTH CODE */
+ if (length == 0)
+ {
+ if (RLB->s[i])
+ level = -level;
+ /*temp =*/
+ BitstreamPutGT8Bits(bs, 7 + 2 + 1, 31); /* ESCAPE CODE + Followed by 11 + Last Coefficient*/
+ //temp = BitstreamPutBits(bs,2,3); /* Followed by 11 */
+ //temp = BitstreamPutBits(bs, 1, 1); /* Last Coefficient!!!*/
+ /*temp =*/
+ BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* Encode Run + Marker Bit */
+ //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+ /*temp =*/
+ BitstreamPutGT8Bits(bs, 12 + 1, ((level << 1) | 1)&0x1FFF); /* Encode Level, mask to make sure length 8 */
+ //temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
+ }
+ }
+ }
+
+ /* Encode Sign Bit */
+ if (length != 0)
+ /*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]);
+
+
+ return ;
+}
+
+#endif /* H263_ONLY */
+/* ======================================================================== */
+/* Function : RUNLevel */
+/* Date : 09/20/2000 */
+/* Purpose : Get the Coded Block Pattern for each block */
+/* In/out : */
+/* Int* qcoeff Quantized DCT coefficients
+ Int Mode Coding Mode
+ Int ncoeffs Number of coefficients */
+/* Return : */
+/* Int CBP Coded Block Pattern */
+/* Modified : */
+/* ======================================================================== */
+
+void RunLevel(VideoEncData *video, Int intra, Int intraDC_decision, Int ncoefblck[])
+{
+ Int i, j;
+ Int CBP = video->headerInfo.CBP[video->mbnum];
+ Int ShortNacNintra = (!(video->vol[video->currLayer]->shortVideoHeader) && video->acPredFlag[video->mbnum] && intra);
+ MacroBlock *MB = video->outputMB;
+ Short *dataBlock;
+ Int level;
+ RunLevelBlock *RLB;
+ Int run, idx;
+ Int *zz, nc, zzorder;
+ UChar imask[6] = {0x1F, 0x2F, 0x37, 0x3B, 0x3D, 0x3E};
+ UInt *bitmapzz;
+
+ /* Set Run, Level and CBP for this Macroblock */
+ /* ZZ scan is done here. */
+
+ if (intra)
+ {
+
+ if (intraDC_decision != 0)
+ intra = 0; /* DC/AC in Run/Level */
+
+ for (i = 0; i < 6 ; i++)
+ {
+
+ zz = (Int *) zigzag_inv;
+
+ RLB = video->RLB + i;
+
+ dataBlock = MB->block[i];
+
+ if (intra)
+ {
+ RLB->run[0] = 0;
+ level = dataBlock[0];
+ dataBlock[0] = 0; /* reset to zero */
+ if (level < 0)
+ {
+ RLB->level[0] = -level;
+ RLB->s[0] = 1;
+ }
+ else
+ {
+ RLB->level[0] = level;
+ RLB->s[0] = 0;
+ }
+ }
+
+ idx = intra;
+
+ if ((CBP >> (5 - i)) & 1)
+ {
+ if (ShortNacNintra)
+ {
+ switch ((video->zz_direction >> (5 - i))&1)
+ {
+ case 0:
+ zz = (Int *)zigzag_v_inv;
+ break;
+ case 1:
+ zz = (Int *)zigzag_h_inv;
+ break;
+ }
+ }
+ run = 0;
+ nc = ncoefblck[i];
+ for (j = intra, zz += intra; j < nc; j++, zz++)
+ {
+ zzorder = *zz;
+ level = dataBlock[zzorder];
+ if (level == 0)
+ run++;
+ else
+ {
+ dataBlock[zzorder] = 0; /* reset output */
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ }
+ }
+ }
+
+ ncoefblck[i] = idx; /* 5/22/01, reuse ncoefblck */
+
+ if (idx == intra) /* reset CBP, nothing to be coded */
+ CBP &= imask[i];
+ }
+
+ video->headerInfo.CBP[video->mbnum] = CBP;
+
+ return ;
+ }
+ else
+ {
+// zz = (Int *) zigzag_inv; no need to use it, default
+
+ if (CBP)
+ {
+ for (i = 0; i < 6 ; i++)
+ {
+ RLB = video->RLB + i;
+ idx = 0;
+
+ if ((CBP >> (5 - i)) & 1)
+ { /* 7/30/01 */
+ /* Use bitmapzz to find the Run,Level,Sign symbols */
+ bitmapzz = video->bitmapzz[i];
+ dataBlock = MB->block[i];
+ nc = ncoefblck[i];
+
+ idx = zero_run_search(bitmapzz, dataBlock, RLB, nc);
+ }
+ ncoefblck[i] = idx; /* 5/22/01, reuse ncoefblck */
+ if (idx == 0) /* reset CBP, nothing to be coded */
+ CBP &= imask[i];
+ }
+ video->headerInfo.CBP[video->mbnum] = CBP;
+ }
+ return ;
+ }
+}
+
+#ifndef H263_ONLY
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ static Bool IntraDCSwitch_Decision(Int Mode, Int intra_dc_vlc_thr, Int intraDCVlcQP)
+ {
+ Bool switched = FALSE;
+
+ if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
+ {
+ if (intra_dc_vlc_thr != 0)
+ {
+ switched = (intra_dc_vlc_thr == 7 || intraDCVlcQP >= intra_dc_vlc_thr * 2 + 11);
+ }
+ }
+
+ return switched;
+ }
+#ifdef __cplusplus
+}
+#endif
+
+Int IntraDC_dpcm(Int val, Int lum, BitstreamEncVideo *bitstream)
+{
+ Int n_bits;
+ Int absval, size = 0;
+
+ absval = (val < 0) ? -val : val; /* abs(val) */
+
+
+ /* compute dct_dc_size */
+
+ size = 0;
+ while (absval)
+ {
+ absval >>= 1;
+ size++;
+ }
+
+ if (lum)
+ { /* luminance */
+ n_bits = PutDCsize_lum(size, bitstream);
+ }
+ else
+ { /* chrominance */
+ n_bits = PutDCsize_chrom(size, bitstream);
+ }
+
+ if (size != 0)
+ {
+ if (val >= 0)
+ {
+ ;
+ }
+ else
+ {
+ absval = -val; /* set to "-val" MW 14-NOV-1996 */
+ val = absval ^((1 << size) - 1);
+ }
+ BitstreamPutBits(bitstream, (size), (UInt)(val));
+ n_bits += size;
+
+ if (size > 8)
+ BitstreamPut1Bits(bitstream, 1);
+ }
+
+ return n_bits; /* # bits for intra_dc dpcm */
+
+}
+
+/* ======================================================================== */
+/* Function : DC_AC_PRED */
+/* Date : 09/24/2000 */
+/* Purpose : DC and AC encoding of Intra Blocks */
+/* In/out : */
+/* VideoEncData *video
+ UChar Mode */
+/* Return : */
+/* */
+/* ======================================================================== */
+Int cal_dc_scalerENC(Int QP, Int type) ;
+
+
+#define PREDICT_AC for (m = 0; m < 7; m++){ \
+ tmp = DCAC[0]*QPtmp;\
+ if(tmp<0) tmp = (tmp-(QP/2))/QP;\
+ else tmp = (tmp+(QP/2))/QP;\
+ pred[m] = tmp;\
+ DCAC++;\
+ }
+
+
+Void DCACPred(VideoEncData *video, UChar Mode, Int *intraDC_decision, Int intraDCVlcQP)
+{
+ MacroBlock *MB = video->outputMB;
+ Int mbnum = video->mbnum;
+ typeDCStore *DC_store = video->predDC + mbnum;
+ typeDCACStore *DCAC_row = video->predDCAC_row;
+ typeDCACStore *DCAC_col = video->predDCAC_col;
+ Short *DCAC;
+ UChar Mode_top, Mode_left;
+
+ Vol *currVol = video->vol[video->currLayer];
+ Int nMBPerRow = currVol->nMBPerRow;
+ Int x_pos = video->outputMB->mb_x; /* 5/28/01 */
+ Int y_pos = video->outputMB->mb_y;
+ UChar QP = video->QPMB[mbnum];
+ UChar *QPMB = video->QPMB;
+ UChar *slice_nb = video->sliceNo;
+ Bool bACPredEnable = video->encParams->ACDCPrediction;
+ Int *ACpred_flag = video->acPredFlag;
+ Int mid_grey = 128 << 3;
+ Int m;
+ Int comp;
+ Int dc_scale = 8, tmp;
+
+ static const Int Xpos[6] = { -1, 0, -1, 0, -1, -1};
+ static const Int Ypos[6] = { -1, -1, 0, 0, -1, -1};
+ static const Int Xtab[6] = {1, 0, 3, 2, 4, 5};
+ static const Int Ytab[6] = {2, 3, 0, 1, 4, 5};
+ static const Int Ztab[6] = {3, 2, 1, 0, 4, 5};
+
+ /* I added these to speed up comparisons */
+ static const Int Pos0[6] = { 1, 1, 0, 0, 1, 1};
+ static const Int Pos1[6] = { 1, 0, 1, 0, 1, 1};
+ static const Int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
+ static const Int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
+
+ Int direction[6]; /* 0: HORIZONTAL, 1: VERTICAL */
+ Int block_A, block_B, block_C;
+ Int grad_hor, grad_ver, DC_pred;
+ Short pred[7], *predptr;
+ Short pcoeff[42];
+ Short *qcoeff;
+ Int S = 0, S1, S2;
+ Int diff, QPtmp;
+ Int newCBP[6];
+ UChar mask1[6] = {0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
+// UChar mask2[6] = {0x1f,0x2f,0x37,0x3b,0x3d,0x3e};
+
+ Int y_offset, x_offset, x_tab, y_tab, z_tab; /* speedup coefficients */
+ Int b_xtab, b_ytab;
+
+ video->zz_direction = 0;
+
+ /* Standard MPEG-4 Headers do DC/AC prediction*/
+ /* check whether neighbors are INTER */
+ if (y_pos > 0)
+ {
+ Mode_top = video->headerInfo.Mode[mbnum-nMBPerRow];
+ if (!(Mode_top == MODE_INTRA || Mode_top == MODE_INTRA_Q))
+ {
+ DCAC = DC_store[-nMBPerRow];
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ /* set to 0 DCAC_row[x_pos][0..3] */
+ if (bACPredEnable == TRUE)
+ {
+ M4VENC_MEMSET(DCAC_row[x_pos][0], 0, sizeof(Short) << 5);
+ }
+ }
+ }
+ if (x_pos > 0)
+ {
+ Mode_left = video->headerInfo.Mode[mbnum-1];
+ if (!(Mode_left == MODE_INTRA || Mode_left == MODE_INTRA_Q))
+ {
+ DCAC = DC_store[-1];
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ *DCAC++ = mid_grey;
+ /* set to 0 DCAC_col[x_pos][0..3] */
+ if (bACPredEnable == TRUE)
+ {
+ M4VENC_MEMSET(DCAC_col[0][0], 0, sizeof(Short) << 5);
+ }
+ }
+ }
+
+ S1 = 0;
+ S2 = 0;
+
+ for (comp = 0; comp < 6; comp++)
+ {
+
+ if (Ypos[comp] != 0) y_offset = -nMBPerRow;
+ else y_offset = 0;
+ x_offset = Xpos[comp];
+ x_tab = Xtab[comp];
+ y_tab = Ytab[comp];
+ z_tab = Ztab[comp];
+
+ b_xtab = B_Xtab[comp];
+ b_ytab = B_Ytab[comp];
+
+ qcoeff = MB->block[comp];
+
+ /****************************/
+ /* Store DC coefficients */
+ /****************************/
+ /* Store coeff values for Intra MB */
+ if (comp == 0) dc_scale = cal_dc_scalerENC(QP, 1) ;
+ if (comp == 4) dc_scale = cal_dc_scalerENC(QP, 2) ;
+
+ QPtmp = qcoeff[0] * dc_scale; /* DC value */
+
+ if (QPtmp > 2047) /* 10/10/01, add clipping (bug fixed) */
+ DC_store[0][comp] = 2047;
+ else if (QPtmp < -2048)
+ DC_store[0][comp] = -2048;
+ else
+ DC_store[0][comp] = QPtmp;
+
+ /**************************************************************/
+ /* Find the direction of the prediction and the DC prediction */
+ /**************************************************************/
+
+ if ((x_pos == 0) && y_pos == 0)
+ { /* top left corner */
+ block_A = (comp == 1 || comp == 3) ? DC_store[0][x_tab] : mid_grey;
+ block_B = (comp == 3) ? DC_store[x_offset][z_tab] : mid_grey;
+ block_C = (comp == 2 || comp == 3) ? DC_store[0][y_tab] : mid_grey;
+ }
+ else if (x_pos == 0)
+ { /* left edge */
+ block_A = (comp == 1 || comp == 3) ? DC_store[0][x_tab] : mid_grey;
+ block_B = ((comp == 1 && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])) || comp == 3) ?
+ DC_store[y_offset+x_offset][z_tab] : mid_grey;
+ block_C = (comp == 2 || comp == 3 ||
+ (Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))) ?
+ DC_store[y_offset][y_tab] : mid_grey;
+ }
+ else if (y_pos == 0)
+ { /* top row */
+ block_A = (comp == 1 || comp == 3 || (Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))) ?
+ DC_store[x_offset][x_tab] : mid_grey;
+ block_B = ((comp == 2 && (slice_nb[mbnum] == slice_nb[mbnum-1])) || comp == 3) ?
+ DC_store[y_offset + x_offset][z_tab] : mid_grey;
+ block_C = (comp == 2 || comp == 3) ?
+ DC_store[y_offset][y_tab] : mid_grey;
+ }
+ else
+ {
+ block_A = (comp == 1 || comp == 3 || (Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))) ?
+ DC_store[x_offset][x_tab] : mid_grey;
+ block_B = (((comp == 0 || comp == 4 || comp == 5) &&
+ (slice_nb[mbnum] == slice_nb[mbnum-1-nMBPerRow])) ||
+ (comp == 1 && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])) ||
+ (comp == 2 && (slice_nb[mbnum] == slice_nb[mbnum-1])) || (comp == 3)) ?
+ (DC_store[y_offset + x_offset][z_tab]) : mid_grey;
+ block_C = (comp == 2 || comp == 3 || (Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))) ?
+ DC_store[y_offset][y_tab] : mid_grey;
+ }
+ grad_hor = block_B - block_C;
+ grad_ver = block_A - block_B;
+
+ if ((PV_ABS(grad_ver)) < (PV_ABS(grad_hor)))
+ {
+ DC_pred = block_C;
+ direction[comp] = 1;
+ video->zz_direction = (video->zz_direction) | mask1[comp];
+
+ }
+ else
+ {
+ DC_pred = block_A;
+ direction[comp] = 0;
+ //video->zz_direction=video->zz_direction<<1;
+ }
+
+ /* DC prediction */
+ QPtmp = dc_scale; /* 5/28/01 */
+ qcoeff[0] -= (DC_pred + QPtmp / 2) / QPtmp;
+
+
+ if (bACPredEnable)
+ {
+ /***********************/
+ /* Find AC prediction */
+ /***********************/
+
+ if ((x_pos == 0) && y_pos == 0) /* top left corner */
+ {
+ if (direction[comp] == 0)
+ {
+ if (comp == 1 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+x_offset];
+ DCAC = DCAC_col[0][b_ytab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ else
+ {
+ if (comp == 2 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+ y_offset];
+ DCAC = DCAC_row[x_pos][b_xtab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ }
+ else if (x_pos == 0) /* left edge */
+ {
+ if (direction[comp] == 0)
+ {
+ if (comp == 1 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+x_offset];
+ DCAC = DCAC_col[0][b_ytab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ else
+ {
+
+ if ((Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))
+ || comp == 2 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+y_offset];
+ DCAC = DCAC_row[x_pos][b_xtab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ }
+ else if (y_pos == 0) /* top row */
+ {
+ if (direction[comp] == 0)
+ {
+ if ((Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))
+ || comp == 1 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+x_offset];
+ DCAC = DCAC_col[0][b_ytab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ else
+ {
+ if (comp == 2 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+y_offset];
+ DCAC = DCAC_row[x_pos][b_xtab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ }
+ else
+ {
+ if (direction[comp] == 0)
+ {
+ if ((Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))
+ || comp == 1 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+x_offset];
+ DCAC = DCAC_col[0][b_ytab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ else
+ {
+ if ((Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))
+ || comp == 2 || comp == 3)
+ {
+ QPtmp = QPMB[mbnum+y_offset];
+ DCAC = DCAC_row[x_pos][b_xtab];
+ if (QPtmp != QP)
+ {
+ predptr = pred;
+ PREDICT_AC
+ }
+ else
+ {
+ predptr = DCAC;
+ }
+ }
+ else
+ {
+ predptr = pred;
+ pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
+ }
+ }
+ }
+
+ /************************************/
+ /* Decide and Perform AC prediction */
+ /************************************/
+ newCBP[comp] = 0;
+
+ if (direction[comp] == 0) /* Horizontal, left COLUMN of block A */
+ {
+ DCAC = pcoeff + comp * 7; /* re-use DCAC as local var */
+ qcoeff += 8;
+ for (m = 0; m < 7; m++)
+ {
+ QPtmp = qcoeff[m<<3];
+ if (QPtmp > 0) S1 += QPtmp;
+ else S1 -= QPtmp;
+ QPtmp -= predptr[m];
+ DCAC[m] = QPtmp; /* save prediction residue to pcoeff*/
+ if (QPtmp) newCBP[comp] = 1;
+ diff = PV_ABS(QPtmp);
+ S2 += diff;
+ }
+ }
+ else /* Vertical, top ROW of block C */
+ {
+ qcoeff++;
+ DCAC = pcoeff + comp * 7; /* re-use DCAC as local var */
+ for (m = 0; m < 7; m++)
+ {
+ QPtmp = qcoeff[m];
+ if (QPtmp > 0) S1 += QPtmp;
+ else S1 -= QPtmp;
+ QPtmp -= predptr[m];
+ DCAC[m] = QPtmp; /* save prediction residue to pcoeff*/
+ if (QPtmp) newCBP[comp] = 1;
+ diff = PV_ABS(QPtmp);
+ S2 += diff;
+ }
+ }
+
+ /****************************/
+ /* Store DCAC coefficients */
+ /****************************/
+ /* Store coeff values for Intra MB */
+ qcoeff = MB->block[comp];
+ DCAC = DCAC_row[x_pos][b_xtab];
+ DCAC[0] = qcoeff[1];
+ DCAC[1] = qcoeff[2];
+ DCAC[2] = qcoeff[3];
+ DCAC[3] = qcoeff[4];
+ DCAC[4] = qcoeff[5];
+ DCAC[5] = qcoeff[6];
+ DCAC[6] = qcoeff[7];
+
+ DCAC = DCAC_col[0][b_ytab];
+ DCAC[0] = qcoeff[8];
+ DCAC[1] = qcoeff[16];
+ DCAC[2] = qcoeff[24];
+ DCAC[3] = qcoeff[32];
+ DCAC[4] = qcoeff[40];
+ DCAC[5] = qcoeff[48];
+ DCAC[6] = qcoeff[56];
+
+
+ } /* bACPredEnable */
+
+ } /* END COMP FOR LOOP */
+
+ //if (diff > 2047)
+ // break;
+ S += (S1 - S2);
+
+
+ if (S >= 0 && bACPredEnable == TRUE)
+ {
+ ACpred_flag[mbnum] = 1;
+ DCAC = pcoeff; /* prediction residue */
+ qcoeff = MB->block[0];
+
+ for (comp = 0; comp < 6; comp++)
+ {
+ if (direction[comp] == 0)
+ {
+ qcoeff[8] = DCAC[0];
+ qcoeff[16] = DCAC[1];
+ qcoeff[24] = DCAC[2];
+ qcoeff[32] = DCAC[3];
+ qcoeff[40] = DCAC[4];
+ qcoeff[48] = DCAC[5];
+ qcoeff[56] = DCAC[6];
+
+ }
+ else
+ {
+ qcoeff[1] = DCAC[0];
+ qcoeff[2] = DCAC[1];
+ qcoeff[3] = DCAC[2];
+ qcoeff[4] = DCAC[3];
+ qcoeff[5] = DCAC[4];
+ qcoeff[6] = DCAC[5];
+ qcoeff[7] = DCAC[6];
+ }
+ if (newCBP[comp]) /* 5/28/01, update CBP */
+ video->headerInfo.CBP[mbnum] |= mask1[comp];
+ DCAC += 7;
+ qcoeff += 64;
+ }
+ }
+ else /* Only DC Prediction */
+ {
+ ACpred_flag[mbnum] = 0;
+ }
+
+ *intraDC_decision = IntraDCSwitch_Decision(Mode, video->currVop->intraDCVlcThr, intraDCVlcQP);
+ if (*intraDC_decision) /* code DC with AC , 5/28/01*/
+ {
+ qcoeff = MB->block[0];
+ for (comp = 0; comp < 6; comp++)
+ {
+ if (*qcoeff)
+ video->headerInfo.CBP[mbnum] |= mask1[comp];
+ qcoeff += 64;
+ }
+ }
+ return;
+}
+#endif /* H263_ONLY */
+
+
+
+Void find_pmvs(VideoEncData *video, Int block, Int *mvx, Int *mvy)
+{
+ Vol *currVol = video->vol[video->currLayer];
+// UChar *Mode = video->headerInfo.Mode; /* modes for MBs */
+ UChar *slice_nb = video->sliceNo;
+ Int nMBPerRow = currVol->nMBPerRow;
+ Int mbnum = video->mbnum;
+
+ Int p1x, p2x, p3x;
+ Int p1y, p2y, p3y;
+ Int xin1, xin2, xin3;
+ Int yin1, yin2, yin3;
+ Int vec1, vec2, vec3;
+ Int rule1, rule2, rule3;
+ MOT **motdata = video->mot;
+ Int x = mbnum % nMBPerRow;
+ Int y = mbnum / nMBPerRow;
+
+ /*
+ In a previous version, a MB vector (block = 0) was predicted the same way
+ as block 1, which is the most likely interpretation of the VM.
+
+ Therefore, if we have advanced pred. mode, and if all MBs around have
+ only one 16x16 vector each, we chose the appropiate block as if these
+ MBs have 4 vectors.
+
+ This different prediction affects only 16x16 vectors of MBs with
+ transparent blocks.
+
+ In the current version, we choose for the 16x16 mode the first
+ non-transparent block in the surrounding MBs
+ */
+
+ switch (block)
+ {
+ case 0:
+ vec1 = 2 ;
+ yin1 = y ;
+ xin1 = x - 1;
+ vec2 = 3 ;
+ yin2 = y - 1;
+ xin2 = x;
+ vec3 = 3 ;
+ yin3 = y - 1;
+ xin3 = x + 1;
+ break;
+
+ case 1:
+ vec1 = 2 ;
+ yin1 = y ;
+ xin1 = x - 1;
+ vec2 = 3 ;
+ yin2 = y - 1;
+ xin2 = x;
+ vec3 = 3 ;
+ yin3 = y - 1;
+ xin3 = x + 1;
+ break;
+
+ case 2:
+ vec1 = 1 ;
+ yin1 = y ;
+ xin1 = x;
+ vec2 = 4 ;
+ yin2 = y - 1;
+ xin2 = x;
+ vec3 = 3 ;
+ yin3 = y - 1;
+ xin3 = x + 1;
+ break;
+
+ case 3:
+ vec1 = 4 ;
+ yin1 = y ;
+ xin1 = x - 1;
+ vec2 = 1 ;
+ yin2 = y ;
+ xin2 = x;
+ vec3 = 2 ;
+ yin3 = y ;
+ xin3 = x;
+ break;
+
+ default: /* case 4 */
+ vec1 = 3 ;
+ yin1 = y ;
+ xin1 = x;
+ vec2 = 1 ;
+ yin2 = y ;
+ xin2 = x;
+ vec3 = 2 ;
+ yin3 = y ;
+ xin3 = x;
+ break;
+ }
+
+ if (block == 0)
+ {
+ /* according to the motion encoding, we must choose a first non-transparent
+ block in the surrounding MBs (16-mode)
+ */
+
+ if (x > 0 && slice_nb[mbnum] == slice_nb[mbnum-1])
+ rule1 = 0;
+ else
+ rule1 = 1;
+
+ if (y > 0 && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])
+ rule2 = 0;
+ else
+ rule2 = 1;
+
+ if ((x != nMBPerRow - 1) && (y > 0) && slice_nb[mbnum] == slice_nb[mbnum+1-nMBPerRow])
+ rule3 = 0;
+ else
+ rule3 = 1;
+ }
+ else
+ {
+ /* check borders for single blocks (advanced mode) */
+ /* rule 1 */
+ if (((block == 1 || block == 3) &&
+ (x == 0 || slice_nb[mbnum] != slice_nb[mbnum-1])))
+ rule1 = 1;
+ else
+ rule1 = 0;
+
+ /* rule 2 */
+ if (((block == 1 || block == 2) &&
+ (y == 0 || slice_nb[mbnum] != slice_nb[mbnum-nMBPerRow])))
+ rule2 = 1;
+ else
+ rule2 = 0;
+
+ /* rule 3 */
+ if (((block == 1 || block == 2) &&
+ (x == nMBPerRow - 1 || y == 0 || slice_nb[mbnum] != slice_nb[mbnum+1-nMBPerRow])))
+ rule3 = 1;
+ else
+ rule3 = 0;
+ }
+
+ if (rule1)
+ {
+ p1x = p1y = 0;
+ }
+ else
+ {
+
+ p1x = motdata[yin1*nMBPerRow+xin1][vec1].x;
+ p1y = motdata[yin1*nMBPerRow+xin1][vec1].y;
+ //p1x = motxdata[xin1*2+(vec1&0x1) + (yin1*2+(vec1>>1))*xB];
+ //p1y = motydata[xin1*2+(vec1&0x1) + (yin1*2+(vec1>>1))*xB];
+ }
+
+ if (rule2)
+ {
+ p2x = p2y = 0;
+ }
+ else
+ {
+ p2x = motdata[yin2*nMBPerRow+xin2][vec2].x;
+ p2y = motdata[yin2*nMBPerRow+xin2][vec2].y;
+ //p2x = motxdata[xin2*2+(vec2&0x1) + (yin2*2+(vec2>>1))*xB];
+ //p2y = motydata[xin2*2+(vec2&0x1) + (yin2*2+(vec2>>1))*xB];
+ }
+
+ if (rule3)
+ {
+ p3x = p3y = 0;
+ }
+ else
+ {
+ p3x = motdata[yin3*nMBPerRow+xin3][vec3].x;
+ p3y = motdata[yin3*nMBPerRow+xin3][vec3].y;
+ //p3x = motxdata[xin3*2+ (vec3&0x1) + (yin3*2+(vec3>>1))*xB];
+ //p3y = motydata[xin3*2+ (vec3&0x1) + (yin3*2+(vec3>>1))*xB];
+ }
+
+ if (rule1 && rule2 && rule3)
+ {
+ /* all MBs are outside the VOP */
+ *mvx = *mvy = 0;
+ }
+ else if (rule1 + rule2 + rule3 == 2)
+ {
+ /* two of three are zero */
+ *mvx = (p1x + p2x + p3x);
+ *mvy = (p1y + p2y + p3y);
+ }
+ else
+ {
+ *mvx = ((p1x + p2x + p3x - PV_MAX(p1x, PV_MAX(p2x, p3x)) - PV_MIN(p1x, PV_MIN(p2x, p3x))));
+ *mvy = ((p1y + p2y + p3y - PV_MAX(p1y, PV_MAX(p2y, p3y)) - PV_MIN(p1y, PV_MIN(p2y, p3y))));
+ }
+
+ return;
+}
+
+
+Void WriteMVcomponent(Int f_code, Int dmv, BitstreamEncVideo *bs)
+{
+ Int residual, vlc_code_mag, bits, entry;
+
+ ScaleMVD(f_code, dmv, &residual, &vlc_code_mag);
+
+ if (vlc_code_mag < 0)
+ entry = vlc_code_mag + 65;
+ else
+ entry = vlc_code_mag;
+
+ bits = PutMV(entry, bs);
+
+ if ((f_code != 1) && (vlc_code_mag != 0))
+ {
+ BitstreamPutBits(bs, f_code - 1, residual);
+ bits += f_code - 1;
+ }
+ return;
+}
+
+
+Void
+ScaleMVD(
+ Int f_code, /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048 */
+ Int diff_vector, /* <-- MV Difference commponent in 1/2 units */
+ Int *residual, /* --> value to be FLC coded */
+ Int *vlc_code_mag /* --> value to be VLC coded */
+)
+{
+ Int range;
+ Int scale_factor;
+ Int r_size;
+ Int low;
+ Int high;
+ Int aux;
+
+ r_size = f_code - 1;
+ scale_factor = 1 << r_size;
+ range = 32 * scale_factor;
+ low = -range;
+ high = range - 1;
+
+ if (diff_vector < low)
+ diff_vector += 2 * range;
+ else if (diff_vector > high)
+ diff_vector -= 2 * range;
+
+ if (diff_vector == 0)
+ {
+ *vlc_code_mag = 0;
+ *residual = 0;
+ }
+ else if (scale_factor == 1)
+ {
+ *vlc_code_mag = diff_vector;
+ *residual = 0;
+ }
+ else
+ {
+ aux = PV_ABS(diff_vector) + scale_factor - 1;
+ *vlc_code_mag = aux >> r_size;
+
+ if (diff_vector < 0)
+ *vlc_code_mag = -*vlc_code_mag;
+ *residual = aux & (scale_factor - 1);
+ }
+}
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h
new file mode 100644
index 0000000..3721b6b
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.h
@@ -0,0 +1,42 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _VLC_ENCODE_H_
+#define _VLC_ENCODE_H_
+
+#include "mp4def.h"
+#include "mp4enc_api.h"
+
+Int PutCoeff_Inter(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutCoeff_Intra(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream);
+Int PutMCBPC_Inter(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+Int PutMCBPC_Intra(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
+Int PutMV(Int mvint, BitstreamEncVideo *bitstream);
+Int PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream);
+Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
+Int PutCoeff_Inter_RVLC(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutCoeff_Intra_RVLC(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutRunCoeff_Inter(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutRunCoeff_Intra(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutLevelCoeff_Inter(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+Int PutLevelCoeff_Intra(Int run, Int level, Int last, BitstreamEncVideo *bitstream);
+
+Void MB_CodeCoeff(VideoEncData *video, BitstreamEncVideo *bs);
+Void BlockCodeCoeff(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, UChar Mode, Int rvlc, Int shortVideoHeader);
+#endif /* _VLC_ENCODE_H_ */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h
new file mode 100644
index 0000000..a2f4934
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode_inline.h
@@ -0,0 +1,316 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#ifndef _VLC_ENCODE_INLINE_H_
+#define _VLC_ENCODE_INLINE_H_
+
+#if !defined(PV_ARM_GCC_V5) && !defined(PV_ARM_GCC_V4)
+
+__inline Int zero_run_search(UInt *bitmapzz, Short *dataBlock, RunLevelBlock *RLB, Int nc)
+{
+ Int idx, run, level, j;
+ UInt end, match;
+
+ idx = 0;
+ j = 0;
+ run = 0;
+ match = 1 << 31;
+ if (nc > 32)
+ end = 1;
+ else
+ end = 1 << (32 - nc);
+
+ while (match >= end)
+ {
+ if ((match&bitmapzz[0]) == 0)
+ {
+ run++;
+ j++;
+ match >>= 1;
+ }
+ else
+ {
+ match >>= 1;
+ level = dataBlock[j];
+ dataBlock[j] = 0; /* reset output */
+ j++;
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ }
+ }
+ nc -= 32;
+ if (nc > 0)
+ {
+ match = 1 << 31;
+ end = 1 << (32 - nc);
+ while (match >= end)
+ {
+ if ((match&bitmapzz[1]) == 0)
+ {
+ run++;
+ j++;
+ match >>= 1;
+ }
+ else
+ {
+ match >>= 1;
+ level = dataBlock[j];
+ dataBlock[j] = 0; /* reset output */
+ j++;
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ }
+ }
+ }
+
+ return idx;
+}
+
+#elif defined(__CC_ARM) /* only work with arm v5 */
+
+__inline Int zero_run_search(UInt *bitmapzz, Short *dataBlock, RunLevelBlock *RLB, Int nc)
+{
+ OSCL_UNUSED_ARG(nc);
+ Int idx, run, level, j;
+ UInt end, match;
+ Int zzorder;
+
+ idx = 0;
+ run = 0;
+ j = -1;
+ __asm
+ {
+ ldr match, [bitmapzz]
+ clz run, match
+ }
+
+ zzorder = 0;
+
+ while (run < 32)
+ {
+ __asm
+ {
+ mov end, #0x80000000
+ mov end, end, lsr run /* mask*/
+ bic match, match, end /* remove it from bitmap */
+ mov run, run, lsl #1 /* 05/09/02 */
+ ldrsh level, [dataBlock, run] /* load data */
+ strh zzorder, [dataBlock, run] /* reset output */
+ add j, j, #1
+ rsb run, j, run, lsr #1 /* delta run */
+ add j, j, run /* current position */
+ }
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ __asm
+ {
+ clz run, match
+ }
+ }
+ __asm
+ {
+ ldr match, [bitmapzz, #4]
+ clz run, match
+ }
+
+ while (run < 32)
+ {
+ __asm
+ {
+ mov end, #0x80000000
+ mov end, end, lsr run /* mask*/
+ bic match, match, end /* remove it from bitmap */
+ add run, run, #32 /* current position */
+ mov run, run, lsl #1 /* 09/02/05 */
+ ldrsh level, [dataBlock, run] /* load data */
+ strh zzorder, [dataBlock, run] /* reset output */
+ add j, j, #1
+ rsb run, j, run, lsr #1 /* delta run */
+ add j, j, run /* current position */
+ }
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ __asm
+ {
+ clz run, match
+ }
+ }
+
+ return idx;
+}
+
+#elif ( defined(PV_ARM_GCC_V4) || defined(PV_ARM_GCC_V5) ) /* ARM GNU COMPILER */
+
+__inline Int m4v_enc_clz(UInt temp)
+{
+ register Int rb;
+ register UInt ra = (UInt)temp;
+
+ asm volatile("clz %0, %1"
+ : "=&r"(rb)
+ : "r"(ra)
+ );
+
+ return (rb);
+}
+
+__inline Int zero_run_search(UInt *bitmapzz, Short *dataBlock, RunLevelBlock *RLB, Int nc)
+{
+ OSCL_UNUSED_ARG(nc);
+ Int idx, run, level = 0, j;
+ UInt end = 0, match;
+ Int zzorder;
+
+ idx = 0;
+ run = 0;
+ j = -1;
+ match = *bitmapzz;
+ run = m4v_enc_clz(match);
+
+ zzorder = 0;
+
+ while (run < 32)
+ {
+ asm volatile("mov %0, #0x80000000\n\t"
+ "mov %0, %0, lsr %1\n\t"
+ "bic %2, %2, %0\n\t"
+ "mov %1, %1, lsl #1\n\t"
+ "ldrsh %3, [%6, %1]\n\t"
+ "strh %5, [%6, %1]\n\t"
+ "add %4, %4, #1\n\t"
+ "rsb %1, %4, %1, lsr #1\n\t"
+ "add %4, %4, %1"
+ : "+r"(end), "+r"(run), "+r"(match), "=r"(level), "+r"(j)
+ : "r"(zzorder), "r"(dataBlock));
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ run = m4v_enc_clz(match);
+ }
+ match = bitmapzz[1];
+ run = m4v_enc_clz(match);
+
+ while (run < 32)
+ {
+ asm volatile("mov %0, #0x80000000\n\t"
+ "mov %0, %0, lsr %1\n\t"
+ "bic %2, %2, %0\n\t"
+ "add %1, %1, #32\n\t"
+ "mov %1, %1, lsl #1\n\t"
+ "ldrsh %3, [%6, %1]\n\t"
+ "strh %5, [%6, %1]\n\t"
+ "add %4, %4, #1\n\t"
+ "rsb %1, %4, %1, lsr #1\n\t"
+ "add %4, %4, %1"
+ : "+r"(end), "+r"(run), "+r"(match), "+r"(level), "+r"(j)
+ : "r"(zzorder), "r"(dataBlock));
+ if (level < 0)
+ {
+ RLB->level[idx] = -level;
+ RLB->s[idx] = 1;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ else
+ {
+ RLB->level[idx] = level;
+ RLB->s[idx] = 0;
+ RLB->run[idx] = run;
+ run = 0;
+ idx++;
+ }
+ run = m4v_enc_clz(match);
+ }
+
+ return idx;
+}
+
+#endif
+
+#endif // _VLC_ENCODE_INLINE_H_
+
+
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp
new file mode 100644
index 0000000..47076c3
--- /dev/null
+++ b/media/libstagefright/codecs/m4v_h263/enc/src/vop.cpp
@@ -0,0 +1,581 @@
+/* ------------------------------------------------------------------
+ * Copyright (C) 1998-2009 PacketVideo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ * -------------------------------------------------------------------
+ */
+#include "mp4def.h"
+#include "mp4lib_int.h"
+#include "mp4enc_lib.h"
+#include "bitstream_io.h"
+#include "m4venc_oscl.h"
+
+PV_STATUS EncodeShortHeader(BitstreamEncVideo *stream, Vop *currVop);
+PV_STATUS EncodeVOPHeader(BitstreamEncVideo *stream, Vol *currVol, Vop *currVop);
+PV_STATUS EncodeGOVHeader(BitstreamEncVideo *stream, UInt seconds);
+
+PV_STATUS EncodeVop_BXRC(VideoEncData *video);
+PV_STATUS EncodeVop_NoME(VideoEncData *video);
+
+/* ======================================================================== */
+/* Function : DecodeVop() */
+/* Date : 08/23/2000 */
+/* Purpose : Encode VOP Header */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS EncodeVop(VideoEncData *video)
+{
+
+ PV_STATUS status;
+ Int currLayer = video->currLayer;
+ Vol *currVol = video->vol[currLayer];
+ Vop *currVop = video->currVop;
+// BitstreamEncVideo *stream=video->bitstream1;
+ UChar *Mode = video->headerInfo.Mode;
+ rateControl **rc = video->rc;
+// UInt time=0;
+
+ /*******************/
+ /* Initialize mode */
+ /*******************/
+
+ switch (currVop->predictionType)
+ {
+ case I_VOP:
+ M4VENC_MEMSET(Mode, MODE_INTRA, sizeof(UChar)*currVol->nTotalMB);
+ break;
+ case P_VOP:
+ M4VENC_MEMSET(Mode, MODE_INTER, sizeof(UChar)*currVol->nTotalMB);
+ break;
+ case B_VOP:
+ /*M4VENC_MEMSET(Mode, MODE_INTER_B,sizeof(UChar)*nTotalMB);*/
+ return PV_FAIL;
+ default:
+ return PV_FAIL;
+ }
+
+ /*********************/
+ /* Motion Estimation */
+ /* compute MVs, scene change detection, edge padding, */
+ /* intra refresh, compute block activity */
+ /*********************/
+ MotionEstimation(video); /* do ME for the whole frame */
+
+ /***************************/
+ /* rate Control (assign QP) */
+ /* 4/11/01, clean-up, and put into a separate function */
+ /***************************/
+ status = RC_VopQPSetting(video, rc);
+ if (status == PV_FAIL)
+ return PV_FAIL;
+
+ /**********************/
+ /* Encode VOP */
+ /**********************/
+ if (video->slice_coding) /* end here */
+ {
+ /* initialize state variable for slice-based APIs */
+ video->totalSAD = 0;
+ video->mbnum = 0;
+ video->sliceNo[0] = 0;
+ video->numIntra = 0;
+ video->offset = 0;
+ video->end_of_buf = 0;
+ video->hp_guess = -1;
+ return status;
+ }
+
+ status = EncodeVop_NoME(video);
+
+ /******************************/
+ /* rate control (update stat) */
+ /* 6/2/01 separate function */
+ /******************************/
+
+ RC_VopUpdateStat(video, rc[currLayer]);
+
+ return status;
+}
+
+/* ======================================================================== */
+/* Function : EncodeVop_NoME() */
+/* Date : 08/28/2001 */
+/* History : */
+/* Purpose : EncodeVop without motion est. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+PV_STATUS EncodeVop_NoME(VideoEncData *video)
+{
+ Vop *currVop = video->currVop;
+ Vol *currVol = video->vol[video->currLayer];
+ BitstreamEncVideo *stream = video->bitstream1;
+ Int time = 0; /* follows EncodeVop value */
+ PV_STATUS status = PV_SUCCESS;
+
+ if (currVol->shortVideoHeader) /* Short Video Header = 1 */
+ {
+
+ status = EncodeShortHeader(stream, currVop); /* Encode Short Header */
+
+ video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+
+ status = EncodeFrameCombinedMode(video);
+
+ }
+#ifndef H263_ONLY
+ else /* Short Video Header = 0 */
+ {
+
+ if (currVol->GOVStart && currVop->predictionType == I_VOP)
+ status = EncodeGOVHeader(stream, time); /* Encode GOV Header */
+
+ status = EncodeVOPHeader(stream, currVol, currVop); /* Encode VOP Header */
+
+ video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+
+ if (currVop->vopCoded)
+ {
+ if (!currVol->scalability)
+ {
+ if (currVol->dataPartitioning)
+ {
+ status = EncodeFrameDataPartMode(video); /* Encode Data Partitioning Mode VOP */
+ }
+ else
+ {
+ status = EncodeFrameCombinedMode(video); /* Encode Combined Mode VOP */
+ }
+ }
+ else
+ status = EncodeFrameCombinedMode(video); /* Encode Combined Mode VOP */
+ }
+ else /* Vop Not coded */
+ {
+
+ return status;
+ }
+ }
+#endif /* H263_ONLY */
+ return status;
+
+}
+
+#ifndef NO_SLICE_ENCODE
+/* ======================================================================== */
+/* Function : EncodeSlice() */
+/* Date : 04/19/2002 */
+/* History : */
+/* Purpose : Encode one slice. */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* */
+/* ======================================================================== */
+
+PV_STATUS EncodeSlice(VideoEncData *video)
+{
+ Vop *currVop = video->currVop;
+ Int currLayer = video->currLayer;
+ Vol *currVol = video->vol[currLayer];
+ BitstreamEncVideo *stream = video->bitstream1; /* different from frame-based */
+ Int time = 0; /* follows EncodeVop value */
+ PV_STATUS status = PV_SUCCESS;
+ rateControl **rc = video->rc;
+
+ if (currVol->shortVideoHeader) /* Short Video Header = 1 */
+ {
+
+ if (video->mbnum == 0)
+ {
+ status = EncodeShortHeader(stream, currVop); /* Encode Short Header */
+
+ video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+ }
+
+ status = EncodeSliceCombinedMode(video);
+
+ }
+#ifndef H263_ONLY
+ else /* Short Video Header = 0 */
+ {
+
+ if (video->mbnum == 0)
+ {
+ if (currVol->GOVStart)
+ status = EncodeGOVHeader(stream, time); /* Encode GOV Header */
+
+ status = EncodeVOPHeader(stream, currVol, currVop); /* Encode VOP Header */
+
+ video->header_bits = BitstreamGetPos(stream); /* Header Bits */
+ }
+
+ if (currVop->vopCoded)
+ {
+ if (!currVol->scalability)
+ {
+ if (currVol->dataPartitioning)
+ {
+ status = EncodeSliceDataPartMode(video); /* Encode Data Partitioning Mode VOP */
+ }
+ else
+ {
+ status = EncodeSliceCombinedMode(video); /* Encode Combined Mode VOP */
+ }
+ }
+ else
+ status = EncodeSliceCombinedMode(video); /* Encode Combined Mode VOP */
+ }
+ else /* Vop Not coded */
+ {
+
+ return status;
+ }
+ }
+#endif /* H263_ONLY */
+ if (video->mbnum >= currVol->nTotalMB && status != PV_END_OF_BUF) /* end of Vop */
+ {
+ /******************************/
+ /* rate control (update stat) */
+ /* 6/2/01 separate function */
+ /******************************/
+
+ status = RC_VopUpdateStat(video, rc[currLayer]);
+ }
+
+ return status;
+
+}
+#endif /* NO_SLICE_ENCODE */
+
+#ifndef H263_ONLY
+/* ======================================================================== */
+/* Function : EncodeGOVHeader() */
+/* Date : 08/23/2000 */
+/* Purpose : Encode GOV Header */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+PV_STATUS EncodeGOVHeader(BitstreamEncVideo *stream, UInt seconds)
+{
+ PV_STATUS status;
+// int temp;
+ UInt tmpvar;
+
+ /********************************/
+ /* Group_of_VideoObjectPlane() */
+ /********************************/
+
+ status = BitstreamPutGT16Bits(stream, 32, GROUP_START_CODE);
+ /* time_code */
+ tmpvar = seconds / 3600;
+ status = BitstreamPutBits(stream, 5, tmpvar); /* Hours*/
+
+ tmpvar = (seconds - tmpvar * 3600) / 60;
+ status = BitstreamPutBits(stream, 6, tmpvar); /* Minutes*/
+
+ status = BitstreamPut1Bits(stream, 1); /* Marker*/
+
+ tmpvar = seconds % 60;
+ status = BitstreamPutBits(stream, 6, tmpvar); /* Seconds*/
+
+ status = BitstreamPut1Bits(stream, 1); /* closed_gov */
+ status = BitstreamPut1Bits(stream, 0); /* broken_link */
+ /*temp =*/
+ BitstreamMpeg4ByteAlignStuffing(stream); /* Byte align GOV Header */
+
+ return status;
+}
+
+#ifdef ALLOW_VOP_NOT_CODED
+
+PV_STATUS EncodeVopNotCoded(VideoEncData *video, UChar *bstream, Int *size, ULong modTime)
+{
+ PV_STATUS status;
+ Vol *currVol = video->vol[0];
+ Vop *currVop = video->currVop;
+ BitstreamEncVideo *stream = currVol->stream;
+ UInt frameTick;
+ Int timeInc;
+
+ stream->bitstreamBuffer = bstream;
+ stream->bufferSize = *size;
+ BitstreamEncReset(stream);
+
+ status = BitstreamPutGT16Bits(stream, 32, VOP_START_CODE); /*Start Code for VOP*/
+ status = BitstreamPutBits(stream, 2, P_VOP);/* VOP Coding Type*/
+
+ frameTick = (Int)(((double)(modTime - video->modTimeRef) * currVol->timeIncrementResolution + 500) / 1000);
+ timeInc = frameTick - video->refTick[0];
+ while (timeInc >= currVol->timeIncrementResolution)
+ {
+ timeInc -= currVol->timeIncrementResolution;
+ status = BitstreamPut1Bits(stream, 1);
+ /* do not update refTick and modTimeRef yet, do it after encoding!! */
+ }
+ status = BitstreamPut1Bits(stream, 0);
+ status = BitstreamPut1Bits(stream, 1); /* marker bit */
+ status = BitstreamPutBits(stream, currVol->nbitsTimeIncRes, timeInc); /* vop_time_increment */
+ status = BitstreamPut1Bits(stream, 1); /* marker bit */
+ status = BitstreamPut1Bits(stream, 0); /* vop_coded bit */
+ BitstreamMpeg4ByteAlignStuffing(stream);
+
+ return status;
+}
+#endif
+
+/* ======================================================================== */
+/* Function : EncodeVOPHeader() */
+/* Date : 08/23/2000 */
+/* Purpose : Encode VOP Header */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS EncodeVOPHeader(BitstreamEncVideo *stream, Vol *currVol, Vop *currVop)
+{
+ PV_STATUS status;
+ //int temp;
+
+ int MTB = currVol->moduloTimeBase;
+ /************************/
+ /* VideoObjectPlane() */
+ /************************/
+
+ status = BitstreamPutGT16Bits(stream, 32, VOP_START_CODE); /*Start Code for VOP*/
+ status = BitstreamPutBits(stream, 2, currVop->predictionType);/* VOP Coding Type*/
+
+ currVol->prevModuloTimeBase = currVol->moduloTimeBase;
+
+ while (MTB)
+ {
+ status = BitstreamPut1Bits(stream, 1);
+ MTB--;
+ }
+ status = BitstreamPut1Bits(stream, 0);
+
+ status = BitstreamPut1Bits(stream, 1); /* marker bit */
+ status = BitstreamPutBits(stream, currVol->nbitsTimeIncRes, currVop->timeInc); /* vop_time_increment */
+ status = BitstreamPut1Bits(stream, 1); /* marker bit */
+ status = BitstreamPut1Bits(stream, currVop->vopCoded); /* vop_coded bit */
+ if (currVop->vopCoded == 0)
+ {
+ /*temp =*/
+ BitstreamMpeg4ByteAlignStuffing(stream); /* Byte align VOP Header */
+ return status;
+ }
+ if (currVop->predictionType == P_VOP)
+ status = BitstreamPut1Bits(stream, currVop->roundingType); /* vop_rounding_type */
+
+ status = BitstreamPutBits(stream, 3, currVop->intraDCVlcThr); /* intra_dc_vlc_thr */
+ status = BitstreamPutBits(stream, 5, currVop->quantizer); /* vop_quant */
+
+ if (currVop->predictionType != I_VOP)
+ status = BitstreamPutBits(stream, 3, currVop->fcodeForward); /* vop_fcode_forward */
+ if (currVop->predictionType == B_VOP)
+ status = BitstreamPutBits(stream, 3, currVop->fcodeBackward);/* vop_fcode_backward */
+
+ if (currVol->scalability)
+ /* enhancement_type = 0 */
+ status = BitstreamPutBits(stream, 2, currVop->refSelectCode); /* ref_select_code */
+
+ return status;
+}
+#endif /* H263_ONLY */
+/* ======================================================================== */
+/* Function : EncodeShortHeader() */
+/* Date : 08/23/2000 */
+/* Purpose : Encode VOP Header */
+/* In/out : */
+/* Return : */
+/* Modified : */
+/* ======================================================================== */
+
+PV_STATUS EncodeShortHeader(BitstreamEncVideo *stream, Vop *currVop)
+{
+
+ PV_STATUS status;
+
+ status = BitstreamPutGT16Bits(stream, 22, SHORT_VIDEO_START_MARKER); /* Short_video_start_marker */
+ status = BitstreamPutBits(stream, 8, currVop->temporalRef); /* temporal_reference */
+ status = BitstreamPut1Bits(stream, 1); /* marker bit */
+ status = BitstreamPut1Bits(stream, 0); /* zero bit */
+ status = BitstreamPut1Bits(stream, 0); /* split_screen_indicator=0*/
+ status = BitstreamPut1Bits(stream, 0); /* document_camera_indicator=0*/
+ status = BitstreamPut1Bits(stream, 0); /* full_picture_freeze_release=0*/
+
+ switch (currVop->width)
+ {
+ case 128:
+ if (currVop->height == 96)
+ status = BitstreamPutBits(stream, 3, 1); /* source_format = 1 */
+ else
+ {
+ status = PV_FAIL;
+ return status;
+ }
+ break;
+
+ case 176:
+ if (currVop->height == 144)
+ status = BitstreamPutBits(stream, 3, 2); /* source_format = 2 */
+ else
+ {
+ status = PV_FAIL;
+ return status;
+ }
+ break;
+
+ case 352:
+ if (currVop->height == 288)
+ status = BitstreamPutBits(stream, 3, 3); /* source_format = 3 */
+ else
+ {
+ status = PV_FAIL;
+ return status;
+ }
+ break;
+
+ case 704:
+ if (currVop->height == 576)
+ status = BitstreamPutBits(stream, 3, 4); /* source_format = 4 */
+ else
+ {
+ status = PV_FAIL;
+ return status;
+ }
+ break;
+
+ case 1408:
+ if (currVop->height == 1152)
+ status = BitstreamPutBits(stream, 3, 5); /* source_format = 5 */
+ else
+ {
+ status = PV_FAIL;
+ return status;
+ }
+ break;
+
+ default:
+ status = PV_FAIL;
+ return status;
+ }
+
+
+ status = BitstreamPut1Bits(stream, currVop->predictionType); /* picture_coding type */
+ status = BitstreamPutBits(stream, 4, 0); /* four_reserved_zero_bits */
+ status = BitstreamPutBits(stream, 5, currVop->quantizer); /* vop_quant*/
+ status = BitstreamPut1Bits(stream, 0); /* zero_bit*/
+ status = BitstreamPut1Bits(stream, 0); /* pei=0 */
+
+ return status;
+}
+
+#ifndef H263_ONLY
+/* ======================================================================== */
+/* Function : EncodeVideoPacketHeader() */
+/* Date : 09/05/2000 */
+/* History : */
+/* Purpose : Encode a frame of MPEG4 bitstream in Combined mode. */
+/* In/out : */
+/* Return : */
+/* Modified : 04/25/2002 */
+/* Add bitstream structure as input argument */
+/* */
+/* ======================================================================== */
+PV_STATUS EncodeVideoPacketHeader(VideoEncData *video, int MB_number,
+ int quant_scale, Int insert)
+{
+// PV_STATUS status=PV_SUCCESS;
+ int fcode;
+ Vop *currVop = video->currVop;
+ Vol *currVol = video->vol[video->currLayer];
+ BitstreamEncVideo *bs, tmp;
+ UChar buffer[30];
+
+ if (insert) /* insert packet header to the beginning of bs1 */
+ {
+ tmp.bitstreamBuffer = buffer; /* use temporary buffer */
+ tmp.bufferSize = 30;
+ BitstreamEncReset(&tmp);
+ bs = &tmp;
+ }
+ else
+ bs = video->bitstream1;
+
+
+ if (currVop->predictionType == I_VOP)
+ BitstreamPutGT16Bits(bs, 17, 1); /* resync_marker I_VOP */
+ else if (currVop->predictionType == P_VOP)
+ {
+ fcode = currVop->fcodeForward;
+ BitstreamPutGT16Bits(bs, 16 + fcode, 1); /* resync_marker P_VOP */
+
+ }
+ else
+ {
+ fcode = currVop->fcodeForward;
+ if (currVop->fcodeBackward > fcode)
+ fcode = currVop->fcodeBackward;
+ BitstreamPutGT16Bits(bs, 16 + fcode, 1); /* resync_marker B_VOP */
+ }
+
+ BitstreamPutBits(bs, currVol->nBitsForMBID, MB_number); /* resync_marker */
+ BitstreamPutBits(bs, 5, quant_scale); /* quant_scale */
+ BitstreamPut1Bits(bs, 0); /* header_extension_code = 0 */
+
+ if (0) /* header_extension_code = 1 */
+ {
+ /* NEED modulo_time_base code here ... default 0x01 belo*/
+ /*status =*/
+ BitstreamPut1Bits(bs, 1);
+ /*status = */
+ BitstreamPut1Bits(bs, 0);
+
+ /*status = */
+ BitstreamPut1Bits(bs, 1); /* marker bit */
+ /*status = */
+ BitstreamPutBits(bs, currVol->nbitsTimeIncRes, currVop->timeInc); /* vop_time_increment */
+ /*status = */
+ BitstreamPut1Bits(bs, 1); /* marker bit */
+
+ /*status = */
+ BitstreamPutBits(bs, 2, currVop->predictionType);/* VOP Coding Type*/
+
+ /*status = */
+ BitstreamPutBits(bs, 3, currVop->intraDCVlcThr); /* intra_dc_vlc_thr */
+
+ if (currVop->predictionType != I_VOP)
+ /*status = */ BitstreamPutBits(bs, 3, currVop->fcodeForward);
+ if (currVop->predictionType == B_VOP)
+ /*status = */ BitstreamPutBits(bs, 3, currVop->fcodeBackward);
+ }
+#ifndef NO_SLICE_ENCODE
+ if (insert)
+ BitstreamPrependPacket(video->bitstream1, bs);
+#endif
+ return PV_SUCCESS;
+}
+
+#endif /* H263_ONLY */
+
+
+
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
index efcb476..c4a8280 100644
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -27,13 +27,35 @@ namespace android {
MP3Decoder::MP3Decoder(const sp<MediaSource> &source)
: mSource(source),
+ mNumChannels(0),
mStarted(false),
mBufferGroup(NULL),
mConfig(new tPVMP3DecoderExternal),
mDecoderBuf(NULL),
mAnchorTimeUs(0),
- mNumSamplesOutput(0),
+ mNumFramesOutput(0),
mInputBuffer(NULL) {
+ init();
+}
+
+void MP3Decoder::init() {
+ sp<MetaData> srcFormat = mSource->getFormat();
+
+ int32_t sampleRate;
+ CHECK(srcFormat->findInt32(kKeyChannelCount, &mNumChannels));
+ CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
+
+ mMeta = new MetaData;
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
+ mMeta->setInt32(kKeyChannelCount, mNumChannels);
+ mMeta->setInt32(kKeySampleRate, sampleRate);
+
+ int64_t durationUs;
+ if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+ mMeta->setInt64(kKeyDuration, durationUs);
+ }
+
+ mMeta->setCString(kKeyDecoderComponent, "MP3Decoder");
}
MP3Decoder::~MP3Decoder() {
@@ -62,7 +84,7 @@ status_t MP3Decoder::start(MetaData *params) {
mSource->start();
mAnchorTimeUs = 0;
- mNumSamplesOutput = 0;
+ mNumFramesOutput = 0;
mStarted = true;
return OK;
@@ -90,26 +112,7 @@ status_t MP3Decoder::stop() {
}
sp<MetaData> MP3Decoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t numChannels;
- int32_t sampleRate;
- CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- meta->setInt32(kKeyChannelCount, numChannels);
- meta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "MP3Decoder");
-
- return meta;
+ return mMeta;
}
status_t MP3Decoder::read(
@@ -119,10 +122,11 @@ status_t MP3Decoder::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
CHECK(seekTimeUs >= 0);
- mNumSamplesOutput = 0;
+ mNumFramesOutput = 0;
if (mInputBuffer) {
mInputBuffer->release();
@@ -142,7 +146,7 @@ status_t MP3Decoder::read(
int64_t timeUs;
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
mAnchorTimeUs = timeUs;
- mNumSamplesOutput = 0;
+ mNumFramesOutput = 0;
} else {
// We must have a new timestamp after seeking.
CHECK(seekTimeUs < 0);
@@ -179,7 +183,7 @@ status_t MP3Decoder::read(
// This is recoverable, just ignore the current frame and
// play silence instead.
- memset(buffer->data(), 0, mConfig->outputFrameSize);
+ memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t));
mConfig->inputBufferUsedLength = mInputBuffer->range_length();
}
@@ -198,9 +202,9 @@ status_t MP3Decoder::read(
buffer->meta_data()->setInt64(
kKeyTime,
mAnchorTimeUs
- + (mNumSamplesOutput * 1000000) / mConfig->samplingRate);
+ + (mNumFramesOutput * 1000000) / mConfig->samplingRate);
- mNumSamplesOutput += mConfig->outputFrameSize / sizeof(int16_t);
+ mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
*out = buffer;
diff --git a/media/libstagefright/codecs/on2/Android.mk b/media/libstagefright/codecs/on2/Android.mk
new file mode 100644
index 0000000..2e43120
--- /dev/null
+++ b/media/libstagefright/codecs/on2/Android.mk
@@ -0,0 +1,4 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libstagefright/codecs/on2/dec/Android.mk b/media/libstagefright/codecs/on2/dec/Android.mk
new file mode 100644
index 0000000..03dfb75
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ VPXDecoder.cpp
+
+LOCAL_MODULE := libstagefright_vpxdec
+
+LOCAL_C_INCLUDES := \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/external/libvpx \
+ $(TOP)/external/libvpx/vpx_codec \
+ $(TOP)/external/libvpx/vpx_ports
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
new file mode 100644
index 0000000..fbc97f4
--- /dev/null
+++ b/media/libstagefright/codecs/on2/dec/VPXDecoder.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "VPXDecoder"
+#include <utils/Log.h>
+
+#include "VPXDecoder.h"
+
+#include <OMX_Component.h>
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "vpx_codec/vpx_decoder.h"
+#include "vp8/vp8dx.h"
+
+namespace android {
+
+VPXDecoder::VPXDecoder(const sp<MediaSource> &source)
+ : mSource(source),
+ mStarted(false),
+ mBufferSize(0),
+ mCtx(NULL),
+ mBufferGroup(NULL),
+ mTargetTimeUs(-1) {
+ sp<MetaData> inputFormat = source->getFormat();
+ const char *mime;
+ CHECK(inputFormat->findCString(kKeyMIMEType, &mime));
+ CHECK(!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_VPX));
+
+ CHECK(inputFormat->findInt32(kKeyWidth, &mWidth));
+ CHECK(inputFormat->findInt32(kKeyHeight, &mHeight));
+
+ mBufferSize = (mWidth * mHeight * 3) / 2;
+
+ mFormat = new MetaData;
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+ mFormat->setInt32(kKeyWidth, mWidth);
+ mFormat->setInt32(kKeyHeight, mHeight);
+ mFormat->setInt32(kKeyColorFormat, OMX_COLOR_FormatYUV420Planar);
+ mFormat->setCString(kKeyDecoderComponent, "VPXDecoder");
+
+ int64_t durationUs;
+ if (inputFormat->findInt64(kKeyDuration, &durationUs)) {
+ mFormat->setInt64(kKeyDuration, durationUs);
+ }
+}
+
+VPXDecoder::~VPXDecoder() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t VPXDecoder::start(MetaData *) {
+ if (mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ status_t err = mSource->start();
+
+ if (err != OK) {
+ return err;
+ }
+
+ mCtx = new vpx_codec_ctx_t;
+ if (vpx_codec_dec_init(
+ (vpx_codec_ctx_t *)mCtx, &vpx_codec_vp8_dx_algo, NULL, 0)) {
+ LOGE("on2 decoder failed to initialize.");
+
+ mSource->stop();
+
+ return UNKNOWN_ERROR;
+ }
+
+ mBufferGroup = new MediaBufferGroup;
+ mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+ mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+ mTargetTimeUs = -1;
+
+ mStarted = true;
+
+ return OK;
+}
+
+status_t VPXDecoder::stop() {
+ if (!mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ delete mBufferGroup;
+ mBufferGroup = NULL;
+
+ vpx_codec_destroy((vpx_codec_ctx_t *)mCtx);
+ delete (vpx_codec_ctx_t *)mCtx;
+ mCtx = NULL;
+
+ mSource->stop();
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> VPXDecoder::getFormat() {
+ return mFormat;
+}
+
+status_t VPXDecoder::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ bool seeking = false;
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+ seeking = true;
+ }
+
+ MediaBuffer *input;
+ status_t err = mSource->read(&input, options);
+
+ if (err != OK) {
+ return err;
+ }
+
+ LOGV("read %d bytes from source\n", input->range_length());
+
+ if (seeking) {
+ int64_t targetTimeUs;
+ if (input->meta_data()->findInt64(kKeyTargetTime, &targetTimeUs)
+ && targetTimeUs >= 0) {
+ mTargetTimeUs = targetTimeUs;
+ } else {
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (vpx_codec_decode(
+ (vpx_codec_ctx_t *)mCtx,
+ (uint8_t *)input->data() + input->range_offset(),
+ input->range_length(),
+ NULL,
+ 0)) {
+ LOGE("on2 decoder failed to decode frame.");
+ input->release();
+ input = NULL;
+
+ return UNKNOWN_ERROR;
+ }
+
+ LOGV("successfully decoded 1 or more frames.");
+
+ int64_t timeUs;
+ CHECK(input->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ input->release();
+ input = NULL;
+
+ bool skipFrame = false;
+
+ if (mTargetTimeUs >= 0) {
+ CHECK(timeUs <= mTargetTimeUs);
+
+ if (timeUs < mTargetTimeUs) {
+ // We're still waiting for the frame with the matching
+ // timestamp and we won't return the current one.
+ skipFrame = true;
+
+ LOGV("skipping frame at %lld us", timeUs);
+ } else {
+ LOGV("found target frame at %lld us", timeUs);
+
+ mTargetTimeUs = -1;
+ }
+ }
+
+ if (skipFrame) {
+ *out = new MediaBuffer(0);
+ return OK;
+ }
+
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t *img = vpx_codec_get_frame((vpx_codec_ctx_t *)mCtx, &iter);
+
+ if (img == NULL) {
+ LOGI("on2 decoder did not return a frame.");
+
+ *out = new MediaBuffer(0);
+ return OK;
+ }
+
+ CHECK_EQ(img->fmt, IMG_FMT_I420);
+
+ int32_t width = img->d_w;
+ int32_t height = img->d_h;
+
+ if (width != mWidth || height != mHeight) {
+ LOGI("Image dimensions changed, width = %d, height = %d",
+ width, height);
+
+ mWidth = width;
+ mHeight = height;
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+
+ mBufferSize = (mWidth * mHeight * 3) / 2;
+ delete mBufferGroup;
+ mBufferGroup = new MediaBufferGroup;
+ mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+ mBufferGroup->add_buffer(new MediaBuffer(mBufferSize));
+
+ return INFO_FORMAT_CHANGED;
+ }
+
+ MediaBuffer *output;
+ CHECK_EQ(mBufferGroup->acquire_buffer(&output), OK);
+
+ const uint8_t *srcLine = (const uint8_t *)img->planes[PLANE_Y];
+ uint8_t *dst = (uint8_t *)output->data();
+ for (size_t i = 0; i < img->d_h; ++i) {
+ memcpy(dst, srcLine, img->d_w);
+
+ srcLine += img->stride[PLANE_Y];
+ dst += img->d_w;
+ }
+
+ srcLine = (const uint8_t *)img->planes[PLANE_U];
+ for (size_t i = 0; i < img->d_h / 2; ++i) {
+ memcpy(dst, srcLine, img->d_w / 2);
+
+ srcLine += img->stride[PLANE_U];
+ dst += img->d_w / 2;
+ }
+
+ srcLine = (const uint8_t *)img->planes[PLANE_V];
+ for (size_t i = 0; i < img->d_h / 2; ++i) {
+ memcpy(dst, srcLine, img->d_w / 2);
+
+ srcLine += img->stride[PLANE_V];
+ dst += img->d_w / 2;
+ }
+
+ output->set_range(0, (width * height * 3) / 2);
+
+ output->meta_data()->setInt64(kKeyTime, timeUs);
+
+ *out = output;
+
+ return OK;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
index df3f16a..53f0638 100644
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
@@ -200,7 +200,8 @@ status_t VorbisDecoder::read(
*out = NULL;
int64_t seekTimeUs;
- if (options && options->getSeekTo(&seekTimeUs)) {
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
CHECK(seekTimeUs >= 0);
mNumFramesOutput = 0;
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index e74782f..5b16997 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -42,6 +42,7 @@ bool ColorConverter::isValid() const {
case OMX_COLOR_FormatYUV420Planar:
case OMX_COLOR_FormatCbYCrY:
case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+ case OMX_COLOR_FormatYUV420SemiPlanar:
return true;
default:
@@ -71,6 +72,11 @@ void ColorConverter::convert(
width, height, srcBits, srcSkip, dstBits, dstSkip);
break;
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ convertYUV420SemiPlanar(
+ width, height, srcBits, srcSkip, dstBits, dstSkip);
+ break;
+
default:
{
CHECK(!"Should not be here. Unknown color conversion.");
@@ -279,6 +285,68 @@ void ColorConverter::convertQCOMYUV420SemiPlanar(
}
}
+void ColorConverter::convertYUV420SemiPlanar(
+ size_t width, size_t height,
+ const void *srcBits, size_t srcSkip,
+ void *dstBits, size_t dstSkip) {
+ CHECK_EQ(srcSkip, 0); // Doesn't really make sense for YUV formats.
+ CHECK(dstSkip >= width * 2);
+ CHECK((dstSkip & 3) == 0);
+
+ uint8_t *kAdjustedClip = initClip();
+
+ uint32_t *dst_ptr = (uint32_t *)dstBits;
+ const uint8_t *src_y = (const uint8_t *)srcBits;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + width * height;
+
+ for (size_t y = 0; y < height; ++y) {
+ for (size_t x = 0; x < width; x += 2) {
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
+
+ signed v = (signed)src_u[x & ~1] - 128;
+ signed u = (signed)src_u[(x & ~1) + 1] - 128;
+
+ signed u_b = u * 517;
+ signed u_g = -u * 100;
+ signed v_g = -v * 208;
+ signed v_r = v * 409;
+
+ signed tmp1 = y1 * 298;
+ signed b1 = (tmp1 + u_b) / 256;
+ signed g1 = (tmp1 + v_g + u_g) / 256;
+ signed r1 = (tmp1 + v_r) / 256;
+
+ signed tmp2 = y2 * 298;
+ signed b2 = (tmp2 + u_b) / 256;
+ signed g2 = (tmp2 + v_g + u_g) / 256;
+ signed r2 = (tmp2 + v_r) / 256;
+
+ uint32_t rgb1 =
+ ((kAdjustedClip[b1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[r1] >> 3);
+
+ uint32_t rgb2 =
+ ((kAdjustedClip[b2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[r2] >> 3);
+
+ dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+ }
+
+ src_y += width;
+
+ if (y & 1) {
+ src_u += width;
+ }
+
+ dst_ptr += dstSkip / 4;
+ }
+}
+
uint8_t *ColorConverter::initClip() {
static const signed kClipMin = -278;
static const signed kClipMax = 535;
diff --git a/media/libstagefright/foundation/AAtomizer.cpp b/media/libstagefright/foundation/AAtomizer.cpp
new file mode 100644
index 0000000..b7b9e9f
--- /dev/null
+++ b/media/libstagefright/foundation/AAtomizer.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/types.h>
+
+#include "AAtomizer.h"
+
+namespace android {
+
+// static
+AAtomizer AAtomizer::gAtomizer;
+
+// static
+const char *AAtomizer::Atomize(const char *name) {
+ return gAtomizer.atomize(name);
+}
+
+AAtomizer::AAtomizer() {
+ for (size_t i = 0; i < 128; ++i) {
+ mAtoms.push(List<AString>());
+ }
+}
+
+const char *AAtomizer::atomize(const char *name) {
+ Mutex::Autolock autoLock(mLock);
+
+ const size_t n = mAtoms.size();
+ size_t index = AAtomizer::Hash(name) % n;
+ List<AString> &entry = mAtoms.editItemAt(index);
+ List<AString>::iterator it = entry.begin();
+ while (it != entry.end()) {
+ if ((*it) == name) {
+ return (*it).c_str();
+ }
+ ++it;
+ }
+
+ entry.push_back(AString(name));
+
+ return (*--entry.end()).c_str();
+}
+
+// static
+uint32_t AAtomizer::Hash(const char *s) {
+ uint32_t sum = 0;
+ while (*s != '\0') {
+ sum = (sum * 31) + *s;
+ ++s;
+ }
+
+ return sum;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
new file mode 100644
index 0000000..6173db4
--- /dev/null
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ABuffer.h"
+
+#include "ADebug.h"
+#include "ALooper.h"
+#include "AMessage.h"
+
+namespace android {
+
+ABuffer::ABuffer(size_t capacity)
+ : mData(malloc(capacity)),
+ mCapacity(capacity),
+ mRangeOffset(0),
+ mRangeLength(capacity),
+ mInt32Data(0),
+ mOwnsData(true) {
+}
+
+ABuffer::ABuffer(void *data, size_t capacity)
+ : mData(data),
+ mCapacity(capacity),
+ mRangeOffset(0),
+ mRangeLength(capacity),
+ mInt32Data(0),
+ mOwnsData(false) {
+}
+
+ABuffer::~ABuffer() {
+ if (mOwnsData) {
+ if (mData != NULL) {
+ free(mData);
+ mData = NULL;
+ }
+ }
+
+ if (mFarewell != NULL) {
+ mFarewell->post();
+ }
+}
+
+void ABuffer::setRange(size_t offset, size_t size) {
+ CHECK_LE(offset, mCapacity);
+ CHECK_LE(offset + size, mCapacity);
+
+ mRangeOffset = offset;
+ mRangeLength = size;
+}
+
+void ABuffer::setFarewellMessage(const sp<AMessage> msg) {
+ mFarewell = msg;
+}
+
+sp<AMessage> ABuffer::meta() {
+ if (mMeta == NULL) {
+ mMeta = new AMessage;
+ }
+ return mMeta;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/libstagefright/foundation/ADebug.cpp
new file mode 100644
index 0000000..16f8b22
--- /dev/null
+++ b/media/libstagefright/foundation/ADebug.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ADebug.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef ANDROID
+#include <cutils/log.h>
+#endif
+
+namespace android {
+
+Logger::Logger(LogType type)
+ : mLogType(type) {
+ switch (mLogType) {
+ case VERBOSE:
+ mMessage = "V ";
+ break;
+ case INFO:
+ mMessage = "I ";
+ break;
+ case WARNING:
+ mMessage = "W ";
+ break;
+ case ERROR:
+ mMessage = "E ";
+ break;
+ case FATAL:
+ mMessage = "F ";
+ break;
+
+ default:
+ break;
+ }
+}
+
+Logger::~Logger() {
+ if (mLogType == VERBOSE) {
+ return;
+ }
+
+ mMessage.append("\n");
+
+#if defined(ANDROID) && 1
+ LOG_PRI(ANDROID_LOG_INFO, "ADebug", "%s", mMessage.c_str());
+#else
+ fprintf(stderr, mMessage.c_str());
+ fflush(stderr);
+#endif
+
+ if (mLogType == FATAL) {
+ abort();
+ }
+}
+
+const char *LeafName(const char *s) {
+ const char *lastSlash = strrchr(s, '/');
+ return lastSlash != NULL ? lastSlash + 1 : s;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/AHandler.cpp b/media/libstagefright/foundation/AHandler.cpp
new file mode 100644
index 0000000..bd5f7e9
--- /dev/null
+++ b/media/libstagefright/foundation/AHandler.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AHandler"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AHandler.h>
+
+#include <media/stagefright/foundation/ALooperRoster.h>
+
+namespace android {
+
+sp<ALooper> AHandler::looper() {
+ extern ALooperRoster gLooperRoster;
+
+ return gLooperRoster.findLooper(id());
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/libstagefright/foundation/ALooper.cpp
new file mode 100644
index 0000000..77afb01
--- /dev/null
+++ b/media/libstagefright/foundation/ALooper.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ALooper"
+#include <utils/Log.h>
+
+#include <sys/time.h>
+
+#include "ALooper.h"
+
+#include "AHandler.h"
+#include "ALooperRoster.h"
+#include "AMessage.h"
+
+namespace android {
+
+ALooperRoster gLooperRoster;
+
+struct ALooper::LooperThread : public Thread {
+ LooperThread(ALooper *looper, bool canCallJava)
+ : Thread(canCallJava),
+ mLooper(looper) {
+ }
+
+ virtual bool threadLoop() {
+ return mLooper->loop();
+ }
+
+protected:
+ virtual ~LooperThread() {}
+
+private:
+ ALooper *mLooper;
+
+ DISALLOW_EVIL_CONSTRUCTORS(LooperThread);
+};
+
+// static
+int64_t ALooper::GetNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_sec * 1000000ll + tv.tv_usec;
+}
+
+ALooper::ALooper()
+ : mRunningLocally(false) {
+}
+
+ALooper::~ALooper() {
+ stop();
+}
+
+ALooper::handler_id ALooper::registerHandler(const sp<AHandler> &handler) {
+ return gLooperRoster.registerHandler(this, handler);
+}
+
+void ALooper::unregisterHandler(handler_id handlerID) {
+ gLooperRoster.unregisterHandler(handlerID);
+}
+
+status_t ALooper::start(
+ bool runOnCallingThread, bool canCallJava, int32_t priority) {
+ if (runOnCallingThread) {
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mThread != NULL || mRunningLocally) {
+ return INVALID_OPERATION;
+ }
+
+ mRunningLocally = true;
+ }
+
+ do {
+ } while (loop());
+
+ return OK;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mThread != NULL || mRunningLocally) {
+ return INVALID_OPERATION;
+ }
+
+ mThread = new LooperThread(this, canCallJava);
+
+ status_t err = mThread->run("ALooper", priority);
+ if (err != OK) {
+ mThread.clear();
+ }
+
+ return err;
+}
+
+status_t ALooper::stop() {
+ sp<LooperThread> thread;
+ bool runningLocally;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ thread = mThread;
+ runningLocally = mRunningLocally;
+ mThread.clear();
+ mRunningLocally = false;
+ }
+
+ if (thread == NULL && !runningLocally) {
+ return INVALID_OPERATION;
+ }
+
+ if (thread != NULL) {
+ thread->requestExit();
+ }
+
+ mQueueChangedCondition.signal();
+
+ if (!runningLocally) {
+ thread->requestExitAndWait();
+ }
+
+ return OK;
+}
+
+void ALooper::post(const sp<AMessage> &msg, int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+
+ int64_t whenUs;
+ if (delayUs > 0) {
+ whenUs = GetNowUs() + delayUs;
+ } else {
+ whenUs = GetNowUs();
+ }
+
+ List<Event>::iterator it = mEventQueue.begin();
+ while (it != mEventQueue.end() && (*it).mWhenUs <= whenUs) {
+ ++it;
+ }
+
+ Event event;
+ event.mWhenUs = whenUs;
+ event.mMessage = msg;
+
+ if (it == mEventQueue.begin()) {
+ mQueueChangedCondition.signal();
+ }
+
+ mEventQueue.insert(it, event);
+}
+
+bool ALooper::loop() {
+ Event event;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (mThread == NULL && !mRunningLocally) {
+ return false;
+ }
+ if (mEventQueue.empty()) {
+ mQueueChangedCondition.wait(mLock);
+ return true;
+ }
+ int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
+ int64_t nowUs = GetNowUs();
+
+ if (whenUs > nowUs) {
+ int64_t delayUs = whenUs - nowUs;
+ mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
+
+ return true;
+ }
+
+ event = *mEventQueue.begin();
+ mEventQueue.erase(mEventQueue.begin());
+ }
+
+ gLooperRoster.deliverMessage(event.mMessage);
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/libstagefright/foundation/ALooperRoster.cpp
new file mode 100644
index 0000000..65f7593
--- /dev/null
+++ b/media/libstagefright/foundation/ALooperRoster.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ALooperRoster"
+#include <utils/Log.h>
+
+#include "ALooperRoster.h"
+
+#include "ADebug.h"
+#include "AHandler.h"
+#include "AMessage.h"
+
+namespace android {
+
+ALooperRoster::ALooperRoster()
+ : mNextHandlerID(1) {
+}
+
+ALooper::handler_id ALooperRoster::registerHandler(
+ const sp<ALooper> looper, const sp<AHandler> &handler) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (handler->id() != 0) {
+ CHECK(!"A handler must only be registered once.");
+ return INVALID_OPERATION;
+ }
+
+ HandlerInfo info;
+ info.mLooper = looper;
+ info.mHandler = handler;
+ ALooper::handler_id handlerID = mNextHandlerID++;
+ mHandlers.add(handlerID, info);
+
+ handler->setID(handlerID);
+
+ return handlerID;
+}
+
+void ALooperRoster::unregisterHandler(ALooper::handler_id handlerID) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mHandlers.indexOfKey(handlerID);
+ CHECK_GE(index, 0);
+
+ const HandlerInfo &info = mHandlers.valueAt(index);
+
+ sp<AHandler> handler = info.mHandler.promote();
+
+ if (handler != NULL) {
+ handler->setID(0);
+ }
+
+ mHandlers.removeItemsAt(index);
+}
+
+void ALooperRoster::postMessage(
+ const sp<AMessage> &msg, int64_t delayUs) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mHandlers.indexOfKey(msg->target());
+
+ if (index < 0) {
+ LOG(WARNING) << "failed to post message. Target handler not registered.";
+ return;
+ }
+
+ const HandlerInfo &info = mHandlers.valueAt(index);
+
+ sp<ALooper> looper = info.mLooper.promote();
+
+ if (looper == NULL) {
+ LOG(WARNING) << "failed to post message. "
+ "Target handler still registered, but object gone.";
+
+ mHandlers.removeItemsAt(index);
+ return;
+ }
+
+ looper->post(msg, delayUs);
+}
+
+void ALooperRoster::deliverMessage(const sp<AMessage> &msg) {
+ sp<AHandler> handler;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mHandlers.indexOfKey(msg->target());
+
+ if (index < 0) {
+ LOG(WARNING) << "failed to deliver message. "
+ << "Target handler not registered.";
+ return;
+ }
+
+ const HandlerInfo &info = mHandlers.valueAt(index);
+ handler = info.mHandler.promote();
+
+ if (handler == NULL) {
+ LOG(WARNING) << "failed to deliver message. "
+ "Target handler registered, but object gone.";
+
+ mHandlers.removeItemsAt(index);
+ return;
+ }
+ }
+
+ handler->onMessageReceived(msg);
+}
+
+sp<ALooper> ALooperRoster::findLooper(ALooper::handler_id handlerID) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mHandlers.indexOfKey(handlerID);
+
+ if (index < 0) {
+ return NULL;
+ }
+
+ sp<ALooper> looper = mHandlers.valueAt(index).mLooper.promote();
+
+ if (looper == NULL) {
+ mHandlers.removeItemsAt(index);
+ return NULL;
+ }
+
+ return looper;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
new file mode 100644
index 0000000..26c6d42
--- /dev/null
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AMessage.h"
+
+#include <ctype.h>
+
+#include "AAtomizer.h"
+#include "ADebug.h"
+#include "ALooperRoster.h"
+#include "AString.h"
+
+namespace android {
+
+AMessage::AMessage(uint32_t what, ALooper::handler_id target)
+ : mWhat(what),
+ mTarget(target),
+ mNumItems(0) {
+}
+
+AMessage::~AMessage() {
+ clear();
+}
+
+void AMessage::setWhat(uint32_t what) {
+ mWhat = what;
+}
+
+uint32_t AMessage::what() const {
+ return mWhat;
+}
+
+void AMessage::setTarget(ALooper::handler_id handlerID) {
+ mTarget = handlerID;
+}
+
+ALooper::handler_id AMessage::target() const {
+ return mTarget;
+}
+
+void AMessage::clear() {
+ for (size_t i = 0; i < mNumItems; ++i) {
+ Item *item = &mItems[i];
+ freeItem(item);
+ }
+ mNumItems = 0;
+}
+
+void AMessage::freeItem(Item *item) {
+ switch (item->mType) {
+ case kTypeString:
+ {
+ delete item->u.stringValue;
+ break;
+ }
+
+ case kTypeObject:
+ case kTypeMessage:
+ {
+ if (item->u.refValue != NULL) {
+ item->u.refValue->decStrong(this);
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+AMessage::Item *AMessage::allocateItem(const char *name) {
+ name = AAtomizer::Atomize(name);
+
+ size_t i = 0;
+ while (i < mNumItems && mItems[i].mName != name) {
+ ++i;
+ }
+
+ Item *item;
+
+ if (i < mNumItems) {
+ item = &mItems[i];
+ freeItem(item);
+ } else {
+ CHECK(mNumItems < kMaxNumItems);
+ i = mNumItems++;
+ item = &mItems[i];
+
+ item->mName = name;
+ }
+
+ return item;
+}
+
+const AMessage::Item *AMessage::findItem(
+ const char *name, Type type) const {
+ name = AAtomizer::Atomize(name);
+
+ for (size_t i = 0; i < mNumItems; ++i) {
+ const Item *item = &mItems[i];
+
+ if (item->mName == name) {
+ return item->mType == type ? item : NULL;
+ }
+ }
+
+ return NULL;
+}
+
+#define BASIC_TYPE(NAME,FIELDNAME,TYPENAME) \
+void AMessage::set##NAME(const char *name, TYPENAME value) { \
+ Item *item = allocateItem(name); \
+ \
+ item->mType = kType##NAME; \
+ item->u.FIELDNAME = value; \
+} \
+ \
+bool AMessage::find##NAME(const char *name, TYPENAME *value) const { \
+ const Item *item = findItem(name, kType##NAME); \
+ if (item) { \
+ *value = item->u.FIELDNAME; \
+ return true; \
+ } \
+ return false; \
+}
+
+BASIC_TYPE(Int32,int32Value,int32_t)
+BASIC_TYPE(Int64,int64Value,int64_t)
+BASIC_TYPE(Size,sizeValue,size_t)
+BASIC_TYPE(Float,floatValue,float)
+BASIC_TYPE(Double,doubleValue,double)
+BASIC_TYPE(Pointer,ptrValue,void *)
+
+#undef BASIC_TYPE
+
+void AMessage::setString(
+ const char *name, const char *s, ssize_t len) {
+ Item *item = allocateItem(name);
+ item->mType = kTypeString;
+ item->u.stringValue = new AString(s, len < 0 ? strlen(s) : len);
+}
+
+void AMessage::setObject(const char *name, const sp<RefBase> &obj) {
+ Item *item = allocateItem(name);
+ item->mType = kTypeObject;
+
+ if (obj != NULL) { obj->incStrong(this); }
+ item->u.refValue = obj.get();
+}
+
+void AMessage::setMessage(const char *name, const sp<AMessage> &obj) {
+ Item *item = allocateItem(name);
+ item->mType = kTypeMessage;
+
+ if (obj != NULL) { obj->incStrong(this); }
+ item->u.refValue = obj.get();
+}
+
+bool AMessage::findString(const char *name, AString *value) const {
+ const Item *item = findItem(name, kTypeString);
+ if (item) {
+ *value = *item->u.stringValue;
+ return true;
+ }
+ return false;
+}
+
+bool AMessage::findObject(const char *name, sp<RefBase> *obj) const {
+ const Item *item = findItem(name, kTypeObject);
+ if (item) {
+ *obj = item->u.refValue;
+ return true;
+ }
+ return false;
+}
+
+bool AMessage::findMessage(const char *name, sp<AMessage> *obj) const {
+ const Item *item = findItem(name, kTypeMessage);
+ if (item) {
+ *obj = static_cast<AMessage *>(item->u.refValue);
+ return true;
+ }
+ return false;
+}
+
+void AMessage::post(int64_t delayUs) {
+ extern ALooperRoster gLooperRoster;
+
+ gLooperRoster.postMessage(this, delayUs);
+}
+
+sp<AMessage> AMessage::dup() const {
+ sp<AMessage> msg = new AMessage(mWhat, mTarget);
+ msg->mNumItems = mNumItems;
+
+ for (size_t i = 0; i < mNumItems; ++i) {
+ const Item *from = &mItems[i];
+ Item *to = &msg->mItems[i];
+
+ to->mName = from->mName;
+ to->mType = from->mType;
+
+ switch (from->mType) {
+ case kTypeString:
+ {
+ to->u.stringValue =
+ new AString(*from->u.stringValue);
+ break;
+ }
+
+ case kTypeObject:
+ case kTypeMessage:
+ {
+ to->u.refValue = from->u.refValue;
+ to->u.refValue->incStrong(msg.get());
+ break;
+ }
+
+ default:
+ {
+ to->u = from->u;
+ break;
+ }
+ }
+ }
+
+ return msg;
+}
+
+static void appendIndent(AString *s, int32_t indent) {
+ static const char kWhitespace[] =
+ " "
+ " ";
+
+ CHECK_LT((size_t)indent, sizeof(kWhitespace));
+
+ s->append(kWhitespace, indent);
+}
+
+static bool isFourcc(uint32_t what) {
+ return isprint(what & 0xff)
+ && isprint((what >> 8) & 0xff)
+ && isprint((what >> 16) & 0xff)
+ && isprint((what >> 24) & 0xff);
+}
+
+AString AMessage::debugString(int32_t indent) const {
+ AString s = "AMessage(what = ";
+
+ AString tmp;
+ if (isFourcc(mWhat)) {
+ tmp = StringPrintf(
+ "'%c%c%c%c'",
+ (char)(mWhat >> 24),
+ (char)((mWhat >> 16) & 0xff),
+ (char)((mWhat >> 8) & 0xff),
+ (char)(mWhat & 0xff));
+ } else {
+ tmp = StringPrintf("0x%08x", mWhat);
+ }
+ s.append(tmp);
+
+ if (mTarget != 0) {
+ tmp = StringPrintf(", target = %d", mTarget);
+ s.append(tmp);
+ }
+ s.append(") = {\n");
+
+ for (size_t i = 0; i < mNumItems; ++i) {
+ const Item &item = mItems[i];
+
+ switch (item.mType) {
+ case kTypeInt32:
+ tmp = StringPrintf(
+ "int32_t %s = %d", item.mName, item.u.int32Value);
+ break;
+ case kTypeInt64:
+ tmp = StringPrintf(
+ "int64_t %s = %lld", item.mName, item.u.int64Value);
+ break;
+ case kTypeSize:
+ tmp = StringPrintf(
+ "size_t %s = %d", item.mName, item.u.sizeValue);
+ break;
+ case kTypeFloat:
+ tmp = StringPrintf(
+ "float %s = %f", item.mName, item.u.floatValue);
+ break;
+ case kTypeDouble:
+ tmp = StringPrintf(
+ "double %s = %f", item.mName, item.u.doubleValue);
+ break;
+ case kTypePointer:
+ tmp = StringPrintf(
+ "void *%s = %p", item.mName, item.u.ptrValue);
+ break;
+ case kTypeString:
+ tmp = StringPrintf(
+ "string %s = \"%s\"",
+ item.mName,
+ item.u.stringValue->c_str());
+ break;
+ case kTypeObject:
+ tmp = StringPrintf(
+ "RefBase *%s = %p", item.mName, item.u.refValue);
+ break;
+ case kTypeMessage:
+ tmp = StringPrintf(
+ "AMessage %s = %s",
+ item.mName,
+ static_cast<AMessage *>(
+ item.u.refValue)->debugString(
+ indent + strlen(item.mName) + 14).c_str());
+ break;
+ default:
+ TRESPASS();
+ }
+
+ appendIndent(&s, indent);
+ s.append(" ");
+ s.append(tmp);
+ s.append("\n");
+ }
+
+ appendIndent(&s, indent);
+ s.append("}");
+
+ return s;
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/AString.cpp b/media/libstagefright/foundation/AString.cpp
new file mode 100644
index 0000000..61b76cf
--- /dev/null
+++ b/media/libstagefright/foundation/AString.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ADebug.h"
+#include "AString.h"
+
+namespace android {
+
+// static
+const char *AString::kEmptyString = "";
+
+AString::AString()
+ : mData((char *)kEmptyString),
+ mSize(0),
+ mAllocSize(1) {
+}
+
+AString::AString(const char *s)
+ : mData(NULL),
+ mSize(0),
+ mAllocSize(1) {
+ setTo(s);
+}
+
+AString::AString(const char *s, size_t size)
+ : mData(NULL),
+ mSize(0),
+ mAllocSize(1) {
+ setTo(s, size);
+}
+
+AString::AString(const AString &from)
+ : mData(NULL),
+ mSize(0),
+ mAllocSize(1) {
+ setTo(from, 0, from.size());
+}
+
+AString::AString(const AString &from, size_t offset, size_t n)
+ : mData(NULL),
+ mSize(0),
+ mAllocSize(1) {
+ setTo(from, offset, n);
+}
+
+AString::~AString() {
+ clear();
+}
+
+AString &AString::operator=(const AString &from) {
+ if (&from != this) {
+ setTo(from, 0, from.size());
+ }
+
+ return *this;
+}
+
+size_t AString::size() const {
+ return mSize;
+}
+
+const char *AString::c_str() const {
+ return mData;
+}
+
+bool AString::empty() const {
+ return mSize == 0;
+}
+
+void AString::setTo(const char *s) {
+ setTo(s, strlen(s));
+}
+
+void AString::setTo(const char *s, size_t size) {
+ clear();
+ append(s, size);
+}
+
+void AString::setTo(const AString &from, size_t offset, size_t n) {
+ CHECK(&from != this);
+
+ clear();
+ setTo(from.mData + offset, n);
+}
+
+void AString::clear() {
+ if (mData && mData != kEmptyString) {
+ free(mData);
+ mData = NULL;
+ }
+
+ mData = (char *)kEmptyString;
+ mSize = 0;
+ mAllocSize = 1;
+}
+
+size_t AString::hash() const {
+ size_t x = 0;
+ for (size_t i = 0; i < mSize; ++i) {
+ x = (x * 31) + mData[i];
+ }
+
+ return x;
+}
+
+bool AString::operator==(const AString &other) const {
+ return mSize == other.mSize && !memcmp(mData, other.mData, mSize);
+}
+
+void AString::trim() {
+ makeMutable();
+
+ size_t i = 0;
+ while (i < mSize && isspace(mData[i])) {
+ ++i;
+ }
+
+ size_t j = mSize;
+ while (j > i && isspace(mData[j - 1])) {
+ --j;
+ }
+
+ memmove(mData, &mData[i], j - i);
+ mSize = j - i;
+ mData[mSize] = '\0';
+}
+
+void AString::erase(size_t start, size_t n) {
+ CHECK_LT(start, mSize);
+ CHECK_LE(start + n, mSize);
+
+ makeMutable();
+
+ memmove(&mData[start], &mData[start + n], mSize - start - n);
+ mSize -= n;
+ mData[mSize] = '\0';
+}
+
+void AString::makeMutable() {
+ if (mData == kEmptyString) {
+ mData = strdup(kEmptyString);
+ }
+}
+
+void AString::append(const char *s) {
+ append(s, strlen(s));
+}
+
+void AString::append(const char *s, size_t size) {
+ makeMutable();
+
+ if (mSize + size + 1 > mAllocSize) {
+ mAllocSize = (mAllocSize + size + 31) & -32;
+ mData = (char *)realloc(mData, mAllocSize);
+ CHECK(mData != NULL);
+ }
+
+ memcpy(&mData[mSize], s, size);
+ mSize += size;
+ mData[mSize] = '\0';
+}
+
+void AString::append(const AString &from) {
+ append(from.c_str(), from.size());
+}
+
+void AString::append(const AString &from, size_t offset, size_t n) {
+ append(from.c_str() + offset, n);
+}
+
+void AString::append(int x) {
+ char s[16];
+ sprintf(s, "%d", x);
+
+ append(s);
+}
+
+void AString::append(unsigned x) {
+ char s[16];
+ sprintf(s, "%u", x);
+
+ append(s);
+}
+
+void AString::append(long x) {
+ char s[16];
+ sprintf(s, "%ld", x);
+
+ append(s);
+}
+
+void AString::append(unsigned long x) {
+ char s[16];
+ sprintf(s, "%lu", x);
+
+ append(s);
+}
+
+void AString::append(long long x) {
+ char s[32];
+ sprintf(s, "%lld", x);
+
+ append(s);
+}
+
+void AString::append(unsigned long long x) {
+ char s[32];
+ sprintf(s, "%llu", x);
+
+ append(s);
+}
+
+void AString::append(float x) {
+ char s[16];
+ sprintf(s, "%f", x);
+
+ append(s);
+}
+
+void AString::append(double x) {
+ char s[16];
+ sprintf(s, "%f", x);
+
+ append(s);
+}
+
+void AString::append(void *x) {
+ char s[16];
+ sprintf(s, "%p", x);
+
+ append(s);
+}
+
+ssize_t AString::find(const char *substring, size_t start) const {
+ CHECK_LE(start, size());
+
+ const char *match = strstr(mData + start, substring);
+
+ if (match == NULL) {
+ return -1;
+ }
+
+ return match - mData;
+}
+
+void AString::insert(const AString &from, size_t insertionPos) {
+ insert(from.c_str(), from.size(), insertionPos);
+}
+
+void AString::insert(const char *from, size_t size, size_t insertionPos) {
+ CHECK_GE(insertionPos, 0u);
+ CHECK_LE(insertionPos, mSize);
+
+ makeMutable();
+
+ if (mSize + size + 1 > mAllocSize) {
+ mAllocSize = (mAllocSize + size + 31) & -32;
+ mData = (char *)realloc(mData, mAllocSize);
+ CHECK(mData != NULL);
+ }
+
+ memmove(&mData[insertionPos + size],
+ &mData[insertionPos], mSize - insertionPos + 1);
+
+ memcpy(&mData[insertionPos], from, size);
+
+ mSize += size;
+}
+
+bool AString::operator<(const AString &other) const {
+ return compare(other) < 0;
+}
+
+bool AString::operator>(const AString &other) const {
+ return compare(other) > 0;
+}
+
+int AString::compare(const AString &other) const {
+ return strcmp(mData, other.mData);
+}
+
+void AString::tolower() {
+ makeMutable();
+
+ for (size_t i = 0; i < mSize; ++i) {
+ mData[i] = ::tolower(mData[i]);
+ }
+}
+
+bool AString::startsWith(const char *prefix) const {
+ return !strncmp(mData, prefix, strlen(prefix));
+}
+
+AString StringPrintf(const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+
+ char *buffer;
+ vasprintf(&buffer, format, ap);
+
+ va_end(ap);
+
+ AString result(buffer);
+
+ free(buffer);
+ buffer = NULL;
+
+ return result;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/foundation/Android.mk b/media/libstagefright/foundation/Android.mk
new file mode 100644
index 0000000..35eea7e
--- /dev/null
+++ b/media/libstagefright/foundation/Android.mk
@@ -0,0 +1,36 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ AAtomizer.cpp \
+ ABuffer.cpp \
+ ADebug.cpp \
+ AHandler.cpp \
+ ALooper.cpp \
+ ALooperRoster.cpp \
+ AMessage.cpp \
+ AString.cpp \
+ base64.cpp \
+ hexdump.cpp
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/include/media/stagefright/foundation
+
+LOCAL_SHARED_LIBRARIES := \
+ libbinder \
+ libmedia \
+ libutils \
+ libcutils \
+ libui \
+ libsonivox \
+ libvorbisidec \
+ libsurfaceflinger_client \
+ libcamera_client
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= libstagefright_foundation
+
+LOCAL_PRELINK_MODULE:= false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp
new file mode 100644
index 0000000..d5fb4e0
--- /dev/null
+++ b/media/libstagefright/foundation/base64.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "base64.h"
+
+#include "ABuffer.h"
+#include "ADebug.h"
+
+namespace android {
+
+sp<ABuffer> decodeBase64(const AString &s) {
+ if ((s.size() % 4) != 0) {
+ return NULL;
+ }
+
+ size_t n = s.size();
+ size_t padding = 0;
+ if (n >= 1 && s.c_str()[n - 1] == '=') {
+ padding = 1;
+
+ if (n >= 2 && s.c_str()[n - 2] == '=') {
+ padding = 2;
+ }
+ }
+
+ size_t outLen = 3 * s.size() / 4 - padding;
+
+ sp<ABuffer> buffer = new ABuffer(outLen);
+
+ uint8_t *out = buffer->data();
+ size_t j = 0;
+ uint32_t accum = 0;
+ for (size_t i = 0; i < n; ++i) {
+ char c = s.c_str()[i];
+ unsigned value;
+ if (c >= 'A' && c <= 'Z') {
+ value = c - 'A';
+ } else if (c >= 'a' && c <= 'z') {
+ value = 26 + c - 'a';
+ } else if (c >= '0' && c <= '9') {
+ value = 52 + c - '0';
+ } else if (c == '+') {
+ value = 62;
+ } else if (c == '/') {
+ value = 63;
+ } else if (c != '=') {
+ return NULL;
+ } else {
+ if (i < n - padding) {
+ return NULL;
+ }
+
+ value = 0;
+ }
+
+ accum = (accum << 6) | value;
+
+ if (((i + 1) % 4) == 0) {
+ out[j++] = (accum >> 16);
+
+ if (j < outLen) { out[j++] = (accum >> 8) & 0xff; }
+ if (j < outLen) { out[j++] = accum & 0xff; }
+
+ accum = 0;
+ }
+ }
+
+ return buffer;
+}
+
+static char encode6Bit(unsigned x) {
+ if (x <= 25) {
+ return 'A' + x;
+ } else if (x <= 51) {
+ return 'a' + x - 26;
+ } else if (x <= 61) {
+ return '0' + x - 52;
+ } else if (x == 62) {
+ return '+';
+ } else {
+ return '/';
+ }
+}
+
+void encodeBase64(
+ const void *_data, size_t size, AString *out) {
+ out->clear();
+
+ const uint8_t *data = (const uint8_t *)_data;
+
+ size_t i;
+ for (i = 0; i < (size / 3) * 3; i += 3) {
+ uint8_t x1 = data[i];
+ uint8_t x2 = data[i + 1];
+ uint8_t x3 = data[i + 2];
+
+ out->append(encode6Bit(x1 >> 2));
+ out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+ out->append(encode6Bit((x2 << 2 | x3 >> 6) & 0x3f));
+ out->append(encode6Bit(x3 & 0x3f));
+ }
+ switch (size % 3) {
+ case 0:
+ break;
+ case 2:
+ {
+ uint8_t x1 = data[i];
+ uint8_t x2 = data[i + 1];
+ out->append(encode6Bit(x1 >> 2));
+ out->append(encode6Bit((x1 << 4 | x2 >> 4) & 0x3f));
+ out->append(encode6Bit((x2 << 2) & 0x3f));
+ out->append('=');
+ break;
+ }
+ default:
+ {
+ uint8_t x1 = data[i];
+ out->append(encode6Bit(x1 >> 2));
+ out->append(encode6Bit((x1 << 4) & 0x3f));
+ out->append("==");
+ break;
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/libstagefright/foundation/hexdump.cpp
new file mode 100644
index 0000000..093b587
--- /dev/null
+++ b/media/libstagefright/foundation/hexdump.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hexdump.h"
+
+#include "ADebug.h"
+#include "AString.h"
+
+#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
+
+namespace android {
+
+void hexdump(const void *_data, size_t size) {
+ const uint8_t *data = (const uint8_t *)_data;
+
+ size_t offset = 0;
+ while (offset < size) {
+ AString line;
+
+ char tmp[32];
+ sprintf(tmp, "%08lx: ", (unsigned long)offset);
+
+ line.append(tmp);
+
+ for (size_t i = 0; i < 16; ++i) {
+ if (i == 8) {
+ line.append(' ');
+ }
+ if (offset + i >= size) {
+ line.append(" ");
+ } else {
+ sprintf(tmp, "%02x ", data[offset + i]);
+ line.append(tmp);
+ }
+ }
+
+ line.append(' ');
+
+ for (size_t i = 0; i < 16; ++i) {
+ if (offset + i >= size) {
+ break;
+ }
+
+ if (isprint(data[offset + i])) {
+ line.append((char)data[offset + i]);
+ } else {
+ line.append('.');
+ }
+ }
+
+ LOG(INFO) << line;
+
+ offset += 16;
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/httplive/Android.mk b/media/libstagefright/httplive/Android.mk
new file mode 100644
index 0000000..3de2c80
--- /dev/null
+++ b/media/libstagefright/httplive/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ LiveSource.cpp \
+ M3UParser.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/frameworks/base/media/libstagefright
+
+LOCAL_MODULE:= libstagefright_httplive
+
+ifeq ($(TARGET_ARCH),arm)
+ LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/httplive/LiveSource.cpp b/media/libstagefright/httplive/LiveSource.cpp
new file mode 100644
index 0000000..001afc4
--- /dev/null
+++ b/media/libstagefright/httplive/LiveSource.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LiveSource"
+#include <utils/Log.h>
+
+#include "include/LiveSource.h"
+#include "include/M3UParser.h"
+#include "include/NuHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDebug.h>
+
+namespace android {
+
+LiveSource::LiveSource(const char *url)
+ : mURL(url),
+ mInitCheck(NO_INIT),
+ mPlaylistIndex(0),
+ mLastFetchTimeUs(-1),
+ mSource(new NuHTTPDataSource),
+ mSourceSize(0),
+ mOffsetBias(0) {
+ if (switchToNext()) {
+ mInitCheck = OK;
+ }
+}
+
+LiveSource::~LiveSource() {
+}
+
+status_t LiveSource::initCheck() const {
+ return mInitCheck;
+}
+
+bool LiveSource::loadPlaylist() {
+ mPlaylist.clear();
+ mPlaylistIndex = 0;
+
+ sp<ABuffer> buffer;
+ status_t err = fetchM3U(mURL.c_str(), &buffer);
+
+ if (err != OK) {
+ return false;
+ }
+
+ mPlaylist = new M3UParser(mURL.c_str(), buffer->data(), buffer->size());
+
+ if (mPlaylist->initCheck() != OK) {
+ return false;
+ }
+
+ if (!mPlaylist->meta()->findInt32(
+ "media-sequence", &mFirstItemSequenceNumber)) {
+ mFirstItemSequenceNumber = 0;
+ }
+
+ return true;
+}
+
+static int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+bool LiveSource::switchToNext() {
+ mOffsetBias += mSourceSize;
+ mSourceSize = 0;
+
+ if (mLastFetchTimeUs < 0 || getNowUs() >= mLastFetchTimeUs + 15000000ll
+ || mPlaylistIndex == mPlaylist->size()) {
+ int32_t nextSequenceNumber =
+ mPlaylistIndex + mFirstItemSequenceNumber;
+
+ if (!loadPlaylist()) {
+ LOGE("failed to reload playlist");
+ return false;
+ }
+
+ if (mLastFetchTimeUs < 0) {
+ mPlaylistIndex = mPlaylist->size() / 2;
+ } else {
+ if (nextSequenceNumber < mFirstItemSequenceNumber
+ || nextSequenceNumber
+ >= mFirstItemSequenceNumber + (int32_t)mPlaylist->size()) {
+ LOGE("Cannot find sequence number %d in new playlist",
+ nextSequenceNumber);
+
+ return false;
+ }
+
+ mPlaylistIndex = nextSequenceNumber - mFirstItemSequenceNumber;
+ }
+
+ mLastFetchTimeUs = getNowUs();
+ }
+
+ AString uri;
+ CHECK(mPlaylist->itemAt(mPlaylistIndex, &uri));
+ LOGI("switching to %s", uri.c_str());
+
+ if (mSource->connect(uri.c_str()) != OK
+ || mSource->getSize(&mSourceSize) != OK) {
+ return false;
+ }
+
+ mPlaylistIndex++;
+ return true;
+}
+
+ssize_t LiveSource::readAt(off_t offset, void *data, size_t size) {
+ CHECK(offset >= mOffsetBias);
+ offset -= mOffsetBias;
+
+ if (offset >= mSourceSize) {
+ CHECK_EQ(offset, mSourceSize);
+
+ offset -= mSourceSize;
+ if (!switchToNext()) {
+ return ERROR_END_OF_STREAM;
+ }
+ }
+
+ size_t numRead = 0;
+ while (numRead < size) {
+ ssize_t n = mSource->readAt(
+ offset + numRead, (uint8_t *)data + numRead, size - numRead);
+
+ if (n <= 0) {
+ break;
+ }
+
+ numRead += n;
+ }
+
+ return numRead;
+}
+
+status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *out) {
+ *out = NULL;
+
+ status_t err = mSource->connect(url);
+
+ if (err != OK) {
+ return err;
+ }
+
+ off_t size;
+ err = mSource->getSize(&size);
+
+ if (err != OK) {
+ return err;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(size);
+ size_t offset = 0;
+ while (offset < (size_t)size) {
+ ssize_t n = mSource->readAt(
+ offset, buffer->data() + offset, size - offset);
+
+ if (n <= 0) {
+ return ERROR_IO;
+ }
+
+ offset += n;
+ }
+
+ *out = buffer;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
new file mode 100644
index 0000000..edd8648
--- /dev/null
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "include/M3UParser.h"
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+M3UParser::M3UParser(
+ const char *baseURI, const void *data, size_t size)
+ : mInitCheck(NO_INIT),
+ mBaseURI(baseURI),
+ mIsExtM3U(false),
+ mIsVariantPlaylist(false) {
+ mInitCheck = parse(data, size);
+}
+
+M3UParser::~M3UParser() {
+}
+
+status_t M3UParser::initCheck() const {
+ return mInitCheck;
+}
+
+bool M3UParser::isExtM3U() const {
+ return mIsExtM3U;
+}
+
+bool M3UParser::isVariantPlaylist() const {
+ return mIsVariantPlaylist;
+}
+
+sp<AMessage> M3UParser::meta() {
+ return mMeta;
+}
+
+size_t M3UParser::size() {
+ return mItems.size();
+}
+
+bool M3UParser::itemAt(size_t index, AString *uri, sp<AMessage> *meta) {
+ uri->clear();
+ if (meta) { *meta = NULL; }
+
+ if (index >= mItems.size()) {
+ return false;
+ }
+
+ *uri = mItems.itemAt(index).mURI;
+
+ if (meta) {
+ *meta = mItems.itemAt(index).mMeta;
+ }
+
+ return true;
+}
+
+static bool MakeURL(const char *baseURL, const char *url, AString *out) {
+ out->clear();
+
+ if (strncasecmp("http://", baseURL, 7)) {
+ // Base URL must be absolute
+ return false;
+ }
+
+ if (!strncasecmp("http://", url, 7)) {
+ // "url" is already an absolute URL, ignore base URL.
+ out->setTo(url);
+ return true;
+ }
+
+ size_t n = strlen(baseURL);
+ if (baseURL[n - 1] == '/') {
+ out->setTo(baseURL);
+ out->append(url);
+ } else {
+ char *slashPos = strrchr(baseURL, '/');
+
+ if (slashPos > &baseURL[6]) {
+ out->setTo(baseURL, slashPos - baseURL);
+ } else {
+ out->setTo(baseURL);
+ }
+
+ out->append("/");
+ out->append(url);
+ }
+
+ return true;
+}
+
+status_t M3UParser::parse(const void *_data, size_t size) {
+ int32_t lineNo = 0;
+
+ sp<AMessage> itemMeta;
+
+ const char *data = (const char *)_data;
+ size_t offset = 0;
+ while (offset < size) {
+ size_t offsetLF = offset;
+ while (offsetLF < size && data[offsetLF] != '\n') {
+ ++offsetLF;
+ }
+ if (offsetLF >= size) {
+ break;
+ }
+
+ AString line;
+ if (offsetLF > offset && data[offsetLF - 1] == '\r') {
+ line.setTo(&data[offset], offsetLF - offset - 1);
+ } else {
+ line.setTo(&data[offset], offsetLF - offset);
+ }
+
+ LOGI("#%s#", line.c_str());
+
+ if (lineNo == 0 && line == "#EXTM3U") {
+ mIsExtM3U = true;
+ }
+
+ if (mIsExtM3U) {
+ status_t err = OK;
+
+ if (line.startsWith("#EXT-X-TARGETDURATION")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+ err = parseMetaData(line, &mMeta, "target-duration");
+ } else if (line.startsWith("#EXT-X-MEDIA-SEQUENCE")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+ err = parseMetaData(line, &mMeta, "media-sequence");
+ } else if (line.startsWith("#EXTINF")) {
+ if (mIsVariantPlaylist) {
+ return ERROR_MALFORMED;
+ }
+ err = parseMetaData(line, &itemMeta, "duration");
+ } else if (line.startsWith("#EXT-X-STREAM-INF")) {
+ if (mMeta != NULL) {
+ return ERROR_MALFORMED;
+ }
+ mIsVariantPlaylist = true;
+ }
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ if (!line.startsWith("#")) {
+ if (!mIsVariantPlaylist) {
+ int32_t durationSecs;
+ if (itemMeta == NULL
+ || !itemMeta->findInt32("duration", &durationSecs)) {
+ return ERROR_MALFORMED;
+ }
+ }
+
+ mItems.push();
+ Item *item = &mItems.editItemAt(mItems.size() - 1);
+
+ CHECK(MakeURL(mBaseURI.c_str(), line.c_str(), &item->mURI));
+
+ item->mMeta = itemMeta;
+
+ itemMeta.clear();
+ }
+
+ offset = offsetLF + 1;
+ ++lineNo;
+ }
+
+ return OK;
+}
+
+// static
+status_t M3UParser::parseMetaData(
+ const AString &line, sp<AMessage> *meta, const char *key) {
+ ssize_t colonPos = line.find(":");
+
+ if (colonPos < 0) {
+ return ERROR_MALFORMED;
+ }
+
+ int32_t x;
+ status_t err = ParseInt32(line.c_str() + colonPos + 1, &x);
+
+ if (err != OK) {
+ return err;
+ }
+
+ if (meta->get() == NULL) {
+ *meta = new AMessage;
+ }
+ (*meta)->setInt32(key, x);
+
+ return OK;
+}
+
+// static
+status_t M3UParser::ParseInt32(const char *s, int32_t *x) {
+ char *end;
+ long lval = strtol(s, &end, 10);
+
+ if (end == s || (*end != '\0' && *end != ',')) {
+ return ERROR_MALFORMED;
+ }
+
+ *x = (int32_t)lval;
+
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/id3/Android.mk b/media/libstagefright/id3/Android.mk
index 93fac1c..23c8e44 100644
--- a/media/libstagefright/id3/Android.mk
+++ b/media/libstagefright/id3/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -28,5 +26,3 @@ LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := testid3
include $(BUILD_EXECUTABLE)
-
-endif
diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h
index f09addd..200f93c 100644
--- a/media/libstagefright/include/AACDecoder.h
+++ b/media/libstagefright/include/AACDecoder.h
@@ -25,6 +25,7 @@ struct tPVMP4AudioDecoderExternal;
namespace android {
struct MediaBufferGroup;
+struct MetaData;
struct AACDecoder : public MediaSource {
AACDecoder(const sp<MediaSource> &source);
@@ -41,6 +42,7 @@ protected:
virtual ~AACDecoder();
private:
+ sp<MetaData> mMeta;
sp<MediaSource> mSource;
bool mStarted;
@@ -50,9 +52,11 @@ private:
void *mDecoderBuf;
int64_t mAnchorTimeUs;
int64_t mNumSamplesOutput;
+ status_t mInitCheck;
MediaBuffer *mInputBuffer;
+ status_t initCheck();
AACDecoder(const AACDecoder &);
AACDecoder &operator=(const AACDecoder &);
};
diff --git a/media/libstagefright/include/AACEncoder.h b/media/libstagefright/include/AACEncoder.h
new file mode 100644
index 0000000..ecc533f
--- /dev/null
+++ b/media/libstagefright/include/AACEncoder.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AAC_ENCODER_H
+#define AAC_ENCODER_H
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+struct VO_AUDIO_CODECAPI;
+struct VO_MEM_OPERATOR;
+
+namespace android {
+
+struct MediaBufferGroup;
+
+class AACEncoder: public MediaSource {
+ public:
+ AACEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+
+ protected:
+ virtual ~AACEncoder();
+
+ private:
+ sp<MediaSource> mSource;
+ sp<MetaData> mMeta;
+ bool mStarted;
+ MediaBufferGroup *mBufferGroup;
+ MediaBuffer *mInputBuffer;
+ status_t mInitCheck;
+ int32_t mSampleRate;
+ int32_t mChannels;
+ int32_t mBitRate;
+ int32_t mFrameCount;
+
+ int64_t mAnchorTimeUs;
+ int64_t mNumInputSamples;
+
+ enum {
+ kNumSamplesPerFrame = 1024,
+ };
+
+ int16_t mInputFrame[kNumSamplesPerFrame];
+
+ uint8_t mAudioSpecificConfigData[2]; // auido specific data
+ void *mEncoderHandle;
+ VO_AUDIO_CODECAPI *mApiHandle;
+ VO_MEM_OPERATOR *mMemOperator;
+
+ status_t setAudioSpecificConfigData();
+ status_t initCheck();
+
+ AACEncoder& operator=(const AACEncoder &rhs);
+ AACEncoder(const AACEncoder& copy);
+
+};
+
+}
+
+#endif //#ifndef AAC_ENCODER_H
+
diff --git a/media/libstagefright/include/AMRNBEncoder.h b/media/libstagefright/include/AMRNBEncoder.h
index 7167c00..71160e6 100644
--- a/media/libstagefright/include/AMRNBEncoder.h
+++ b/media/libstagefright/include/AMRNBEncoder.h
@@ -19,13 +19,14 @@
#define AMR_NB_ENCODER_H_
#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
namespace android {
struct MediaBufferGroup;
struct AMRNBEncoder : public MediaSource {
- AMRNBEncoder(const sp<MediaSource> &source);
+ AMRNBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
virtual status_t start(MetaData *params);
virtual status_t stop();
@@ -40,6 +41,7 @@ protected:
private:
sp<MediaSource> mSource;
+ sp<MetaData> mMeta;
bool mStarted;
MediaBufferGroup *mBufferGroup;
diff --git a/media/libstagefright/include/AMRWBEncoder.h b/media/libstagefright/include/AMRWBEncoder.h
new file mode 100644
index 0000000..f2d155f
--- /dev/null
+++ b/media/libstagefright/include/AMRWBEncoder.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AMR_WB_ENCODER_H
+#define AMR_WB_ENCODER_H
+
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+struct VO_AUDIO_CODECAPI;
+struct VO_MEM_OPERATOR;
+
+namespace android {
+
+struct MediaBufferGroup;
+
+class AMRWBEncoder: public MediaSource {
+ public:
+ AMRWBEncoder(const sp<MediaSource> &source, const sp<MetaData> &meta);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+
+ protected:
+ virtual ~AMRWBEncoder();
+
+ private:
+ sp<MediaSource> mSource;
+ sp<MetaData> mMeta;
+ bool mStarted;
+ MediaBufferGroup *mBufferGroup;
+ MediaBuffer *mInputBuffer;
+ status_t mInitCheck;
+ int32_t mBitRate;
+ void *mEncoderHandle;
+ VO_AUDIO_CODECAPI *mApiHandle;
+ VO_MEM_OPERATOR *mMemOperator;
+
+ int64_t mAnchorTimeUs;
+ int64_t mNumFramesOutput;
+
+ int16_t mInputFrame[320];
+ int32_t mNumInputSamples;
+
+ status_t initCheck();
+
+ AMRWBEncoder& operator=(const AMRWBEncoder &rhs);
+ AMRWBEncoder(const AMRWBEncoder& copy);
+
+};
+
+}
+
+#endif //#ifndef AMR_WB_ENCODER_H
+
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
new file mode 100644
index 0000000..55efd41
--- /dev/null
+++ b/media/libstagefright/include/ARTSPController.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_RTSP_CONTROLLER_H_
+
+#define A_RTSP_CONTROLLER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+
+namespace android {
+
+struct ALooper;
+struct MyHandler;
+
+struct ARTSPController : public MediaExtractor {
+ ARTSPController(const sp<ALooper> &looper);
+
+ status_t connect(const char *url);
+ void disconnect();
+
+ virtual size_t countTracks();
+ virtual sp<MediaSource> getTrack(size_t index);
+
+ virtual sp<MetaData> getTrackMetaData(
+ size_t index, uint32_t flags);
+
+protected:
+ virtual ~ARTSPController();
+
+private:
+ sp<ALooper> mLooper;
+ sp<MyHandler> mHandler;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTSPController);
+};
+
+} // namespace android
+
+#endif // A_RTSP_CONTROLLER_H_
diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h
index 621aa9a..7810171 100644
--- a/media/libstagefright/include/AVCDecoder.h
+++ b/media/libstagefright/include/AVCDecoder.h
@@ -58,6 +58,9 @@ private:
int64_t mAnchorTimeUs;
int64_t mNumSamplesOutput;
int64_t mPendingSeekTimeUs;
+ MediaSource::ReadOptions::SeekMode mPendingSeekMode;
+
+ int64_t mTargetTimeUs;
void addCodecSpecificData(const uint8_t *data, size_t size);
diff --git a/media/libstagefright/include/AVCEncoder.h b/media/libstagefright/include/AVCEncoder.h
new file mode 100644
index 0000000..4fe2e30
--- /dev/null
+++ b/media/libstagefright/include/AVCEncoder.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AVC_ENCODER_H_
+
+#define AVC_ENCODER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+struct tagAVCHandle;
+struct tagAVCEncParam;
+
+namespace android {
+
+struct MediaBuffer;
+struct MediaBufferGroup;
+
+struct AVCEncoder : public MediaSource,
+ public MediaBufferObserver {
+ AVCEncoder(const sp<MediaSource> &source,
+ const sp<MetaData>& meta);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+ // Callbacks required by the encoder
+ int32_t allocOutputBuffers(unsigned int sizeInMbs, unsigned int numBuffers);
+ void unbindOutputBuffer(int32_t index);
+ int32_t bindOutputBuffer(int32_t index, uint8_t **yuv);
+
+protected:
+ virtual ~AVCEncoder();
+
+private:
+ sp<MediaSource> mSource;
+ sp<MetaData> mFormat;
+ sp<MetaData> mMeta;
+
+ int32_t mVideoWidth;
+ int32_t mVideoHeight;
+ int32_t mVideoFrameRate;
+ int32_t mVideoBitRate;
+ int32_t mVideoColorFormat;
+ int64_t mNumInputFrames;
+ status_t mInitCheck;
+ bool mStarted;
+ bool mSpsPpsHeaderReceived;
+ bool mReadyForNextFrame;
+ int32_t mIsIDRFrame; // for set kKeyIsSyncFrame
+
+ tagAVCHandle *mHandle;
+ tagAVCEncParam *mEncParams;
+ MediaBuffer *mInputBuffer;
+ uint8_t *mInputFrameData;
+ MediaBufferGroup *mGroup;
+ Vector<MediaBuffer *> mOutputBuffers;
+
+
+ status_t initCheck(const sp<MetaData>& meta);
+ void releaseOutputBuffers();
+
+ AVCEncoder(const AVCEncoder &);
+ AVCEncoder &operator=(const AVCEncoder &);
+};
+
+} // namespace android
+
+#endif // AVC_ENCODER_H_
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 9455743..8d0877c 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -18,12 +18,13 @@
#define AWESOME_PLAYER_H_
+#include "NuHTTPDataSource.h"
#include "TimedEventQueue.h"
#include <media/MediaPlayerInterface.h>
#include <media/stagefright/DataSource.h>
-#include <media/stagefright/HTTPDataSource.h>
#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/TimeSource.h>
#include <utils/threads.h>
namespace android {
@@ -33,8 +34,10 @@ struct DataSource;
struct MediaBuffer;
struct MediaExtractor;
struct MediaSource;
-struct Prefetcher;
-struct TimeSource;
+struct NuCachedSource2;
+
+struct ALooper;
+struct ARTSPController;
struct AwesomeRenderer : public RefBase {
AwesomeRenderer() {}
@@ -98,6 +101,9 @@ private:
PREPARED = 16,
AT_EOS = 32,
PREPARE_CANCELLED = 64,
+ CACHE_UNDERRUN = 128,
+ AUDIO_AT_EOS = 256,
+ VIDEO_AT_EOS = 512,
};
mutable Mutex mLock;
@@ -111,6 +117,7 @@ private:
sp<ISurface> mISurface;
sp<MediaPlayerBase::AudioSink> mAudioSink;
+ SystemTimeSource mSystemTimeSource;
TimeSource *mTimeSource;
String8 mUri;
@@ -166,8 +173,11 @@ private:
MediaBuffer *mLastVideoBuffer;
MediaBuffer *mVideoBuffer;
- sp<Prefetcher> mPrefetcher;
- sp<HTTPDataSource> mConnectingDataSource;
+ sp<NuHTTPDataSource> mConnectingDataSource;
+ sp<NuCachedSource2> mCachedSource;
+
+ sp<ALooper> mLooper;
+ sp<ARTSPController> mRTSPController;
struct SuspensionState {
String8 mUri;
diff --git a/media/libstagefright/include/LiveSource.h b/media/libstagefright/include/LiveSource.h
new file mode 100644
index 0000000..c55508c
--- /dev/null
+++ b/media/libstagefright/include/LiveSource.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef LIVE_SOURCE_H_
+
+#define LIVE_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/DataSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct ABuffer;
+struct NuHTTPDataSource;
+struct M3UParser;
+
+struct LiveSource : public DataSource {
+ LiveSource(const char *url);
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off_t offset, void *data, size_t size);
+
+ virtual uint32_t flags() {
+ return kWantsPrefetching;
+ }
+
+protected:
+ virtual ~LiveSource();
+
+private:
+ AString mURL;
+ status_t mInitCheck;
+
+ sp<M3UParser> mPlaylist;
+ int32_t mFirstItemSequenceNumber;
+ size_t mPlaylistIndex;
+ int64_t mLastFetchTimeUs;
+
+ sp<NuHTTPDataSource> mSource;
+ off_t mSourceSize;
+ off_t mOffsetBias;
+
+ status_t fetchM3U(const char *url, sp<ABuffer> *buffer);
+
+ bool switchToNext();
+ bool loadPlaylist();
+
+ DISALLOW_EVIL_CONSTRUCTORS(LiveSource);
+};
+
+} // namespace android
+
+#endif // LIVE_SOURCE_H_
diff --git a/media/libstagefright/include/M3UParser.h b/media/libstagefright/include/M3UParser.h
new file mode 100644
index 0000000..36553de
--- /dev/null
+++ b/media/libstagefright/include/M3UParser.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef M3U_PARSER_H_
+
+#define M3U_PARSER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct M3UParser : public RefBase {
+ M3UParser(const char *baseURI, const void *data, size_t size);
+
+ status_t initCheck() const;
+
+ bool isExtM3U() const;
+ bool isVariantPlaylist() const;
+
+ sp<AMessage> meta();
+
+ size_t size();
+ bool itemAt(size_t index, AString *uri, sp<AMessage> *meta = NULL);
+
+protected:
+ virtual ~M3UParser();
+
+private:
+ struct Item {
+ AString mURI;
+ sp<AMessage> mMeta;
+ };
+
+ status_t mInitCheck;
+
+ AString mBaseURI;
+ bool mIsExtM3U;
+ bool mIsVariantPlaylist;
+
+ sp<AMessage> mMeta;
+ Vector<Item> mItems;
+
+ status_t parse(const void *data, size_t size);
+
+ static status_t parseMetaData(
+ const AString &line, sp<AMessage> *meta, const char *key);
+
+ static status_t ParseInt32(const char *s, int32_t *x);
+
+ DISALLOW_EVIL_CONSTRUCTORS(M3UParser);
+};
+
+} // namespace android
+
+#endif // M3U_PARSER_H_
diff --git a/media/libstagefright/include/M4vH263Decoder.h b/media/libstagefright/include/M4vH263Decoder.h
index ec49e80..7d73e30 100644
--- a/media/libstagefright/include/M4vH263Decoder.h
+++ b/media/libstagefright/include/M4vH263Decoder.h
@@ -54,6 +54,7 @@ private:
MediaBuffer *mInputBuffer;
int64_t mNumSamplesOutput;
+ int64_t mTargetTimeUs;
void allocateFrames(int32_t width, int32_t height);
void releaseFrames();
diff --git a/media/libstagefright/include/M4vH263Encoder.h b/media/libstagefright/include/M4vH263Encoder.h
new file mode 100644
index 0000000..dd146f4
--- /dev/null
+++ b/media/libstagefright/include/M4vH263Encoder.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef M4V_H263_ENCODER_H_
+
+#define M4V_H263_ENCODER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+
+struct tagvideoEncControls;
+struct tagvideoEncOptions;
+
+namespace android {
+
+struct MediaBuffer;
+struct MediaBufferGroup;
+
+struct M4vH263Encoder : public MediaSource,
+ public MediaBufferObserver {
+ M4vH263Encoder(const sp<MediaSource> &source,
+ const sp<MetaData>& meta);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+protected:
+ virtual ~M4vH263Encoder();
+
+private:
+ sp<MediaSource> mSource;
+ sp<MetaData> mFormat;
+ sp<MetaData> mMeta;
+
+ int32_t mVideoWidth;
+ int32_t mVideoHeight;
+ int32_t mVideoFrameRate;
+ int32_t mVideoBitRate;
+ int32_t mVideoColorFormat;
+ int64_t mNumInputFrames;
+ int64_t mNextModTimeUs;
+ status_t mInitCheck;
+ bool mStarted;
+
+ tagvideoEncControls *mHandle;
+ tagvideoEncOptions *mEncParams;
+ MediaBuffer *mInputBuffer;
+ uint8_t *mInputFrameData;
+ MediaBufferGroup *mGroup;
+
+ status_t initCheck(const sp<MetaData>& meta);
+ void releaseOutputBuffers();
+
+ M4vH263Encoder(const M4vH263Encoder &);
+ M4vH263Encoder &operator=(const M4vH263Encoder &);
+};
+
+} // namespace android
+
+#endif // M4V_H263_ENCODER_H_
diff --git a/media/libstagefright/include/MP3Decoder.h b/media/libstagefright/include/MP3Decoder.h
index 88aa4c6..4086fb6 100644
--- a/media/libstagefright/include/MP3Decoder.h
+++ b/media/libstagefright/include/MP3Decoder.h
@@ -42,6 +42,9 @@ protected:
private:
sp<MediaSource> mSource;
+ sp<MetaData> mMeta;
+ int32_t mNumChannels;
+
bool mStarted;
MediaBufferGroup *mBufferGroup;
@@ -49,10 +52,12 @@ private:
tPVMP3DecoderExternal *mConfig;
void *mDecoderBuf;
int64_t mAnchorTimeUs;
- int64_t mNumSamplesOutput;
+ int64_t mNumFramesOutput;
MediaBuffer *mInputBuffer;
+ void init();
+
MP3Decoder(const MP3Decoder &);
MP3Decoder &operator=(const MP3Decoder &);
};
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
new file mode 100644
index 0000000..c96973b
--- /dev/null
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -0,0 +1,54 @@
+#ifndef MPEG2_TS_EXTRACTOR_H_
+
+#define MPEG2_TS_EXTRACTOR_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AnotherPacketSource;
+struct ATSParser;
+struct DataSource;
+struct MPEG2TSSource;
+struct String8;
+
+struct MPEG2TSExtractor : public MediaExtractor {
+ MPEG2TSExtractor(const sp<DataSource> &source);
+
+ virtual size_t countTracks();
+ virtual sp<MediaSource> getTrack(size_t index);
+ virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
+
+ virtual sp<MetaData> getMetaData();
+
+ virtual uint32_t flags() const {
+ return CAN_PAUSE;
+ }
+
+private:
+ friend struct MPEG2TSSource;
+
+ Mutex mLock;
+
+ sp<DataSource> mDataSource;
+ sp<ATSParser> mParser;
+
+ Vector<sp<AnotherPacketSource> > mSourceImpls;
+
+ off_t mOffset;
+
+ void init();
+ status_t feedMore();
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSExtractor);
+};
+
+bool SniffMPEG2TS(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence);
+
+} // namespace android
+
+#endif // MPEG2_TS_EXTRACTOR_H_
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
new file mode 100644
index 0000000..3a20c16
--- /dev/null
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NU_CACHED_SOURCE_2_H_
+
+#define NU_CACHED_SOURCE_2_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+struct ALooper;
+struct PageCache;
+
+struct NuCachedSource2 : public DataSource {
+ NuCachedSource2(const sp<DataSource> &source);
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off_t *size);
+ virtual uint32_t flags();
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ size_t cachedSize();
+ size_t approxDataRemaining(bool *eos);
+
+protected:
+ virtual ~NuCachedSource2();
+
+private:
+ friend struct AHandlerReflector<NuCachedSource2>;
+
+ enum {
+ kPageSize = 65536,
+ kHighWaterThreshold = 5 * 1024 * 1024,
+ kLowWaterThreshold = 512 * 1024,
+
+ // Read data after a 15 sec timeout whether we're actively
+ // fetching or not.
+ kKeepAliveIntervalUs = 15000000,
+ };
+
+ enum {
+ kWhatFetchMore = 'fetc',
+ kWhatRead = 'read',
+ };
+
+ sp<DataSource> mSource;
+ sp<AHandlerReflector<NuCachedSource2> > mReflector;
+ sp<ALooper> mLooper;
+
+ Mutex mSerializer;
+ Mutex mLock;
+ Condition mCondition;
+
+ PageCache *mCache;
+ off_t mCacheOffset;
+ status_t mFinalStatus;
+ off_t mLastAccessPos;
+ sp<AMessage> mAsyncResult;
+ bool mFetching;
+ int64_t mLastFetchTimeUs;
+
+ void onMessageReceived(const sp<AMessage> &msg);
+ void onFetch();
+ void onRead(const sp<AMessage> &msg);
+
+ void fetchInternal();
+ ssize_t readInternal(off_t offset, void *data, size_t size);
+ status_t seekInternal_l(off_t offset);
+
+ size_t approxDataRemaining_l(bool *eos);
+ void restartPrefetcherIfNecessary_l();
+
+ DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
+};
+
+} // namespace android
+
+#endif // NU_CACHED_SOURCE_2_H_
diff --git a/media/libstagefright/include/NuHTTPDataSource.h b/media/libstagefright/include/NuHTTPDataSource.h
new file mode 100644
index 0000000..8593a91
--- /dev/null
+++ b/media/libstagefright/include/NuHTTPDataSource.h
@@ -0,0 +1,73 @@
+#ifndef NU_HTTP_DATA_SOURCE_H_
+
+#define NU_HTTP_DATA_SOURCE_H_
+
+#include <media/stagefright/DataSource.h>
+#include <utils/String8.h>
+#include <utils/threads.h>
+
+#include "HTTPStream.h"
+
+namespace android {
+
+struct NuHTTPDataSource : public DataSource {
+ NuHTTPDataSource();
+
+ status_t connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers = NULL,
+ off_t offset = 0);
+
+ void disconnect();
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off_t offset, void *data, size_t size);
+ virtual status_t getSize(off_t *size);
+ virtual uint32_t flags();
+
+protected:
+ virtual ~NuHTTPDataSource();
+
+private:
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED
+ };
+
+ Mutex mLock;
+
+ State mState;
+
+ String8 mHost;
+ unsigned mPort;
+ String8 mPath;
+ String8 mHeaders;
+
+ HTTPStream mHTTP;
+ off_t mOffset;
+ off_t mContentLength;
+ bool mContentLengthValid;
+
+ status_t connect(
+ const char *uri, const String8 &headers, off_t offset);
+
+ status_t connect(
+ const char *host, unsigned port, const char *path,
+ const String8 &headers,
+ off_t offset);
+
+ void applyTimeoutResponse();
+
+ static void MakeFullHeaders(
+ const KeyedVector<String8, String8> *overrides,
+ String8 *headers);
+
+ NuHTTPDataSource(const NuHTTPDataSource &);
+ NuHTTPDataSource &operator=(const NuHTTPDataSource &);
+};
+
+} // namespace android
+
+#endif // NU_HTTP_DATA_SOURCE_H_
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index ea131e8..c99da59 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -102,7 +102,7 @@ public:
OMX_IN OMX_U32 nData1,
OMX_IN OMX_U32 nData2,
OMX_IN OMX_PTR pEventData);
-
+
OMX_ERRORTYPE OnEmptyBufferDone(
node_id node, OMX_IN OMX_BUFFERHEADERTYPE *pBuffer);
@@ -115,20 +115,19 @@ protected:
virtual ~OMX();
private:
- Mutex mLock;
-
- OMXMaster *mMaster;
-
struct CallbackDispatcher;
- sp<CallbackDispatcher> mDispatcher;
+ Mutex mLock;
+ OMXMaster *mMaster;
int32_t mNodeCounter;
KeyedVector<wp<IBinder>, OMXNodeInstance *> mLiveNodes;
KeyedVector<node_id, OMXNodeInstance *> mNodeIDToInstance;
+ KeyedVector<node_id, sp<CallbackDispatcher> > mDispatchers;
node_id makeNodeID(OMXNodeInstance *instance);
OMXNodeInstance *findInstance(node_id node);
+ sp<CallbackDispatcher> findDispatcher(node_id node);
void invalidateNodeID_l(node_id node);
diff --git a/media/libstagefright/include/Prefetcher.h b/media/libstagefright/include/Prefetcher.h
deleted file mode 100644
index b411d1b..0000000
--- a/media/libstagefright/include/Prefetcher.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PREFETCHER_H_
-
-#define PREFETCHER_H_
-
-#include <utils/RefBase.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-namespace android {
-
-struct MediaSource;
-struct PrefetchedSource;
-
-struct Prefetcher : public RefBase {
- Prefetcher();
-
- // Given an existing MediaSource returns a new MediaSource
- // that will benefit from prefetching/caching the original one.
- sp<MediaSource> addSource(const sp<MediaSource> &source);
-
- int64_t getCachedDurationUs(bool *noMoreData = NULL);
-
- // If provided (non-NULL), "continueFunc" will be called repeatedly
- // while preparing and preparation will finish early if it returns
- // false. In this case "-EINTR" is returned as a result.
- status_t prepare(
- bool (*continueFunc)(void *cookie) = NULL,
- void *cookie = NULL);
-
-protected:
- virtual ~Prefetcher();
-
-private:
- Mutex mLock;
- Condition mCondition;
-
- Vector<wp<PrefetchedSource> > mSources;
- android_thread_id_t mThread;
- bool mDone;
- bool mThreadExited;
-
- void startThread();
- void stopThread();
-
- static int ThreadWrapper(void *me);
- void threadFunc();
-
- Prefetcher(const Prefetcher &);
- Prefetcher &operator=(const Prefetcher &);
-};
-
-} // namespace android
-
-#endif // PREFETCHER_H_
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index 533ce84..a2b2c99 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -63,11 +63,17 @@ public:
uint32_t *decodingTime);
enum {
- kSyncSample_Flag = 1
+ kFlagBefore,
+ kFlagAfter,
+ kFlagClosest
};
- status_t findClosestSample(
+ status_t findSampleAtTime(
uint32_t req_time, uint32_t *sample_index, uint32_t flags);
+ status_t findSyncSampleNear(
+ uint32_t start_sample_index, uint32_t *sample_index,
+ uint32_t flags);
+
status_t findThumbnailSample(uint32_t *sample_index);
protected:
@@ -111,9 +117,6 @@ private:
friend struct SampleIterator;
- status_t findClosestSyncSample_l(
- uint32_t start_sample_index, uint32_t *sample_index);
-
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
SampleTable(const SampleTable &);
diff --git a/media/libstagefright/include/ThrottledSource.h b/media/libstagefright/include/ThrottledSource.h
new file mode 100644
index 0000000..88164b3
--- /dev/null
+++ b/media/libstagefright/include/ThrottledSource.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef THROTTLED_SOURCE_H_
+
+#define THROTTLED_SOURCE_H_
+
+#include <media/stagefright/DataSource.h>
+#include <utils/threads.h>
+
+namespace android {
+
+struct ThrottledSource : public DataSource {
+ ThrottledSource(
+ const sp<DataSource> &source,
+ int32_t bandwidthLimitBytesPerSecond);
+
+ virtual status_t initCheck() const;
+
+ virtual ssize_t readAt(off_t offset, void *data, size_t size);
+
+ virtual status_t getSize(off_t *size);
+ virtual uint32_t flags();
+
+private:
+ Mutex mLock;
+
+ sp<DataSource> mSource;
+ int32_t mBandwidthLimitBytesPerSecond;
+ int64_t mStartTimeUs;
+ size_t mTotalTransferred;
+
+ ThrottledSource(const ThrottledSource &);
+ ThrottledSource &operator=(const ThrottledSource &);
+};
+
+} // namespace android
+
+#endif // THROTTLED_SOURCE_H_
diff --git a/media/libstagefright/include/VPXDecoder.h b/media/libstagefright/include/VPXDecoder.h
new file mode 100644
index 0000000..3b8362d
--- /dev/null
+++ b/media/libstagefright/include/VPXDecoder.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VPX_DECODER_H_
+
+#define VPX_DECODER_H_
+
+#include <media/stagefright/MediaSource.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct MediaBufferGroup;
+
+struct VPXDecoder : public MediaSource {
+ VPXDecoder(const sp<MediaSource> &source);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+protected:
+ virtual ~VPXDecoder();
+
+private:
+ sp<MediaSource> mSource;
+ bool mStarted;
+ int32_t mWidth, mHeight;
+ size_t mBufferSize;
+
+ void *mCtx;
+ MediaBufferGroup *mBufferGroup;
+
+ int64_t mTargetTimeUs;
+
+ sp<MetaData> mFormat;
+
+ VPXDecoder(const VPXDecoder &);
+ VPXDecoder &operator=(const VPXDecoder &);
+};
+
+} // namespace android
+
+#endif // VPX_DECODER_H_
+
diff --git a/media/libstagefright/matroska/Android.mk b/media/libstagefright/matroska/Android.mk
new file mode 100644
index 0000000..0e72198
--- /dev/null
+++ b/media/libstagefright/matroska/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ MatroskaExtractor.cpp \
+ mkvparser.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_MODULE:= libstagefright_matroska
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
new file mode 100644
index 0000000..3739be1
--- /dev/null
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MatroskaExtractor"
+#include <utils/Log.h>
+
+#include "MatroskaExtractor.h"
+
+#include "mkvparser.hpp"
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct DataSourceReader : public mkvparser::IMkvReader {
+ DataSourceReader(const sp<DataSource> &source)
+ : mSource(source) {
+ }
+
+ virtual int Read(long long position, long length, unsigned char* buffer) {
+ CHECK(position >= 0);
+ CHECK(length >= 0);
+
+ if (length == 0) {
+ return 0;
+ }
+
+ ssize_t n = mSource->readAt(position, buffer, length);
+
+ if (n <= 0) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ virtual int Length(long long* total, long long* available) {
+ off_t size;
+ if (mSource->getSize(&size) != OK) {
+ return -1;
+ }
+
+ if (total) {
+ *total = size;
+ }
+
+ if (available) {
+ *available = size;
+ }
+
+ return 0;
+ }
+
+private:
+ sp<DataSource> mSource;
+
+ DataSourceReader(const DataSourceReader &);
+ DataSourceReader &operator=(const DataSourceReader &);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#include <ctype.h>
+static void hexdump(const void *_data, size_t size) {
+ const uint8_t *data = (const uint8_t *)_data;
+ size_t offset = 0;
+ while (offset < size) {
+ printf("0x%04x ", offset);
+
+ size_t n = size - offset;
+ if (n > 16) {
+ n = 16;
+ }
+
+ for (size_t i = 0; i < 16; ++i) {
+ if (i == 8) {
+ printf(" ");
+ }
+
+ if (offset + i < size) {
+ printf("%02x ", data[offset + i]);
+ } else {
+ printf(" ");
+ }
+ }
+
+ printf(" ");
+
+ for (size_t i = 0; i < n; ++i) {
+ if (isprint(data[offset + i])) {
+ printf("%c", data[offset + i]);
+ } else {
+ printf(".");
+ }
+ }
+
+ printf("\n");
+
+ offset += 16;
+ }
+}
+
+struct BlockIterator {
+ BlockIterator(mkvparser::Segment *segment, unsigned long trackNum);
+
+ bool eos() const;
+
+ void advance();
+ void reset();
+ void seek(int64_t seekTimeUs);
+
+ const mkvparser::Block *block() const;
+ int64_t blockTimeUs() const;
+
+private:
+ mkvparser::Segment *mSegment;
+ unsigned long mTrackNum;
+
+ mkvparser::Cluster *mCluster;
+ const mkvparser::BlockEntry *mBlockEntry;
+
+ BlockIterator(const BlockIterator &);
+ BlockIterator &operator=(const BlockIterator &);
+};
+
+struct MatroskaSource : public MediaSource {
+ MatroskaSource(
+ const sp<MatroskaExtractor> &extractor, size_t index);
+
+ virtual status_t start(MetaData *params);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options);
+
+private:
+ enum Type {
+ AVC,
+ AAC,
+ OTHER
+ };
+
+ sp<MatroskaExtractor> mExtractor;
+ size_t mTrackIndex;
+ Type mType;
+ BlockIterator mBlockIter;
+
+ status_t advance();
+
+ MatroskaSource(const MatroskaSource &);
+ MatroskaSource &operator=(const MatroskaSource &);
+};
+
+MatroskaSource::MatroskaSource(
+ const sp<MatroskaExtractor> &extractor, size_t index)
+ : mExtractor(extractor),
+ mTrackIndex(index),
+ mType(OTHER),
+ mBlockIter(mExtractor->mSegment,
+ mExtractor->mTracks.itemAt(index).mTrackNum) {
+ const char *mime;
+ CHECK(mExtractor->mTracks.itemAt(index).mMeta->
+ findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mType = AVC;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ mType = AAC;
+ }
+}
+
+status_t MatroskaSource::start(MetaData *params) {
+ mBlockIter.reset();
+
+ return OK;
+}
+
+status_t MatroskaSource::stop() {
+ return OK;
+}
+
+sp<MetaData> MatroskaSource::getFormat() {
+ return mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+BlockIterator::BlockIterator(
+ mkvparser::Segment *segment, unsigned long trackNum)
+ : mSegment(segment),
+ mTrackNum(trackNum),
+ mCluster(NULL),
+ mBlockEntry(NULL) {
+ reset();
+}
+
+bool BlockIterator::eos() const {
+ return mCluster == NULL || mCluster->EOS();
+}
+
+void BlockIterator::advance() {
+ while (!eos()) {
+ if (mBlockEntry != NULL) {
+ mBlockEntry = mCluster->GetNext(mBlockEntry);
+ } else if (mCluster != NULL) {
+ mCluster = mSegment->GetNext(mCluster);
+
+ if (eos()) {
+ break;
+ }
+
+ mBlockEntry = mCluster->GetFirst();
+ }
+
+ if (mBlockEntry != NULL
+ && mBlockEntry->GetBlock()->GetTrackNumber() == mTrackNum) {
+ break;
+ }
+ }
+}
+
+void BlockIterator::reset() {
+ mCluster = mSegment->GetFirst();
+ mBlockEntry = mCluster->GetFirst();
+
+ while (!eos() && block()->GetTrackNumber() != mTrackNum) {
+ advance();
+ }
+}
+
+void BlockIterator::seek(int64_t seekTimeUs) {
+ mCluster = mSegment->GetCluster(seekTimeUs * 1000ll);
+ mBlockEntry = mCluster != NULL ? mCluster->GetFirst() : NULL;
+
+ while (!eos() && block()->GetTrackNumber() != mTrackNum) {
+ advance();
+ }
+
+ while (!eos() && !mBlockEntry->GetBlock()->IsKey()) {
+ advance();
+ }
+}
+
+const mkvparser::Block *BlockIterator::block() const {
+ CHECK(!eos());
+
+ return mBlockEntry->GetBlock();
+}
+
+int64_t BlockIterator::blockTimeUs() const {
+ return (mBlockEntry->GetBlock()->GetTime(mCluster) + 500ll) / 1000ll;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+status_t MatroskaSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ mBlockIter.seek(seekTimeUs);
+ }
+
+ if (mBlockIter.eos()) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ const mkvparser::Block *block = mBlockIter.block();
+ size_t size = block->GetSize();
+ int64_t timeUs = mBlockIter.blockTimeUs();
+
+ MediaBuffer *buffer = new MediaBuffer(size + 2);
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+ long res = block->Read(
+ mExtractor->mReader, (unsigned char *)buffer->data() + 2);
+
+ if (res != 0) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ buffer->set_range(2, size);
+
+ if (mType == AVC) {
+ CHECK(size >= 2);
+
+ uint8_t *data = (uint8_t *)buffer->data();
+
+ unsigned NALsize = data[2] << 8 | data[3];
+ CHECK_EQ(size, NALsize + 2);
+
+ memcpy(data, "\x00\x00\x00\x01", 4);
+ buffer->set_range(0, size + 2);
+ } else if (mType == AAC) {
+ // There's strange junk at the beginning...
+
+ const uint8_t *data = (const uint8_t *)buffer->data() + 2;
+ size_t offset = 0;
+ while (offset < size && data[offset] != 0x21) {
+ ++offset;
+ }
+ buffer->set_range(2 + offset, size - offset);
+ }
+
+ *out = buffer;
+
+#if 0
+ hexdump((const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+#endif
+
+ mBlockIter.advance();
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MatroskaExtractor::MatroskaExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mReader(new DataSourceReader(mDataSource)),
+ mSegment(NULL),
+ mExtractedThumbnails(false) {
+ mkvparser::EBMLHeader ebmlHeader;
+ long long pos;
+ if (ebmlHeader.Parse(mReader, pos) < 0) {
+ return;
+ }
+
+ long long ret =
+ mkvparser::Segment::CreateInstance(mReader, pos, mSegment);
+
+ if (ret) {
+ CHECK(mSegment == NULL);
+ return;
+ }
+
+ ret = mSegment->Load();
+
+ if (ret < 0) {
+ delete mSegment;
+ mSegment = NULL;
+ return;
+ }
+
+ addTracks();
+}
+
+MatroskaExtractor::~MatroskaExtractor() {
+ delete mSegment;
+ mSegment = NULL;
+
+ delete mReader;
+ mReader = NULL;
+}
+
+size_t MatroskaExtractor::countTracks() {
+ return mTracks.size();
+}
+
+sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
+ if (index >= mTracks.size()) {
+ return NULL;
+ }
+
+ return new MatroskaSource(this, index);
+}
+
+sp<MetaData> MatroskaExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ if (index >= mTracks.size()) {
+ return NULL;
+ }
+
+ if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails) {
+ findThumbnails();
+ mExtractedThumbnails = true;
+ }
+
+ return mTracks.itemAt(index).mMeta;
+}
+
+static void addESDSFromAudioSpecificInfo(
+ const sp<MetaData> &meta, const void *asi, size_t asiSize) {
+ static const uint8_t kStaticESDS[] = {
+ 0x03, 22,
+ 0x00, 0x00, // ES_ID
+ 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ 0x04, 17,
+ 0x40, // Audio ISO/IEC 14496-3
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x05,
+ // AudioSpecificInfo (with size prefix) follows
+ };
+
+ CHECK(asiSize < 128);
+ size_t esdsSize = sizeof(kStaticESDS) + asiSize + 1;
+ uint8_t *esds = new uint8_t[esdsSize];
+ memcpy(esds, kStaticESDS, sizeof(kStaticESDS));
+ uint8_t *ptr = esds + sizeof(kStaticESDS);
+ *ptr++ = asiSize;
+ memcpy(ptr, asi, asiSize);
+
+ meta->setData(kKeyESDS, 0, esds, esdsSize);
+
+ delete[] esds;
+ esds = NULL;
+}
+
+void addVorbisCodecInfo(
+ const sp<MetaData> &meta,
+ const void *_codecPrivate, size_t codecPrivateSize) {
+ // printf("vorbis private data follows:\n");
+ // hexdump(_codecPrivate, codecPrivateSize);
+
+ CHECK(codecPrivateSize >= 3);
+
+ const uint8_t *codecPrivate = (const uint8_t *)_codecPrivate;
+ CHECK(codecPrivate[0] == 0x02);
+
+ size_t len1 = codecPrivate[1];
+ size_t len2 = codecPrivate[2];
+
+ CHECK(codecPrivateSize > 3 + len1 + len2);
+
+ CHECK(codecPrivate[3] == 0x01);
+ meta->setData(kKeyVorbisInfo, 0, &codecPrivate[3], len1);
+
+ CHECK(codecPrivate[len1 + 3] == 0x03);
+
+ CHECK(codecPrivate[len1 + len2 + 3] == 0x05);
+ meta->setData(
+ kKeyVorbisBooks, 0, &codecPrivate[len1 + len2 + 3],
+ codecPrivateSize - len1 - len2 - 3);
+}
+
+void MatroskaExtractor::addTracks() {
+ const mkvparser::Tracks *tracks = mSegment->GetTracks();
+
+ for (size_t index = 0; index < tracks->GetTracksCount(); ++index) {
+ const mkvparser::Track *track = tracks->GetTrackByIndex(index);
+
+ const char *const codecID = track->GetCodecId();
+ LOGV("codec id = %s", codecID);
+ LOGV("codec name = %s", track->GetCodecNameAsUTF8());
+
+ size_t codecPrivateSize;
+ const unsigned char *codecPrivate =
+ track->GetCodecPrivate(&codecPrivateSize);
+
+ enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
+
+ sp<MetaData> meta = new MetaData;
+
+ switch (track->GetType()) {
+ case VIDEO_TRACK:
+ {
+ const mkvparser::VideoTrack *vtrack =
+ static_cast<const mkvparser::VideoTrack *>(track);
+
+ if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
+ } else if (!strcmp("V_VP8", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
+ } else {
+ continue;
+ }
+
+ meta->setInt32(kKeyWidth, vtrack->GetWidth());
+ meta->setInt32(kKeyHeight, vtrack->GetHeight());
+ break;
+ }
+
+ case AUDIO_TRACK:
+ {
+ const mkvparser::AudioTrack *atrack =
+ static_cast<const mkvparser::AudioTrack *>(track);
+
+ if (!strcmp("A_AAC", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ CHECK(codecPrivateSize >= 2);
+
+ addESDSFromAudioSpecificInfo(
+ meta, codecPrivate, codecPrivateSize);
+ } else if (!strcmp("A_VORBIS", codecID)) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+
+ addVorbisCodecInfo(meta, codecPrivate, codecPrivateSize);
+ } else {
+ continue;
+ }
+
+ meta->setInt32(kKeySampleRate, atrack->GetSamplingRate());
+ meta->setInt32(kKeyChannelCount, atrack->GetChannels());
+ break;
+ }
+
+ default:
+ continue;
+ }
+
+ long long durationNs = mSegment->GetDuration();
+ meta->setInt64(kKeyDuration, (durationNs + 500) / 1000);
+
+ mTracks.push();
+ TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1);
+ trackInfo->mTrackNum = track->GetNumber();
+ trackInfo->mMeta = meta;
+ }
+}
+
+void MatroskaExtractor::findThumbnails() {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ TrackInfo *info = &mTracks.editItemAt(i);
+
+ const char *mime;
+ CHECK(info->mMeta->findCString(kKeyMIMEType, &mime));
+
+ if (strncasecmp(mime, "video/", 6)) {
+ continue;
+ }
+
+ BlockIterator iter(mSegment, info->mTrackNum);
+ int32_t i = 0;
+ int64_t thumbnailTimeUs = 0;
+ size_t maxBlockSize = 0;
+ while (!iter.eos() && i < 20) {
+ if (iter.block()->IsKey()) {
+ ++i;
+
+ size_t blockSize = iter.block()->GetSize();
+ if (blockSize > maxBlockSize) {
+ maxBlockSize = blockSize;
+ thumbnailTimeUs = iter.blockTimeUs();
+ }
+ }
+ iter.advance();
+ }
+ info->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+ }
+}
+
+sp<MetaData> MatroskaExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MATROSKA);
+
+ return meta;
+}
+
+bool SniffMatroska(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ DataSourceReader reader(source);
+ mkvparser::EBMLHeader ebmlHeader;
+ long long pos;
+ if (ebmlHeader.Parse(&reader, pos) < 0) {
+ return false;
+ }
+
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MATROSKA);
+ *confidence = 0.6;
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
new file mode 100644
index 0000000..7471848
--- /dev/null
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MATROSKA_EXTRACTOR_H_
+
+#define MATROSKA_EXTRACTOR_H_
+
+#include <media/stagefright/MediaExtractor.h>
+#include <utils/Vector.h>
+
+namespace mkvparser {
+struct Segment;
+};
+
+namespace android {
+
+class String8;
+
+struct DataSourceReader;
+struct MatroskaSource;
+
+struct MatroskaExtractor : public MediaExtractor {
+ MatroskaExtractor(const sp<DataSource> &source);
+
+ virtual size_t countTracks();
+
+ virtual sp<MediaSource> getTrack(size_t index);
+
+ virtual sp<MetaData> getTrackMetaData(
+ size_t index, uint32_t flags);
+
+ virtual sp<MetaData> getMetaData();
+
+protected:
+ virtual ~MatroskaExtractor();
+
+private:
+ friend struct MatroskaSource;
+
+ struct TrackInfo {
+ unsigned long mTrackNum;
+ sp<MetaData> mMeta;
+ };
+ Vector<TrackInfo> mTracks;
+
+ sp<DataSource> mDataSource;
+ DataSourceReader *mReader;
+ mkvparser::Segment *mSegment;
+ bool mExtractedThumbnails;
+
+ void addTracks();
+ void findThumbnails();
+
+ MatroskaExtractor(const MatroskaExtractor &);
+ MatroskaExtractor &operator=(const MatroskaExtractor &);
+};
+
+bool SniffMatroska(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence);
+
+} // namespace android
+
+#endif // MATROSKA_EXTRACTOR_H_
diff --git a/media/libstagefright/matroska/mkvparser.cpp b/media/libstagefright/matroska/mkvparser.cpp
new file mode 100644
index 0000000..4e51004
--- /dev/null
+++ b/media/libstagefright/matroska/mkvparser.cpp
@@ -0,0 +1,3103 @@
+#include "mkvparser.hpp"
+#include <cassert>
+#include <cstring>
+
+mkvparser::IMkvReader::~IMkvReader()
+{
+}
+
+long long mkvparser::ReadUInt(IMkvReader* pReader, long long pos, long& len)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(pos < available);
+ assert((available - pos) >= 1); //assume here max u-int len is 8
+
+ unsigned char b;
+
+ hr = pReader->Read(pos, 1, &b);
+ if (hr < 0)
+ return hr;
+
+ assert(hr == 0L);
+
+ if (b & 0x80) //1000 0000
+ {
+ len = 1;
+ b &= 0x7F; //0111 1111
+ }
+ else if (b & 0x40) //0100 0000
+ {
+ len = 2;
+ b &= 0x3F; //0011 1111
+ }
+ else if (b & 0x20) //0010 0000
+ {
+ len = 3;
+ b &= 0x1F; //0001 1111
+ }
+ else if (b & 0x10) //0001 0000
+ {
+ len = 4;
+ b &= 0x0F; //0000 1111
+ }
+ else if (b & 0x08) //0000 1000
+ {
+ len = 5;
+ b &= 0x07; //0000 0111
+ }
+ else if (b & 0x04) //0000 0100
+ {
+ len = 6;
+ b &= 0x03; //0000 0011
+ }
+ else if (b & 0x02) //0000 0010
+ {
+ len = 7;
+ b &= 0x01; //0000 0001
+ }
+ else
+ {
+ assert(b & 0x01); //0000 0001
+ len = 8;
+ b = 0; //0000 0000
+ }
+
+ assert((available - pos) >= len);
+
+ long long result = b;
+ ++pos;
+ for (long i = 1; i < len; ++i)
+ {
+ hr = pReader->Read(pos, 1, &b);
+
+ if (hr < 0)
+ return hr;
+
+ assert(hr == 0L);
+
+ result <<= 8;
+ result |= b;
+
+ ++pos;
+ }
+
+ return result;
+}
+
+
+long long mkvparser::GetUIntLength(
+ IMkvReader* pReader,
+ long long pos,
+ long& len)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ if (pos >= available)
+ return pos; //too few bytes available
+
+ unsigned char b;
+
+ hr = pReader->Read(pos, 1, &b);
+
+ if (hr < 0)
+ return hr;
+
+ assert(hr == 0L);
+
+ if (b == 0) //we can't handle u-int values larger than 8 bytes
+ return E_FILE_FORMAT_INVALID;
+
+ unsigned char m = 0x80;
+ len = 1;
+
+ while (!(b & m))
+ {
+ m >>= 1;
+ ++len;
+ }
+
+ return 0; //success
+}
+
+
+long long mkvparser::SyncReadUInt(
+ IMkvReader* pReader,
+ long long pos,
+ long long stop,
+ long& len)
+{
+ assert(pReader);
+
+ if (pos >= stop)
+ return E_FILE_FORMAT_INVALID;
+
+ unsigned char b;
+
+ long hr = pReader->Read(pos, 1, &b);
+
+ if (hr < 0)
+ return hr;
+
+ if (hr != 0L)
+ return E_BUFFER_NOT_FULL;
+
+ if (b == 0) //we can't handle u-int values larger than 8 bytes
+ return E_FILE_FORMAT_INVALID;
+
+ unsigned char m = 0x80;
+ len = 1;
+
+ while (!(b & m))
+ {
+ m >>= 1;
+ ++len;
+ }
+
+ if ((pos + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ long long result = b & (~m);
+ ++pos;
+
+ for (int i = 1; i < len; ++i)
+ {
+ hr = pReader->Read(pos, 1, &b);
+
+ if (hr < 0)
+ return hr;
+
+ if (hr != 0L)
+ return E_BUFFER_NOT_FULL;
+
+ result <<= 8;
+ result |= b;
+
+ ++pos;
+ }
+
+ return result;
+}
+
+
+long long mkvparser::UnserializeUInt(
+ IMkvReader* pReader,
+ long long pos,
+ long long size)
+{
+ assert(pReader);
+ assert(pos >= 0);
+ assert(size > 0);
+ assert(size <= 8);
+
+ long long result = 0;
+
+ for (long long i = 0; i < size; ++i)
+ {
+ unsigned char b;
+
+ const long hr = pReader->Read(pos, 1, &b);
+
+ if (hr < 0)
+ return hr;
+ result <<= 8;
+ result |= b;
+
+ ++pos;
+ }
+
+ return result;
+}
+
+
+float mkvparser::Unserialize4Float(
+ IMkvReader* pReader,
+ long long pos)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+ assert((pos + 4) <= available);
+
+ float result;
+
+ unsigned char* const p = (unsigned char*)&result;
+ unsigned char* q = p + 4;
+
+ for (;;)
+ {
+ hr = pReader->Read(pos, 1, --q);
+ assert(hr == 0L);
+
+ if (q == p)
+ break;
+
+ ++pos;
+ }
+
+ return result;
+}
+
+
+double mkvparser::Unserialize8Double(
+ IMkvReader* pReader,
+ long long pos)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ double result;
+
+ unsigned char* const p = (unsigned char*)&result;
+ unsigned char* q = p + 8;
+
+ for (;;)
+ {
+ const long hr = pReader->Read(pos, 1, --q);
+ assert(hr == 0L);
+
+ if (q == p)
+ break;
+
+ ++pos;
+ }
+
+ return result;
+}
+
+signed char mkvparser::Unserialize1SInt(
+ IMkvReader* pReader,
+ long long pos)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr == 0);
+ assert(available <= total);
+ assert(pos < available);
+
+ signed char result;
+
+ hr = pReader->Read(pos, 1, (unsigned char*)&result);
+ assert(hr == 0);
+
+ return result;
+}
+
+short mkvparser::Unserialize2SInt(
+ IMkvReader* pReader,
+ long long pos)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+ assert((pos + 2) <= available);
+
+ short result;
+
+ unsigned char* const p = (unsigned char*)&result;
+ unsigned char* q = p + 2;
+
+ for (;;)
+ {
+ hr = pReader->Read(pos, 1, --q);
+ assert(hr == 0L);
+
+ if (q == p)
+ break;
+
+ ++pos;
+ }
+
+ return result;
+}
+
+
+bool mkvparser::Match(
+ IMkvReader* pReader,
+ long long& pos,
+ unsigned long id_,
+ long long& val)
+
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ long len;
+
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0);
+ assert(len > 0);
+ assert(len <= 8);
+ assert((pos + len) <= available);
+
+ if ((unsigned long)id != id_)
+ return false;
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0);
+ assert(size <= 8);
+ assert(len > 0);
+ assert(len <= 8);
+ assert((pos + len) <= available);
+
+ pos += len; //consume length of size of payload
+
+ val = UnserializeUInt(pReader, pos, size);
+ assert(val >= 0);
+
+ pos += size; //consume size of payload
+
+ return true;
+}
+
+bool mkvparser::Match(
+ IMkvReader* pReader,
+ long long& pos,
+ unsigned long id_,
+ char*& val)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ long len;
+
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0);
+ assert(len > 0);
+ assert(len <= 8);
+ assert((pos + len) <= available);
+
+ if ((unsigned long)id != id_)
+ return false;
+
+ pos += len; //consume id
+
+ const long long size_ = ReadUInt(pReader, pos, len);
+ assert(size_ >= 0);
+ assert(len > 0);
+ assert(len <= 8);
+ assert((pos + len) <= available);
+
+ pos += len; //consume length of size of payload
+ assert((pos + size_) <= available);
+
+ const size_t size = static_cast<size_t>(size_);
+ val = new char[size+1];
+
+ for (size_t i = 0; i < size; ++i)
+ {
+ char c;
+
+ hr = pReader->Read(pos + i, 1, (unsigned char*)&c);
+ assert(hr == 0L);
+
+ val[i] = c;
+
+ if (c == '\0')
+ break;
+
+ }
+
+ val[size] = '\0';
+ pos += size_; //consume size of payload
+
+ return true;
+}
+
+#if 0
+bool mkvparser::Match(
+ IMkvReader* pReader,
+ long long& pos,
+ unsigned long id,
+ wchar_t*& val)
+{
+ char* str;
+
+ if (!Match(pReader, pos, id, str))
+ return false;
+
+ const size_t size = mbstowcs(NULL, str, 0);
+
+ if (size == 0)
+ val = NULL;
+ else
+ {
+ val = new wchar_t[size+1];
+ mbstowcs(val, str, size);
+ val[size] = L'\0';
+ }
+
+ delete[] str;
+ return true;
+}
+#endif
+
+
+bool mkvparser::Match(
+ IMkvReader* pReader,
+ long long& pos,
+ unsigned long id_,
+ unsigned char*& val,
+ size_t *optionalSize)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0);
+ assert(len > 0);
+ assert(len <= 8);
+ assert((pos + len) <= available);
+
+ if ((unsigned long)id != id_)
+ return false;
+
+ pos += len; //consume id
+
+ const long long size_ = ReadUInt(pReader, pos, len);
+ assert(size_ >= 0);
+ assert(len > 0);
+ assert(len <= 8);
+ assert((pos + len) <= available);
+
+ pos += len; //consume length of size of payload
+ assert((pos + size_) <= available);
+
+ const size_t size = static_cast<size_t>(size_);
+ val = new unsigned char[size];
+
+ if (optionalSize) {
+ *optionalSize = size;
+ }
+
+ for (size_t i = 0; i < size; ++i)
+ {
+ unsigned char b;
+
+ hr = pReader->Read(pos + i, 1, &b);
+ assert(hr == 0L);
+
+ val[i] = b;
+ }
+
+ pos += size_; //consume size of payload
+ return true;
+}
+
+
+bool mkvparser::Match(
+ IMkvReader* pReader,
+ long long& pos,
+ unsigned long id_,
+ double& val)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+ long idlen;
+ const long long id = ReadUInt(pReader, pos, idlen);
+ assert(id >= 0); //TODO
+
+ if ((unsigned long)id != id_)
+ return false;
+
+ long sizelen;
+ const long long size = ReadUInt(pReader, pos + idlen, sizelen);
+
+ switch (size)
+ {
+ case 4:
+ case 8:
+ break;
+ default:
+ return false;
+ }
+
+ pos += idlen + sizelen; //consume id and size fields
+ assert((pos + size) <= available);
+
+ if (size == 4)
+ val = Unserialize4Float(pReader, pos);
+ else
+ {
+ assert(size == 8);
+ val = Unserialize8Double(pReader, pos);
+ }
+
+ pos += size; //consume size of payload
+
+ return true;
+}
+
+
+bool mkvparser::Match(
+ IMkvReader* pReader,
+ long long& pos,
+ unsigned long id_,
+ short& val)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0);
+ assert((pos + len) <= available);
+
+ if ((unsigned long)id != id_)
+ return false;
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size <= 2);
+ assert((pos + len) <= available);
+
+ pos += len; //consume length of size of payload
+ assert((pos + size) <= available);
+
+ //TODO:
+ // Generalize this to work for any size signed int
+ if (size == 1)
+ val = Unserialize1SInt(pReader, pos);
+ else
+ val = Unserialize2SInt(pReader, pos);
+
+ pos += size; //consume size of payload
+
+ return true;
+}
+
+
+namespace mkvparser
+{
+
+EBMLHeader::EBMLHeader():
+ m_docType(NULL)
+{
+}
+
+EBMLHeader::~EBMLHeader()
+{
+ delete[] m_docType;
+}
+
+long long EBMLHeader::Parse(
+ IMkvReader* pReader,
+ long long& pos)
+{
+ assert(pReader);
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+
+ if (hr < 0)
+ return hr;
+
+ pos = 0;
+ long long end = (1024 < available)? 1024: available;
+
+ for (;;)
+ {
+ unsigned char b = 0;
+
+ while (pos < end)
+ {
+ hr = pReader->Read(pos, 1, &b);
+
+ if (hr < 0)
+ return hr;
+
+ if (b == 0x1A)
+ break;
+
+ ++pos;
+ }
+
+ if (b != 0x1A)
+ {
+ if ((pos >= 1024) ||
+ (available >= total) ||
+ ((total - available) < 5))
+ return -1;
+
+ return available + 5; //5 = 4-byte ID + 1st byte of size
+ }
+
+ if ((total - pos) < 5)
+ return E_FILE_FORMAT_INVALID;
+
+ if ((available - pos) < 5)
+ return pos + 5; //try again later
+
+ long len;
+
+ const long long result = ReadUInt(pReader, pos, len);
+
+ if (result < 0) //error
+ return result;
+
+ if (result == 0x0A45DFA3) //ReadId masks-off length indicator bits
+ {
+ assert(len == 4);
+ pos += len;
+ break;
+ }
+
+ ++pos; //throw away just the 0x1A byte, and try again
+ }
+
+ long len;
+ long long result = GetUIntLength(pReader, pos, len);
+
+ if (result < 0) //error
+ return result;
+
+ if (result > 0) //need more data
+ return result;
+
+ assert(len > 0);
+ assert(len <= 8);
+
+ if ((total - pos) < len)
+ return E_FILE_FORMAT_INVALID;
+ if ((available - pos) < len)
+ return pos + len; //try again later
+
+ result = ReadUInt(pReader, pos, len);
+
+ if (result < 0) //error
+ return result;
+
+ pos += len; //consume u-int
+
+ if ((total - pos) < result)
+ return E_FILE_FORMAT_INVALID;
+
+ if ((available - pos) < result)
+ return pos + result;
+
+ end = pos + result;
+
+ m_version = 1;
+ m_readVersion = 1;
+ m_maxIdLength = 4;
+ m_maxSizeLength = 8;
+ m_docTypeVersion = 1;
+ m_docTypeReadVersion = 1;
+
+ while (pos < end)
+ {
+ if (Match(pReader, pos, 0x0286, m_version))
+ ;
+ else if (Match(pReader, pos, 0x02F7, m_readVersion))
+ ;
+ else if (Match(pReader, pos, 0x02F2, m_maxIdLength))
+ ;
+ else if (Match(pReader, pos, 0x02F3, m_maxSizeLength))
+ ;
+ else if (Match(pReader, pos, 0x0282, m_docType))
+ ;
+ else if (Match(pReader, pos, 0x0287, m_docTypeVersion))
+ ;
+ else if (Match(pReader, pos, 0x0285, m_docTypeReadVersion))
+ ;
+ else
+ {
+ result = ReadUInt(pReader, pos, len);
+ assert(result > 0);
+ assert(len > 0);
+ assert(len <= 8);
+
+ pos += len;
+ assert(pos < end);
+
+ result = ReadUInt(pReader, pos, len);
+ assert(result >= 0);
+ assert(len > 0);
+ assert(len <= 8);
+
+ pos += len + result;
+ assert(pos <= end);
+ }
+ }
+
+ assert(pos == end);
+
+ return 0;
+}
+
+
+Segment::Segment(
+ IMkvReader* pReader,
+ long long start,
+ long long size) :
+ m_pReader(pReader),
+ m_start(start),
+ m_size(size),
+ m_pos(start),
+ m_pInfo(NULL),
+ m_pTracks(NULL),
+ m_clusterCount(0)
+ //m_clusterNumber(0)
+{
+}
+
+
+Segment::~Segment()
+{
+ Cluster** i = m_clusters;
+ Cluster** j = m_clusters + m_clusterCount;
+
+ while (i != j)
+ {
+ Cluster* p = *i++;
+ assert(p);
+ delete p;
+ }
+
+ delete[] m_clusters;
+
+ delete m_pTracks;
+ delete m_pInfo;
+}
+
+
+long long Segment::CreateInstance(
+ IMkvReader* pReader,
+ long long pos,
+ Segment*& pSegment)
+{
+ assert(pReader);
+ assert(pos >= 0);
+
+ pSegment = NULL;
+
+ long long total, available;
+
+ long hr = pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ //I would assume that in practice this loop would execute
+ //exactly once, but we allow for other elements (e.g. Void)
+ //to immediately follow the EBML header. This is fine for
+ //the source filter case (since the entire file is available),
+ //but in the splitter case over a network we should probably
+ //just give up early. We could for example decide only to
+ //execute this loop a maximum of, say, 10 times.
+
+ while (pos < total)
+ {
+ //Read ID
+
+ long len;
+ long long result = GetUIntLength(pReader, pos, len);
+
+ if (result) //error, or too few available bytes
+ return result;
+
+ if ((pos + len) > total)
+ return E_FILE_FORMAT_INVALID;
+
+ if ((pos + len) > available)
+ return pos + len;
+
+ //TODO: if we liberalize the behavior of ReadUInt, we can
+ //probably eliminate having to use GetUIntLength here.
+ const long long id = ReadUInt(pReader, pos, len);
+
+ if (id < 0) //error
+ return id;
+
+ pos += len; //consume ID
+
+ //Read Size
+
+ result = GetUIntLength(pReader, pos, len);
+
+ if (result) //error, or too few available bytes
+ return result;
+
+ if ((pos + len) > total)
+ return E_FILE_FORMAT_INVALID;
+
+ if ((pos + len) > available)
+ return pos + len;
+
+ //TODO: if we liberalize the behavior of ReadUInt, we can
+ //probably eliminate having to use GetUIntLength here.
+ const long long size = ReadUInt(pReader, pos, len);
+
+ if (size < 0)
+ return size;
+
+ pos += len; //consume length of size of element
+
+ //Pos now points to start of payload
+
+ if ((pos + size) > total)
+ return E_FILE_FORMAT_INVALID;
+
+ if (id == 0x08538067) //Segment ID
+ {
+ pSegment = new Segment(pReader, pos, size);
+ assert(pSegment); //TODO
+
+ return 0; //success
+ }
+
+ pos += size; //consume payload
+ }
+
+ assert(pos == total);
+
+ pSegment = new Segment(pReader, pos, 0);
+ assert(pSegment); //TODO
+
+ return 0; //success (sort of)
+}
+
+
+long long Segment::ParseHeaders()
+{
+ //Outermost (level 0) segment object has been constructed,
+ //and pos designates start of payload. We need to find the
+ //inner (level 1) elements.
+ long long total, available;
+
+ long hr = m_pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available <= total);
+
+ const long long stop = m_start + m_size;
+ assert(stop <= total);
+ assert(m_pos <= stop);
+
+ bool bQuit = false;
+ while ((m_pos < stop) && !bQuit)
+ {
+ long long pos = m_pos;
+
+ long len;
+ long long result = GetUIntLength(m_pReader, pos, len);
+
+ if (result) //error, or too few available bytes
+ return result;
+
+ if ((pos + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ if ((pos + len) > available)
+ return pos + len;
+
+ const long long idpos = pos;
+ const long long id = ReadUInt(m_pReader, idpos, len);
+
+ if (id < 0) //error
+ return id;
+
+ pos += len; //consume ID
+
+ //Read Size
+ result = GetUIntLength(m_pReader, pos, len);
+
+ if (result) //error, or too few available bytes
+ return result;
+
+ if ((pos + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ if ((pos + len) > available)
+ return pos + len;
+
+ const long long size = ReadUInt(m_pReader, pos, len);
+
+ if (size < 0)
+ return size;
+
+ pos += len; //consume length of size of element
+
+ //Pos now points to start of payload
+
+ if ((pos + size) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ //We read EBML elements either in total or nothing at all.
+
+ if ((pos + size) > available)
+ return pos + size;
+
+ if (id == 0x0549A966) //Segment Info ID
+ {
+ assert(m_pInfo == NULL);
+ m_pInfo = new SegmentInfo(this, pos, size);
+ assert(m_pInfo); //TODO
+
+ if (m_pTracks)
+ bQuit = true;
+ }
+ else if (id == 0x0654AE6B) //Tracks ID
+ {
+ assert(m_pTracks == NULL);
+ m_pTracks = new Tracks(this, pos, size);
+ assert(m_pTracks); //TODO
+
+ if (m_pInfo)
+ bQuit = true;
+ }
+ else if (id == 0x0F43B675) //Cluster ID
+ {
+#if 0
+ if (m_pInfo == NULL) //TODO: liberalize
+ ;
+ else if (m_pTracks == NULL)
+ ;
+ else
+ //ParseCluster(idpos, pos, size);
+ Cluster::Parse(this, m_clusters, pos, size);
+#endif
+ bQuit = true;
+ }
+
+ m_pos = pos + size; //consume payload
+ }
+
+ assert(m_pos <= stop);
+
+ return 0; //success
+}
+
+
+long Segment::ParseCluster(Cluster*& pCluster, long long& pos_) const
+{
+ pCluster = NULL;
+ pos_ = -1;
+
+ const long long stop = m_start + m_size;
+ assert(m_pos <= stop);
+
+ long long pos = m_pos;
+ long long off = -1;
+
+
+ while (pos < stop)
+ {
+ long len;
+ const long long idpos = pos;
+
+ const long long id = SyncReadUInt(m_pReader, pos, stop, len);
+
+ if (id < 0) //error
+ return static_cast<long>(id);
+
+ if (id == 0)
+ return E_FILE_FORMAT_INVALID;
+
+ pos += len; //consume id
+ assert(pos < stop);
+
+ const long long size = SyncReadUInt(m_pReader, pos, stop, len);
+
+ if (size < 0) //error
+ return static_cast<long>(size);
+
+ pos += len; //consume size
+ assert(pos <= stop);
+
+ if (size == 0) //weird
+ continue;
+
+ //pos now points to start of payload
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+
+ if (off >= 0)
+ {
+ pos_ = idpos;
+ break;
+ }
+
+ if (id == 0x0F43B675) //Cluster ID
+ off = idpos - m_start;
+ }
+
+ Segment* const this_ = const_cast<Segment*>(this);
+ const size_t idx = m_clusterCount;
+
+ if (pos >= stop)
+ {
+ pos_ = stop;
+
+#if 0
+ if (off < 0)
+ {
+ pCluster = Cluster::CreateEndOfStream(this_, idx);
+ return 1L;
+ }
+#else
+ if (off < 0)
+ return 1L;
+#endif
+
+ //Reading 0 bytes at pos might work too -- it would depend
+ //on how the reader is implemented.
+
+ unsigned char b;
+
+ const long hr = m_pReader->Read(pos - 1, 1, &b);
+
+ if (hr < 0)
+ return hr;
+
+ if (hr != 0L)
+ return E_BUFFER_NOT_FULL;
+ }
+
+ assert(off >= 0);
+ assert(pos_ >= m_start);
+ assert(pos_ <= stop);
+
+ pCluster = Cluster::Parse(this_, idx, off);
+ return 0L;
+}
+
+
+bool Segment::AddCluster(Cluster* pCluster, long long pos)
+{
+ assert(pos >= m_start);
+
+ const long long stop = m_start + m_size;
+ assert(pos <= stop);
+
+ if (pCluster)
+ m_clusters[pos] = pCluster;
+
+ m_pos = pos; //m_pos >= stop is now we know we have all clusters
+
+ return (pos >= stop);
+}
+
+
+long Segment::Load()
+{
+ //Outermost (level 0) segment object has been constructed,
+ //and pos designates start of payload. We need to find the
+ //inner (level 1) elements.
+ const long long stop = m_start + m_size;
+#ifdef _DEBUG
+ {
+ long long total, available;
+
+ long hr = m_pReader->Length(&total, &available);
+ assert(hr >= 0);
+ assert(available >= total);
+ assert(stop <= total);
+ }
+#endif
+ long long index = m_pos;
+
+ m_clusterCount = 0;
+
+ while (index < stop)
+ {
+ long len = 0;
+
+ long long result = GetUIntLength(m_pReader, index, len);
+
+ if (result < 0) //error
+ return static_cast<long>(result);
+
+ if ((index + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ const long long idpos = index;
+ const long long id = ReadUInt(m_pReader, idpos, len);
+
+ if (id < 0) //error
+ return static_cast<long>(id);
+
+ index += len; //consume ID
+
+ //Read Size
+ result = GetUIntLength(m_pReader, index, len);
+
+ if (result < 0) //error
+ return static_cast<long>(result);
+
+ if ((index + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ const long long size = ReadUInt(m_pReader, index, len);
+
+ if (size < 0) //error
+ return static_cast<long>(size);
+
+ index += len; //consume length of size of element
+
+ if (id == 0x0F43B675) // Cluster ID
+ break;
+
+ if (id == 0x014D9B74) // SeekHead ID
+ {
+ ParseSeekHead(index, size, NULL);
+ break;
+ }
+ index += size;
+ }
+
+ if (m_clusterCount == 0)
+ return -1L;
+
+ while (m_pos < stop)
+ {
+ long long pos = m_pos;
+
+ long len;
+
+ long long result = GetUIntLength(m_pReader, pos, len);
+
+ if (result < 0) //error
+ return static_cast<long>(result);
+
+ if ((pos + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ const long long idpos = pos;
+ const long long id = ReadUInt(m_pReader, idpos, len);
+
+ if (id < 0) //error
+ return static_cast<long>(id);
+
+ pos += len; //consume ID
+
+ //Read Size
+ result = GetUIntLength(m_pReader, pos, len);
+
+ if (result < 0) //error
+ return static_cast<long>(result);
+
+ if ((pos + len) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ const long long size = ReadUInt(m_pReader, pos, len);
+
+ if (size < 0) //error
+ return static_cast<long>(size);
+
+ pos += len; //consume length of size of element
+
+ //Pos now points to start of payload
+
+ if ((pos + size) > stop)
+ return E_FILE_FORMAT_INVALID;
+
+ if (id == 0x0F43B675) //Cluster ID
+ break;
+
+ if (id == 0x014D9B74) //SeekHead ID
+ {
+ m_clusters = new Cluster*[m_clusterCount];
+ size_t index = 0;
+
+ ParseSeekHead(pos, size, &index);
+ assert(index == m_clusterCount);
+ }
+ else if (id == 0x0549A966) //Segment Info ID
+ {
+ assert(m_pInfo == NULL);
+ m_pInfo = new SegmentInfo(this, pos, size);
+ assert(m_pInfo); //TODO
+ }
+ else if (id == 0x0654AE6B) //Tracks ID
+ {
+ assert(m_pTracks == NULL);
+ m_pTracks = new Tracks(this, pos, size);
+ assert(m_pTracks); //TODO
+ }
+
+ m_pos = pos + size; //consume payload
+ }
+
+ assert(m_clusters);
+
+ //TODO: see notes above. This check is here (temporarily) to ensure
+ //that the first seekhead has entries for the clusters (because that's
+ //when they're loaded). In case we are given a file that lists the
+ //clusters in a second seekhead, the worst thing that happens is that
+ //we treat this as an invalid file (which is better then simply
+ //asserting somewhere). But that's only a work-around. What we need
+ //to do is be able to handle having multiple seekheads, and having
+ //clusters listed somewhere besides the first seekhead.
+ //
+ //if (m_clusters == NULL)
+ // return E_FILE_FORMAT_INVALID;
+
+ //NOTE: we stop parsing when we reach the first cluster, under the
+ //assumption all clusters are named in some SeekHead. Clusters
+ //will have been (pre)loaded, so we indicate that we have all clusters
+ //by adjusting the parse position:
+ m_pos = stop; //means "we have all clusters"
+
+ return 0L;
+}
+
+
+void Segment::ParseSeekHead(long long start, long long size_, size_t* pIndex)
+{
+ long long pos = start;
+ const long long stop = start + size_;
+ while (pos < stop)
+ {
+ long len;
+
+ const long long id = ReadUInt(m_pReader, pos, len);
+ assert(id >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume ID
+
+ const long long size = ReadUInt(m_pReader, pos, len);
+ assert(size >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume Size field
+ assert((pos + size) <= stop);
+
+ if (id == 0x0DBB) //SeekEntry ID
+ ParseSeekEntry(pos, size, pIndex);
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+ }
+
+ assert(pos == stop);
+}
+
+
+void Segment::ParseSecondarySeekHead(long long off, size_t* pIndex)
+{
+ assert(off >= 0);
+ assert(off < m_size);
+
+ long long pos = m_start + off;
+ const long long stop = m_start + m_size;
+
+ long len;
+
+ long long result = GetUIntLength(m_pReader, pos, len);
+ assert(result == 0);
+ assert((pos + len) <= stop);
+
+ const long long idpos = pos;
+
+ const long long id = ReadUInt(m_pReader, idpos, len);
+ assert(id == 0x014D9B74); //SeekHead ID
+
+ pos += len; //consume ID
+ assert(pos < stop);
+
+ //Read Size
+
+ result = GetUIntLength(m_pReader, pos, len);
+ assert(result == 0);
+ assert((pos + len) <= stop);
+
+ const long long size = ReadUInt(m_pReader, pos, len);
+ assert(size >= 0);
+
+ pos += len; //consume length of size of element
+ assert((pos + size) <= stop);
+
+ //Pos now points to start of payload
+
+ ParseSeekHead(pos, size, pIndex);
+}
+
+
+void Segment::ParseSeekEntry(long long start, long long size_, size_t* pIndex)
+{
+ long long pos = start;
+
+ const long long stop = start + size_;
+
+ long len;
+
+ const long long seekIdId = ReadUInt(m_pReader, pos, len);
+ //seekIdId;
+ assert(seekIdId == 0x13AB); //SeekID ID
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long seekIdSize = ReadUInt(m_pReader, pos, len);
+ assert(seekIdSize >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume size
+
+ const long long seekId = ReadUInt(m_pReader, pos, len); //payload
+ assert(seekId >= 0);
+ assert(len == seekIdSize);
+ assert((pos + len) <= stop);
+
+ pos += seekIdSize; //consume payload
+
+ const long long seekPosId = ReadUInt(m_pReader, pos, len);
+ //seekPosId;
+ assert(seekPosId == 0x13AC); //SeekPos ID
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long seekPosSize = ReadUInt(m_pReader, pos, len);
+ assert(seekPosSize >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume size
+ assert((pos + seekPosSize) <= stop);
+
+ const long long seekOff = UnserializeUInt(m_pReader, pos, seekPosSize);
+ assert(seekOff >= 0);
+ assert(seekOff < m_size);
+
+ pos += seekPosSize; //consume payload
+ assert(pos == stop);
+
+ const long long seekPos = m_start + seekOff;
+ assert(seekPos < (m_start + m_size));
+
+ if (seekId == 0x0F43B675) //cluster id
+ {
+ if (pIndex == NULL)
+ ++m_clusterCount;
+ else
+ {
+ assert(m_clusters);
+ assert(m_clusterCount > 0);
+
+ size_t& index = *pIndex;
+ assert(index < m_clusterCount);
+
+ Cluster*& pCluster = m_clusters[index];
+
+ pCluster = Cluster::Parse(this, index, seekOff);
+ assert(pCluster); //TODO
+
+ ++index;
+ }
+ }
+ else if (seekId == 0x014D9B74) //SeekHead ID
+ {
+ ParseSecondarySeekHead(seekOff, pIndex);
+ }
+}
+
+
+long long Segment::Unparsed() const
+{
+ const long long stop = m_start + m_size;
+
+ const long long result = stop - m_pos;
+ assert(result >= 0);
+
+ return result;
+}
+
+
+#if 0 //NOTE: too inefficient
+long long Segment::Load(long long time_ns)
+{
+ if (Unparsed() <= 0)
+ return 0;
+
+ while (m_clusters.empty())
+ {
+ const long long result = Parse();
+
+ if (result) //error, or not enough bytes available
+ return result;
+
+ if (Unparsed() <= 0)
+ return 0;
+ }
+
+ while (m_clusters.back()->GetTime() < time_ns)
+ {
+ const long long result = Parse();
+
+ if (result) //error, or not enough bytes available
+ return result;
+
+ if (Unparsed() <= 0)
+ return 0;
+ }
+
+ return 0;
+}
+#endif
+
+
+Cluster* Segment::GetFirst()
+{
+ if ((m_clusters == NULL) || (m_clusterCount <= 0))
+ return &m_eos;
+
+ Cluster* const pCluster = m_clusters[0];
+ assert(pCluster);
+
+ return pCluster;
+}
+
+
+Cluster* Segment::GetLast()
+{
+ if ((m_clusters == NULL) || (m_clusterCount <= 0))
+ return &m_eos;
+
+ const size_t idx = m_clusterCount - 1;
+ Cluster* const pCluster = m_clusters[idx];
+ assert(pCluster);
+
+ return pCluster;
+}
+
+
+unsigned long Segment::GetCount() const
+{
+ //TODO: m_clusterCount should not be long long.
+ return static_cast<unsigned long>(m_clusterCount);
+}
+
+
+Cluster* Segment::GetNext(const Cluster* pCurr)
+{
+ assert(pCurr);
+ assert(pCurr != &m_eos);
+ assert(m_clusters);
+ assert(m_clusterCount > 0);
+
+ size_t idx = pCurr->m_index;
+ assert(idx < m_clusterCount);
+ assert(pCurr == m_clusters[idx]);
+
+ idx++;
+
+ if (idx >= m_clusterCount)
+ return &m_eos;
+
+ Cluster* const pNext = m_clusters[idx];
+ assert(pNext);
+
+ return pNext;
+}
+
+
+Cluster* Segment::GetCluster(long long time_ns)
+{
+ if ((m_clusters == NULL) || (m_clusterCount <= 0))
+ return &m_eos;
+
+ {
+ Cluster* const pCluster = m_clusters[0];
+ assert(pCluster);
+ assert(pCluster->m_index == 0);
+
+ if (time_ns <= pCluster->GetTime())
+ return pCluster;
+ }
+
+ //Binary search of cluster array
+
+ size_t i = 0;
+ size_t j = m_clusterCount;
+
+ while (i < j)
+ {
+ //INVARIANT:
+ //[0, i) <= time_ns
+ //[i, j) ?
+ //[j, m_clusterCount) > time_ns
+
+ const size_t k = i + (j - i) / 2;
+ assert(k < m_clusterCount);
+
+ Cluster* const pCluster = m_clusters[k];
+ assert(pCluster);
+ assert(pCluster->m_index == k);
+
+ const long long t = pCluster->GetTime();
+
+ if (t <= time_ns)
+ i = k + 1;
+ else
+ j = k;
+
+ assert(i <= j);
+ }
+
+ assert(i == j);
+ assert(i > 0);
+ assert(i <= m_clusterCount);
+
+ const size_t k = i - 1;
+
+ Cluster* const pCluster = m_clusters[k];
+ assert(pCluster);
+ assert(pCluster->m_index == k);
+ assert(pCluster->GetTime() <= time_ns);
+
+ return pCluster;
+}
+
+
+Tracks* Segment::GetTracks() const
+{
+ return m_pTracks;
+}
+
+
+const SegmentInfo* const Segment::GetInfo() const
+{
+ return m_pInfo;
+}
+
+
+long long Segment::GetDuration() const
+{
+ assert(m_pInfo);
+ return m_pInfo->GetDuration();
+}
+
+
+SegmentInfo::SegmentInfo(Segment* pSegment, long long start, long long size_) :
+ m_pSegment(pSegment),
+ m_start(start),
+ m_size(size_),
+ m_pMuxingAppAsUTF8(NULL),
+ m_pWritingAppAsUTF8(NULL),
+ m_pTitleAsUTF8(NULL)
+{
+ IMkvReader* const pReader = m_pSegment->m_pReader;
+
+ long long pos = start;
+ const long long stop = start + size_;
+
+ m_timecodeScale = 1000000;
+ m_duration = 0;
+
+
+ while (pos < stop)
+ {
+ if (Match(pReader, pos, 0x0AD7B1, m_timecodeScale))
+ assert(m_timecodeScale > 0);
+
+ else if (Match(pReader, pos, 0x0489, m_duration))
+ assert(m_duration >= 0);
+
+ else if (Match(pReader, pos, 0x0D80, m_pMuxingAppAsUTF8)) //[4D][80]
+ assert(m_pMuxingAppAsUTF8);
+
+ else if (Match(pReader, pos, 0x1741, m_pWritingAppAsUTF8)) //[57][41]
+ assert(m_pWritingAppAsUTF8);
+
+ else if (Match(pReader, pos, 0x3BA9, m_pTitleAsUTF8)) //[7B][A9]
+ assert(m_pTitleAsUTF8);
+
+ else
+ {
+ long len;
+
+ const long long id = ReadUInt(pReader, pos, len);
+ //id;
+ assert(id >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+ assert((stop - pos) > 0);
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len + size; //consume size and payload
+ assert(pos <= stop);
+ }
+ }
+
+ assert(pos == stop);
+}
+
+SegmentInfo::~SegmentInfo()
+{
+ if (m_pMuxingAppAsUTF8)
+ {
+ delete[] m_pMuxingAppAsUTF8;
+ m_pMuxingAppAsUTF8 = NULL;
+ }
+
+ if (m_pWritingAppAsUTF8)
+ {
+ delete[] m_pWritingAppAsUTF8;
+ m_pWritingAppAsUTF8 = NULL;
+ }
+
+ if (m_pTitleAsUTF8)
+ {
+ delete[] m_pTitleAsUTF8;
+ m_pTitleAsUTF8 = NULL;
+ }
+}
+
+long long SegmentInfo::GetTimeCodeScale() const
+{
+ return m_timecodeScale;
+}
+
+
+long long SegmentInfo::GetDuration() const
+{
+ assert(m_duration >= 0);
+ assert(m_timecodeScale >= 1);
+
+ const double dd = double(m_duration) * double(m_timecodeScale);
+ const long long d = static_cast<long long>(dd);
+
+ return d;
+}
+
+const char* SegmentInfo::GetMuxingAppAsUTF8() const
+{
+ return m_pMuxingAppAsUTF8;
+}
+
+const char* SegmentInfo::GetWritingAppAsUTF8() const
+{
+ return m_pWritingAppAsUTF8;
+}
+
+const char* SegmentInfo::GetTitleAsUTF8() const
+{
+ return m_pTitleAsUTF8;
+}
+
+Track::Track(Segment* pSegment, const Info& i) :
+ m_pSegment(pSegment),
+ m_info(i)
+{
+}
+
+Track::~Track()
+{
+ Info& info = const_cast<Info&>(m_info);
+ info.Clear();
+}
+
+Track::Info::Info():
+ type(-1),
+ number(-1),
+ uid(-1),
+ nameAsUTF8(NULL),
+ codecId(NULL),
+ codecPrivate(NULL),
+ codecPrivateSize(0),
+ codecNameAsUTF8(NULL)
+{
+}
+
+void Track::Info::Clear()
+{
+ delete[] nameAsUTF8;
+ nameAsUTF8 = NULL;
+
+ delete[] codecId;
+ codecId = NULL;
+
+ delete[] codecPrivate;
+ codecPrivate = NULL;
+
+ delete[] codecNameAsUTF8;
+ codecNameAsUTF8 = NULL;
+}
+
+const BlockEntry* Track::GetEOS() const
+{
+ return &m_eos;
+}
+
+long long Track::GetType() const
+{
+ const unsigned long result = static_cast<unsigned long>(m_info.type);
+ return result;
+}
+
+unsigned long Track::GetNumber() const
+{
+ assert(m_info.number >= 0);
+ const unsigned long result = static_cast<unsigned long>(m_info.number);
+ return result;
+}
+
+const char* Track::GetNameAsUTF8() const
+{
+ return m_info.nameAsUTF8;
+}
+
+const char* Track::GetCodecNameAsUTF8() const
+{
+ return m_info.codecNameAsUTF8;
+}
+
+
+const char* Track::GetCodecId() const
+{
+ return m_info.codecId;
+}
+
+
+const unsigned char* Track::GetCodecPrivate(size_t *optionalSize) const
+{
+ if (optionalSize) {
+ *optionalSize = m_info.codecPrivateSize;
+ }
+ return m_info.codecPrivate;
+}
+
+
+long Track::GetFirst(const BlockEntry*& pBlockEntry) const
+{
+ Cluster* const pCluster = m_pSegment->GetFirst();
+
+ //If Segment::GetFirst returns NULL, then this must be a network
+ //download, and we haven't loaded any clusters yet. In this case,
+ //returning NULL from Track::GetFirst means the same thing.
+
+ if ((pCluster == NULL) || pCluster->EOS())
+ {
+ pBlockEntry = NULL;
+ return E_BUFFER_NOT_FULL; //return 1L instead?
+ }
+
+ pBlockEntry = pCluster->GetFirst();
+
+ while (pBlockEntry)
+ {
+ const Block* const pBlock = pBlockEntry->GetBlock();
+ assert(pBlock);
+
+ if (pBlock->GetTrackNumber() == (unsigned long)m_info.number)
+ return 0L;
+
+ pBlockEntry = pCluster->GetNext(pBlockEntry);
+ }
+
+ //NOTE: if we get here, it means that we didn't find a block with
+ //a matching track number. We interpret that as an error (which
+ //might be too conservative).
+
+ pBlockEntry = GetEOS(); //so we can return a non-NULL value
+ return 1L;
+}
+
+
+long Track::GetNext(const BlockEntry* pCurrEntry, const BlockEntry*& pNextEntry) const
+{
+ assert(pCurrEntry);
+ assert(!pCurrEntry->EOS()); //?
+ assert(pCurrEntry->GetBlock()->GetTrackNumber() == (unsigned long)m_info.number);
+
+ const Cluster* const pCurrCluster = pCurrEntry->GetCluster();
+ assert(pCurrCluster);
+ assert(!pCurrCluster->EOS());
+
+ pNextEntry = pCurrCluster->GetNext(pCurrEntry);
+
+ while (pNextEntry)
+ {
+ const Block* const pNextBlock = pNextEntry->GetBlock();
+ assert(pNextBlock);
+
+ if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number)
+ return 0L;
+
+ pNextEntry = pCurrCluster->GetNext(pNextEntry);
+ }
+
+ Segment* pSegment = pCurrCluster->m_pSegment;
+ Cluster* const pNextCluster = pSegment->GetNext(pCurrCluster);
+
+ if ((pNextCluster == NULL) || pNextCluster->EOS())
+ {
+ if (pSegment->Unparsed() <= 0) //all clusters have been loaded
+ {
+ pNextEntry = GetEOS();
+ return 1L;
+ }
+
+ pNextEntry = NULL;
+ return E_BUFFER_NOT_FULL;
+ }
+
+ pNextEntry = pNextCluster->GetFirst();
+
+ while (pNextEntry)
+ {
+ const Block* const pNextBlock = pNextEntry->GetBlock();
+ assert(pNextBlock);
+
+ if (pNextBlock->GetTrackNumber() == (unsigned long)m_info.number)
+ return 0L;
+
+ pNextEntry = pNextCluster->GetNext(pNextEntry);
+ }
+
+ //TODO: what has happened here is that we did not find a block
+ //with a matching track number on the next cluster. It might
+ //be the case that some cluster beyond the next cluster
+ //contains a block having a matching track number, but for
+ //now we terminate the search immediately. We do this so that
+ //we don't end up searching the entire file looking for the
+ //next block. Another possibility is to try searching for the next
+ //block in a small, fixed number of clusters (intead searching
+ //just the next one), or to terminate the search when when the
+ //there is a large gap in time, or large gap in file position. It
+ //might very well be the case that the approach we use here is
+ //unnecessarily conservative.
+
+ //TODO: again, here's a case where we need to return the special
+ //EOS block. Or something. It's OK if pNext is NULL, because
+ //we only need it to set the stop time of the media sample.
+ //(The start time is determined from pCurr, which is non-NULL
+ //and non-EOS.) The problem is when we set pCurr=pNext; when
+ //pCurr has the value NULL we interpret that to mean that we
+ //haven't fully initialized pCurr and we attempt to set it to
+ //point to the first block for this track. But that's not what
+ //we want at all; we want the next call to PopulateSample to
+ //return end-of-stream, not (re)start from the beginning.
+ //
+ //One work-around is to send EOS immediately. We would send
+ //the EOS the next pass anyway, so maybe it's no great loss. The
+ //only problem is that if this the stream really does end one
+ //cluster early (relative to other tracks), or the last frame
+ //happens to be a keyframe ("CanSeekToEnd").
+ //
+ //The problem is that we need a way to mark as stream as
+ //"at end of stream" without actually being at end of stream.
+ //We need to give pCurr some value that means "you've reached EOS".
+ //We can't synthesize the special EOS Cluster immediately
+ //(when we first open the file, say), because we use the existance
+ //of that special cluster value to mean that we've read all of
+ //the clusters (this is a network download, so we can't know apriori
+ //how many we have).
+ //
+ //Or, we could return E_FAIL, and set another bit in the stream
+ //object itself, to indicate that it should send EOS earlier
+ //than when (pCurr=pStop).
+ //
+ //Or, probably the best solution, when we actually load the
+ //blocks into a cluster: if we notice that there's no block
+ //for a track, we synthesize a nonce EOS block for that track.
+ //That way we always have something to return. But that will
+ //only work for sequential scan???
+
+ //pNext = NULL;
+ //return E_FAIL;
+ pNextEntry = GetEOS();
+ return 1L;
+}
+
+
+Track::EOSBlock::EOSBlock()
+{
+}
+
+
+bool Track::EOSBlock::EOS() const
+{
+ return true;
+}
+
+
+Cluster* Track::EOSBlock::GetCluster() const
+{
+ return NULL;
+}
+
+
+size_t Track::EOSBlock::GetIndex() const
+{
+ return 0;
+}
+
+
+const Block* Track::EOSBlock::GetBlock() const
+{
+ return NULL;
+}
+
+
+bool Track::EOSBlock::IsBFrame() const
+{
+ return false;
+}
+
+
+VideoTrack::VideoTrack(Segment* pSegment, const Info& i) :
+ Track(pSegment, i),
+ m_width(-1),
+ m_height(-1),
+ m_rate(-1)
+{
+ assert(i.type == 1);
+ assert(i.number > 0);
+
+ IMkvReader* const pReader = pSegment->m_pReader;
+
+ const Settings& s = i.settings;
+ assert(s.start >= 0);
+ assert(s.size >= 0);
+
+ long long pos = s.start;
+ assert(pos >= 0);
+
+ const long long stop = pos + s.size;
+
+ while (pos < stop)
+ {
+#ifdef _DEBUG
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+#endif
+ if (Match(pReader, pos, 0x30, m_width))
+ ;
+ else if (Match(pReader, pos, 0x3A, m_height))
+ ;
+ else if (Match(pReader, pos, 0x0383E3, m_rate))
+ ;
+ else
+ {
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+
+ pos += len; //consume length of size
+ assert((pos + size) <= stop);
+
+ //pos now designates start of payload
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+ }
+ }
+
+ return;
+}
+
+
+bool VideoTrack::VetEntry(const BlockEntry* pBlockEntry) const
+{
+ assert(pBlockEntry);
+
+ const Block* const pBlock = pBlockEntry->GetBlock();
+ assert(pBlock);
+ assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number);
+
+ return pBlock->IsKey();
+}
+
+
+
+long long VideoTrack::GetWidth() const
+{
+ return m_width;
+}
+
+
+long long VideoTrack::GetHeight() const
+{
+ return m_height;
+}
+
+
+double VideoTrack::GetFrameRate() const
+{
+ return m_rate;
+}
+
+
+AudioTrack::AudioTrack(Segment* pSegment, const Info& i) :
+ Track(pSegment, i)
+{
+ assert(i.type == 2);
+ assert(i.number > 0);
+
+ IMkvReader* const pReader = pSegment->m_pReader;
+
+ const Settings& s = i.settings;
+ assert(s.start >= 0);
+ assert(s.size >= 0);
+
+ long long pos = s.start;
+ assert(pos >= 0);
+
+ const long long stop = pos + s.size;
+
+ while (pos < stop)
+ {
+#ifdef _DEBUG
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+#endif
+ if (Match(pReader, pos, 0x35, m_rate))
+ ;
+ else if (Match(pReader, pos, 0x1F, m_channels))
+ ;
+ else if (Match(pReader, pos, 0x2264, m_bitDepth))
+ ;
+ else
+ {
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+
+ pos += len; //consume length of size
+ assert((pos + size) <= stop);
+
+ //pos now designates start of payload
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+ }
+ }
+
+ return;
+}
+
+bool AudioTrack::VetEntry(const BlockEntry* pBlockEntry) const
+{
+ assert(pBlockEntry);
+
+ const Block* const pBlock = pBlockEntry->GetBlock();
+ assert(pBlock);
+ assert(pBlock->GetTrackNumber() == (unsigned long)m_info.number);
+
+ return true;
+}
+
+
+double AudioTrack::GetSamplingRate() const
+{
+ return m_rate;
+}
+
+
+long long AudioTrack::GetChannels() const
+{
+ return m_channels;
+}
+
+long long AudioTrack::GetBitDepth() const
+{
+ return m_bitDepth;
+}
+
+Tracks::Tracks(Segment* pSegment, long long start, long long size_) :
+ m_pSegment(pSegment),
+ m_start(start),
+ m_size(size_),
+ m_trackEntries(NULL),
+ m_trackEntriesEnd(NULL)
+{
+ long long stop = m_start + m_size;
+ IMkvReader* const pReader = m_pSegment->m_pReader;
+
+ long long pos1 = m_start;
+ int count = 0;
+
+ while (pos1 < stop)
+ {
+ long len;
+ const long long id = ReadUInt(pReader, pos1, len);
+ assert(id >= 0);
+ assert((pos1 + len) <= stop);
+
+ pos1 += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos1, len);
+ assert(size >= 0);
+ assert((pos1 + len) <= stop);
+
+ pos1 += len; //consume length of size
+
+ //pos now desinates start of element
+ if (id == 0x2E) //TrackEntry ID
+ ++count;
+
+ pos1 += size; //consume payload
+ assert(pos1 <= stop);
+ }
+
+ if (count <= 0)
+ return;
+
+ m_trackEntries = new Track*[count];
+ m_trackEntriesEnd = m_trackEntries;
+
+ long long pos = m_start;
+
+ while (pos < stop)
+ {
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long size1 = ReadUInt(pReader, pos, len);
+ assert(size1 >= 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume length of size
+
+ //pos now desinates start of element
+
+ if (id == 0x2E) //TrackEntry ID
+ ParseTrackEntry(pos, size1, *m_trackEntriesEnd++);
+
+ pos += size1; //consume payload
+ assert(pos <= stop);
+ }
+}
+
+unsigned long Tracks::GetTracksCount() const
+{
+ const ptrdiff_t result = m_trackEntriesEnd - m_trackEntries;
+ assert(result >= 0);
+
+ return static_cast<unsigned long>(result);
+}
+
+
+void Tracks::ParseTrackEntry(
+ long long start,
+ long long size,
+ Track*& pTrack)
+{
+ IMkvReader* const pReader = m_pSegment->m_pReader;
+
+ long long pos = start;
+ const long long stop = start + size;
+
+ Track::Info i;
+
+ Track::Settings videoSettings;
+ videoSettings.start = -1;
+
+ Track::Settings audioSettings;
+ audioSettings.start = -1;
+
+ while (pos < stop)
+ {
+#ifdef _DEBUG
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ len;
+ id;
+#endif
+ if (Match(pReader, pos, 0x57, i.number))
+ assert(i.number > 0);
+
+ else if (Match(pReader, pos, 0x33C5, i.uid))
+ ;
+
+ else if (Match(pReader, pos, 0x03, i.type))
+ ;
+
+ else if (Match(pReader, pos, 0x136E, i.nameAsUTF8))
+ assert(i.nameAsUTF8);
+
+ else if (Match(pReader, pos, 0x06, i.codecId))
+ ;
+
+ else if (Match(pReader, pos, 0x23A2, i.codecPrivate, &i.codecPrivateSize))
+ ;
+
+ else if (Match(pReader, pos, 0x058688, i.codecNameAsUTF8))
+ assert(i.codecNameAsUTF8);
+
+ else
+ {
+ long len;
+
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0); //TODO: handle error case
+ assert((pos + len) <= stop);
+
+ pos += len; //consume length of size
+ const long long start = pos;
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+
+ if (id == 0x60)
+ {
+ videoSettings.start = start;
+ videoSettings.size = size;
+ }
+ else if (id == 0x61)
+ {
+ audioSettings.start = start;
+ audioSettings.size = size;
+ }
+ }
+ }
+
+ assert(pos == stop);
+ //TODO: propertly vet info.number, to ensure both its existence,
+ //and that it is unique among all tracks.
+ assert(i.number > 0);
+
+ //TODO: vet settings, to ensure that video settings (0x60)
+ //were specified when type = 1, and that audio settings (0x61)
+ //were specified when type = 2.
+ if (i.type == 1) //video
+ {
+ assert(audioSettings.start < 0);
+ assert(videoSettings.start >= 0);
+
+ i.settings = videoSettings;
+
+ VideoTrack* const t = new VideoTrack(m_pSegment, i);
+ assert(t); //TODO
+ pTrack = t;
+ }
+ else if (i.type == 2) //audio
+ {
+ assert(videoSettings.start < 0);
+ assert(audioSettings.start >= 0);
+
+ i.settings = audioSettings;
+
+ AudioTrack* const t = new AudioTrack(m_pSegment, i);
+ assert(t); //TODO
+ pTrack = t;
+ }
+ else
+ {
+ // for now we do not support other track types yet.
+ // TODO: support other track types
+ i.Clear();
+
+ pTrack = NULL;
+ }
+
+ return;
+}
+
+
+Tracks::~Tracks()
+{
+ Track** i = m_trackEntries;
+ Track** const j = m_trackEntriesEnd;
+
+ while (i != j)
+ {
+ Track* pTrack = *i++;
+ delete pTrack;
+ pTrack = NULL;
+ }
+
+ delete[] m_trackEntries;
+}
+
+
+Track* Tracks::GetTrackByNumber(unsigned long tn) const
+{
+ Track** i = m_trackEntries;
+ Track** const j = m_trackEntriesEnd;
+
+ while (i != j)
+ {
+ Track* const pTrack = *i++;
+
+ if (pTrack == NULL)
+ continue;
+
+ if (tn == pTrack->GetNumber())
+ return pTrack;
+ }
+
+ return NULL; //not found
+}
+
+
+Track* Tracks::GetTrackByIndex(unsigned long idx) const
+{
+ const ptrdiff_t count = m_trackEntriesEnd - m_trackEntries;
+
+ if (idx >= static_cast<unsigned long>(count))
+ return NULL;
+
+ return m_trackEntries[idx];
+}
+
+
+void Cluster::Load()
+{
+ assert(m_pSegment);
+
+ if (m_start > 0)
+ {
+ assert(m_size > 0);
+ assert(m_timecode >= 0);
+ return;
+ }
+
+ assert(m_size == 0);
+ assert(m_timecode < 0);
+
+ IMkvReader* const pReader = m_pSegment->m_pReader;
+
+ const long long off = -m_start; //relative to segment
+ long long pos = m_pSegment->m_start + off; //absolute
+
+ long len;
+
+ const long long id_ = ReadUInt(pReader, pos, len);
+ assert(id_ >= 0);
+ assert(id_ == 0x0F43B675); //Cluster ID
+
+ pos += len; //consume id
+
+ const long long size_ = ReadUInt(pReader, pos, len);
+ assert(size_ >= 0);
+
+ pos += len; //consume size
+
+ m_start = pos;
+ m_size = size_;
+
+ const long long stop = m_start + size_;
+
+ long long timecode = -1;
+
+ while (pos < stop)
+ {
+ if (Match(pReader, pos, 0x67, timecode))
+ break;
+ else
+ {
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume size
+
+ if (id == 0x20) //BlockGroup ID
+ break;
+
+ if (id == 0x23) //SimpleBlock ID
+ break;
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+ }
+ }
+
+ assert(pos <= stop);
+ assert(timecode >= 0);
+
+ m_timecode = timecode;
+}
+
+
+Cluster* Cluster::Parse(
+ Segment* pSegment,
+ size_t idx,
+ long long off)
+{
+ assert(pSegment);
+ assert(off >= 0);
+ assert(off < pSegment->m_size);
+ Cluster* const pCluster = new Cluster(pSegment, idx, -off);
+ assert(pCluster);
+
+ return pCluster;
+}
+
+
+Cluster::Cluster() :
+ m_pSegment(NULL),
+ m_index(0),
+ m_start(0),
+ m_size(0),
+ m_timecode(0),
+ m_pEntries(NULL),
+ m_entriesCount(0)
+{
+}
+
+Cluster::Cluster(
+ Segment* pSegment,
+ size_t idx,
+ long long off) :
+ m_pSegment(pSegment),
+ m_index(idx),
+ m_start(off),
+ m_size(0),
+ m_timecode(-1),
+ m_pEntries(NULL),
+ m_entriesCount(0)
+{
+}
+
+
+Cluster::~Cluster()
+{
+#if 0
+ while (!m_pEntries.empty())
+ {
+ BlockEntry* pBlockEntry = m_pEntries.front();
+ assert(pBlockEntry);
+
+ m_pEntries.pop_front();
+ delete pBlockEntry;
+ }
+#else
+ BlockEntry** i = m_pEntries;
+ BlockEntry** const j = m_pEntries + m_entriesCount;
+ while (i != j)
+ {
+ BlockEntry* p = *i++;
+
+ assert(p);
+ delete p;
+ }
+
+ delete[] m_pEntries;
+#endif
+
+}
+
+bool Cluster::EOS() const
+{
+ return (m_pSegment == 0);
+}
+
+
+void Cluster::LoadBlockEntries()
+{
+ if (m_pEntries)
+ return;
+
+ Load();
+ assert(m_timecode >= 0);
+ assert(m_start > 0);
+ assert(m_size > 0);
+
+ IMkvReader* const pReader = m_pSegment->m_pReader;
+
+ long long pos = m_start;
+ const long long stop = m_start + m_size;
+ long long timecode = -1;
+
+ long long idx = pos;
+
+ m_entriesCount = 0;
+
+ while (idx < stop)
+ {
+ if (Match(pReader, idx, 0x67, timecode))
+ assert(timecode == m_timecode);
+ else
+ {
+ long len;
+
+ const long long id = ReadUInt(pReader, idx, len);
+ assert(id >= 0); //TODO
+ assert((idx + len) <= stop);
+
+ idx += len; //consume id
+
+ const long long size = ReadUInt(pReader, idx, len);
+ assert(size >= 0); //TODO
+ assert((idx + len) <= stop);
+
+ idx += len; //consume size
+
+ if (id == 0x20) //BlockGroup ID
+ ++m_entriesCount;
+ else if (id == 0x23) //SimpleBlock ID
+ ++m_entriesCount;
+
+ idx += size; //consume payload
+
+ assert(idx <= stop);
+ }
+ }
+
+ if (m_entriesCount == 0)
+ return;
+
+ m_pEntries = new BlockEntry*[m_entriesCount];
+ size_t index = 0;
+
+ while (pos < stop)
+ {
+ if (Match(pReader, pos, 0x67, timecode))
+ assert(timecode == m_timecode);
+ else
+ {
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume id
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume size
+
+ if (id == 0x20) //BlockGroup ID
+ ParseBlockGroup(pos, size, index++);
+ else if (id == 0x23) //SimpleBlock ID
+ ParseSimpleBlock(pos, size, index++);
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+ }
+ }
+
+ assert(pos == stop);
+ assert(timecode >= 0);
+ assert(index == m_entriesCount);
+}
+
+
+
+long long Cluster::GetTimeCode()
+{
+ Load();
+ return m_timecode;
+}
+
+
+long long Cluster::GetTime()
+{
+ const long long tc = GetTimeCode();
+ assert(tc >= 0);
+
+ const SegmentInfo* const pInfo = m_pSegment->GetInfo();
+ assert(pInfo);
+
+ const long long scale = pInfo->GetTimeCodeScale();
+ assert(scale >= 1);
+
+ const long long t = m_timecode * scale;
+
+ return t;
+}
+
+
+void Cluster::ParseBlockGroup(long long start, long long size, size_t index)
+{
+ assert(m_pEntries);
+ assert(m_entriesCount);
+ assert(index < m_entriesCount);
+
+ BlockGroup* const pGroup = new BlockGroup(this, index, start, size);
+ assert(pGroup); //TODO
+
+ m_pEntries[index] = pGroup;
+}
+
+
+
+void Cluster::ParseSimpleBlock(long long start, long long size, size_t index)
+{
+ assert(m_pEntries);
+ assert(m_entriesCount);
+ assert(index < m_entriesCount);
+
+ SimpleBlock* const pSimpleBlock = new SimpleBlock(this, index, start, size);
+ assert(pSimpleBlock); //TODO
+
+ m_pEntries[index] = pSimpleBlock;
+}
+
+
+const BlockEntry* Cluster::GetFirst()
+{
+ LoadBlockEntries();
+
+ return m_pEntries[0];
+}
+
+
+const BlockEntry* Cluster::GetLast()
+{
+ if (m_entriesCount == 0)
+ return m_pEntries[0];
+
+ return m_pEntries[m_entriesCount-1];
+}
+
+
+const BlockEntry* Cluster::GetNext(const BlockEntry* pEntry) const
+{
+ assert(pEntry);
+
+ size_t idx = pEntry->GetIndex();
+
+ ++idx;
+
+ if (idx == m_entriesCount)
+ return NULL;
+
+ return m_pEntries[idx];
+
+}
+
+
+const BlockEntry* Cluster::GetEntry(const Track* pTrack)
+{
+
+ assert(pTrack);
+
+ if (m_pSegment == NULL) //EOS
+ return pTrack->GetEOS();
+
+ LoadBlockEntries();
+
+ BlockEntry* i = *m_pEntries;
+ BlockEntry* j = *m_pEntries + m_entriesCount;
+ while (i != j)
+ {
+ BlockEntry* pEntry = i;
+ i++;
+ assert(pEntry);
+ assert(!pEntry->EOS());
+
+ const Block* const pBlock = pEntry->GetBlock();
+ assert(pBlock);
+
+ if (pBlock->GetTrackNumber() != pTrack->GetNumber())
+ continue;
+
+ if (pTrack->VetEntry(pEntry))
+ return pEntry;
+ }
+
+ return pTrack->GetEOS(); //no satisfactory block found
+}
+
+
+BlockEntry::BlockEntry()
+{
+}
+
+
+BlockEntry::~BlockEntry()
+{
+}
+
+
+
+SimpleBlock::SimpleBlock(
+ Cluster* pCluster,
+ size_t idx,
+ long long start,
+ long long size) :
+ m_pCluster(pCluster),
+ m_index(idx),
+ m_block(start, size, pCluster->m_pSegment->m_pReader)
+{
+}
+
+
+bool SimpleBlock::EOS() const
+{
+ return false;
+}
+
+
+Cluster* SimpleBlock::GetCluster() const
+{
+ return m_pCluster;
+}
+
+
+size_t SimpleBlock::GetIndex() const
+{
+ return m_index;
+}
+
+
+const Block* SimpleBlock::GetBlock() const
+{
+ return &m_block;
+}
+
+
+bool SimpleBlock::IsBFrame() const
+{
+ return false;
+}
+
+
+BlockGroup::BlockGroup(
+ Cluster* pCluster,
+ size_t idx,
+ long long start,
+ long long size_) :
+ m_pCluster(pCluster),
+ m_index(idx),
+ m_prevTimeCode(0),
+ m_nextTimeCode(0),
+ m_pBlock(NULL) //TODO: accept multiple blocks within a block group
+{
+ IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
+
+ long long pos = start;
+ const long long stop = start + size_;
+
+ bool bSimpleBlock = false;
+
+ while (pos < stop)
+ {
+ short t;
+
+ if (Match(pReader, pos, 0x7B, t))
+ {
+ if (t < 0)
+ m_prevTimeCode = t;
+ else if (t > 0)
+ m_nextTimeCode = t;
+ else
+ assert(false);
+ }
+ else
+ {
+ long len;
+ const long long id = ReadUInt(pReader, pos, len);
+ assert(id >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume ID
+
+ const long long size = ReadUInt(pReader, pos, len);
+ assert(size >= 0); //TODO
+ assert((pos + len) <= stop);
+
+ pos += len; //consume size
+
+ switch (id)
+ {
+ case 0x23: //SimpleBlock ID
+ bSimpleBlock = true;
+ //YES, FALL THROUGH TO NEXT CASE
+
+ case 0x21: //Block ID
+ ParseBlock(pos, size);
+ break;
+
+ default:
+ break;
+ }
+
+ pos += size; //consume payload
+ assert(pos <= stop);
+ }
+ }
+
+ assert(pos == stop);
+ assert(m_pBlock);
+
+ if (!bSimpleBlock)
+ m_pBlock->SetKey(m_prevTimeCode >= 0);
+}
+
+
+BlockGroup::~BlockGroup()
+{
+ delete m_pBlock;
+}
+
+
+void BlockGroup::ParseBlock(long long start, long long size)
+{
+ IMkvReader* const pReader = m_pCluster->m_pSegment->m_pReader;
+
+ Block* const pBlock = new Block(start, size, pReader);
+ assert(pBlock); //TODO
+
+ //TODO: the Matroska spec says you have multiple blocks within the
+ //same block group, with blocks ranked by priority (the flag bits).
+ //I haven't ever seen such a file (mkvmux certainly doesn't make
+ //one), so until then I'll just assume block groups contain a single
+ //block.
+#if 0
+ m_blocks.push_back(pBlock);
+#else
+ assert(m_pBlock == NULL);
+ m_pBlock = pBlock;
+#endif
+
+#if 0
+ Track* const pTrack = pBlock->GetTrack();
+ assert(pTrack);
+
+ pTrack->Insert(pBlock);
+#endif
+}
+
+
+bool BlockGroup::EOS() const
+{
+ return false;
+}
+
+
+Cluster* BlockGroup::GetCluster() const
+{
+ return m_pCluster;
+}
+
+
+size_t BlockGroup::GetIndex() const
+{
+ return m_index;
+}
+
+
+const Block* BlockGroup::GetBlock() const
+{
+ return m_pBlock;
+}
+
+
+short BlockGroup::GetPrevTimeCode() const
+{
+ return m_prevTimeCode;
+}
+
+
+short BlockGroup::GetNextTimeCode() const
+{
+ return m_nextTimeCode;
+}
+
+
+bool BlockGroup::IsBFrame() const
+{
+ return (m_nextTimeCode > 0);
+}
+
+
+
+Block::Block(long long start, long long size_, IMkvReader* pReader) :
+ m_start(start),
+ m_size(size_)
+{
+ long long pos = start;
+ const long long stop = start + size_;
+
+ long len;
+
+ m_track = ReadUInt(pReader, pos, len);
+ assert(m_track > 0);
+ assert((pos + len) <= stop);
+
+ pos += len; //consume track number
+ assert((stop - pos) >= 2);
+
+ m_timecode = Unserialize2SInt(pReader, pos);
+
+ pos += 2;
+ assert((stop - pos) >= 1);
+
+ const long hr = pReader->Read(pos, 1, &m_flags);
+ assert(hr == 0L);
+
+ ++pos;
+ assert(pos <= stop);
+
+ m_frameOff = pos;
+
+ const long long frame_size = stop - pos;
+
+ assert(frame_size <= 2147483647L);
+
+ m_frameSize = static_cast<long>(frame_size);
+}
+
+
+long long Block::GetTimeCode(Cluster* pCluster) const
+{
+ assert(pCluster);
+
+ const long long tc0 = pCluster->GetTimeCode();
+ assert(tc0 >= 0);
+
+ const long long tc = tc0 + static_cast<long long>(m_timecode);
+ assert(tc >= 0);
+
+ return tc; //unscaled timecode units
+}
+
+
+long long Block::GetTime(Cluster* pCluster) const
+{
+ assert(pCluster);
+
+ const long long tc = GetTimeCode(pCluster);
+
+ const Segment* const pSegment = pCluster->m_pSegment;
+ const SegmentInfo* const pInfo = pSegment->GetInfo();
+ assert(pInfo);
+
+ const long long scale = pInfo->GetTimeCodeScale();
+ assert(scale >= 1);
+
+ const long long ns = tc * scale;
+
+ return ns;
+}
+
+
+unsigned long Block::GetTrackNumber() const
+{
+ assert(m_track > 0);
+
+ return static_cast<unsigned long>(m_track);
+}
+
+
+bool Block::IsKey() const
+{
+ return ((m_flags & static_cast<unsigned char>(1 << 7)) != 0);
+}
+
+
+void Block::SetKey(bool bKey)
+{
+ if (bKey)
+ m_flags |= static_cast<unsigned char>(1 << 7);
+ else
+ m_flags &= 0x7F;
+}
+
+
+long Block::GetSize() const
+{
+ return m_frameSize;
+}
+
+
+long Block::Read(IMkvReader* pReader, unsigned char* buf) const
+{
+
+ assert(pReader);
+ assert(buf);
+
+ const long hr = pReader->Read(m_frameOff, m_frameSize, buf);
+
+ return hr;
+}
+
+
+} //end namespace mkvparser
diff --git a/media/libstagefright/matroska/mkvparser.hpp b/media/libstagefright/matroska/mkvparser.hpp
new file mode 100644
index 0000000..4d311b4
--- /dev/null
+++ b/media/libstagefright/matroska/mkvparser.hpp
@@ -0,0 +1,428 @@
+#ifndef MKVPARSER_HPP
+#define MKVPARSER_HPP
+
+#include <cstdlib>
+#include <cstdio>
+
+namespace mkvparser
+{
+
+const int E_FILE_FORMAT_INVALID = -2;
+const int E_BUFFER_NOT_FULL = -3;
+
+class IMkvReader
+{
+public:
+ virtual int Read(long long position, long length, unsigned char* buffer) = 0;
+ virtual int Length(long long* total, long long* available) = 0;
+protected:
+ virtual ~IMkvReader();
+};
+
+long long GetUIntLength(IMkvReader*, long long, long&);
+long long ReadUInt(IMkvReader*, long long, long&);
+long long SyncReadUInt(IMkvReader*, long long pos, long long stop, long&);
+long long UnserializeUInt(IMkvReader*, long long pos, long long size);
+float Unserialize4Float(IMkvReader*, long long);
+double Unserialize8Double(IMkvReader*, long long);
+short Unserialize2SInt(IMkvReader*, long long);
+signed char Unserialize1SInt(IMkvReader*, long long);
+bool Match(IMkvReader*, long long&, unsigned long, long long&);
+bool Match(IMkvReader*, long long&, unsigned long, char*&);
+bool Match(IMkvReader*, long long&, unsigned long,unsigned char*&,
+ size_t *optionalSize = NULL);
+bool Match(IMkvReader*, long long&, unsigned long, double&);
+bool Match(IMkvReader*, long long&, unsigned long, short&);
+
+
+struct EBMLHeader
+{
+ EBMLHeader();
+ ~EBMLHeader();
+ long long m_version;
+ long long m_readVersion;
+ long long m_maxIdLength;
+ long long m_maxSizeLength;
+ char* m_docType;
+ long long m_docTypeVersion;
+ long long m_docTypeReadVersion;
+
+ long long Parse(IMkvReader*, long long&);
+};
+
+
+class Segment;
+class Track;
+class Cluster;
+
+class Block
+{
+ Block(const Block&);
+ Block& operator=(const Block&);
+
+public:
+ const long long m_start;
+ const long long m_size;
+
+ Block(long long start, long long size, IMkvReader*);
+
+ unsigned long GetTrackNumber() const;
+
+ long long GetTimeCode(Cluster*) const; //absolute, but not scaled
+ long long GetTime(Cluster*) const; //absolute, and scaled (nanosecond units)
+ bool IsKey() const;
+ void SetKey(bool);
+
+ long GetSize() const;
+ long Read(IMkvReader*, unsigned char*) const;
+
+private:
+ long long m_track; //Track::Number()
+ short m_timecode; //relative to cluster
+ unsigned char m_flags;
+ long long m_frameOff;
+ long m_frameSize;
+
+};
+
+
+class BlockEntry
+{
+ BlockEntry(const BlockEntry&);
+ BlockEntry& operator=(const BlockEntry&);
+
+public:
+ virtual ~BlockEntry();
+ virtual bool EOS() const = 0;
+ virtual Cluster* GetCluster() const = 0;
+ virtual size_t GetIndex() const = 0;
+ virtual const Block* GetBlock() const = 0;
+ virtual bool IsBFrame() const = 0;
+
+protected:
+ BlockEntry();
+
+};
+
+
+class SimpleBlock : public BlockEntry
+{
+ SimpleBlock(const SimpleBlock&);
+ SimpleBlock& operator=(const SimpleBlock&);
+
+public:
+ SimpleBlock(Cluster*, size_t, long long start, long long size);
+
+ bool EOS() const;
+ Cluster* GetCluster() const;
+ size_t GetIndex() const;
+ const Block* GetBlock() const;
+ bool IsBFrame() const;
+
+protected:
+ Cluster* const m_pCluster;
+ const size_t m_index;
+ Block m_block;
+
+};
+
+
+class BlockGroup : public BlockEntry
+{
+ BlockGroup(const BlockGroup&);
+ BlockGroup& operator=(const BlockGroup&);
+
+public:
+ BlockGroup(Cluster*, size_t, long long, long long);
+ ~BlockGroup();
+
+ bool EOS() const;
+ Cluster* GetCluster() const;
+ size_t GetIndex() const;
+ const Block* GetBlock() const;
+ bool IsBFrame() const;
+
+ short GetPrevTimeCode() const; //relative to block's time
+ short GetNextTimeCode() const; //as above
+
+protected:
+ Cluster* const m_pCluster;
+ const size_t m_index;
+
+private:
+ BlockGroup(Cluster*, size_t, unsigned long);
+ void ParseBlock(long long start, long long size);
+
+ short m_prevTimeCode;
+ short m_nextTimeCode;
+
+ //TODO: the Matroska spec says you can have multiple blocks within the
+ //same block group, with blocks ranked by priority (the flag bits).
+ //For now we just cache a single block.
+#if 0
+ typedef std::deque<Block*> blocks_t;
+ blocks_t m_blocks; //In practice should contain only a single element.
+#else
+ Block* m_pBlock;
+#endif
+
+};
+
+
+class Track
+{
+ Track(const Track&);
+ Track& operator=(const Track&);
+
+public:
+ Segment* const m_pSegment;
+ virtual ~Track();
+
+ long long GetType() const;
+ unsigned long GetNumber() const;
+ const char* GetNameAsUTF8() const;
+ const char* GetCodecNameAsUTF8() const;
+ const char* GetCodecId() const;
+ const unsigned char* GetCodecPrivate(
+ size_t *optionalSize = NULL) const;
+
+ const BlockEntry* GetEOS() const;
+
+ struct Settings
+ {
+ long long start;
+ long long size;
+ };
+
+ struct Info
+ {
+ long long type;
+ long long number;
+ long long uid;
+ char* nameAsUTF8;
+ char* codecId;
+ unsigned char* codecPrivate;
+ size_t codecPrivateSize;
+ char* codecNameAsUTF8;
+ Settings settings;
+ Info();
+ void Clear();
+ };
+
+ long GetFirst(const BlockEntry*&) const;
+ long GetNext(const BlockEntry* pCurr, const BlockEntry*& pNext) const;
+ virtual bool VetEntry(const BlockEntry*) const = 0;
+
+protected:
+ Track(Segment*, const Info&);
+ const Info m_info;
+
+ class EOSBlock : public BlockEntry
+ {
+ public:
+ EOSBlock();
+
+ bool EOS() const;
+ Cluster* GetCluster() const;
+ size_t GetIndex() const;
+ const Block* GetBlock() const;
+ bool IsBFrame() const;
+ };
+
+ EOSBlock m_eos;
+
+};
+
+
+class VideoTrack : public Track
+{
+ VideoTrack(const VideoTrack&);
+ VideoTrack& operator=(const VideoTrack&);
+
+public:
+ VideoTrack(Segment*, const Info&);
+ long long GetWidth() const;
+ long long GetHeight() const;
+ double GetFrameRate() const;
+
+ bool VetEntry(const BlockEntry*) const;
+
+private:
+ long long m_width;
+ long long m_height;
+ double m_rate;
+
+};
+
+
+class AudioTrack : public Track
+{
+ AudioTrack(const AudioTrack&);
+ AudioTrack& operator=(const AudioTrack&);
+
+public:
+ AudioTrack(Segment*, const Info&);
+ double GetSamplingRate() const;
+ long long GetChannels() const;
+ long long GetBitDepth() const;
+ bool VetEntry(const BlockEntry*) const;
+
+private:
+ double m_rate;
+ long long m_channels;
+ long long m_bitDepth;
+};
+
+
+class Tracks
+{
+ Tracks(const Tracks&);
+ Tracks& operator=(const Tracks&);
+
+public:
+ Segment* const m_pSegment;
+ const long long m_start;
+ const long long m_size;
+
+ Tracks(Segment*, long long start, long long size);
+ virtual ~Tracks();
+
+ Track* GetTrackByNumber(unsigned long tn) const;
+ Track* GetTrackByIndex(unsigned long idx) const;
+
+private:
+ Track** m_trackEntries;
+ Track** m_trackEntriesEnd;
+
+ void ParseTrackEntry(long long, long long, Track*&);
+
+public:
+ unsigned long GetTracksCount() const;
+};
+
+
+class SegmentInfo
+{
+ SegmentInfo(const SegmentInfo&);
+ SegmentInfo& operator=(const SegmentInfo&);
+
+public:
+ Segment* const m_pSegment;
+ const long long m_start;
+ const long long m_size;
+
+ SegmentInfo(Segment*, long long start, long long size);
+ ~SegmentInfo();
+ long long GetTimeCodeScale() const;
+ long long GetDuration() const; //scaled
+ const char* GetMuxingAppAsUTF8() const;
+ const char* GetWritingAppAsUTF8() const;
+ const char* GetTitleAsUTF8() const;
+
+private:
+ long long m_timecodeScale;
+ double m_duration;
+ char* m_pMuxingAppAsUTF8;
+ char* m_pWritingAppAsUTF8;
+ char* m_pTitleAsUTF8;
+};
+
+
+class Cluster
+{
+ Cluster(const Cluster&);
+ Cluster& operator=(const Cluster&);
+
+public:
+ Segment* const m_pSegment;
+ const size_t m_index;
+
+public:
+ static Cluster* Parse(Segment*, size_t, long long off);
+
+ Cluster(); //EndOfStream
+ ~Cluster();
+
+ bool EOS() const;
+
+ long long GetTimeCode(); //absolute, but not scaled
+ long long GetTime(); //absolute, and scaled (nanosecond units)
+
+ const BlockEntry* GetFirst();
+ const BlockEntry* GetLast();
+ const BlockEntry* GetNext(const BlockEntry*) const;
+ const BlockEntry* GetEntry(const Track*);
+protected:
+ Cluster(Segment*, size_t, long long off);
+
+private:
+ long long m_start;
+ long long m_size;
+ long long m_timecode;
+ BlockEntry** m_pEntries;
+ size_t m_entriesCount;
+
+ void Load();
+ void LoadBlockEntries();
+ void ParseBlockGroup(long long, long long, size_t);
+ void ParseSimpleBlock(long long, long long, size_t);
+
+};
+
+
+class Segment
+{
+ Segment(const Segment&);
+ Segment& operator=(const Segment&);
+
+private:
+ Segment(IMkvReader*, long long pos, long long size);
+
+public:
+ IMkvReader* const m_pReader;
+ const long long m_start; //posn of segment payload
+ const long long m_size; //size of segment payload
+ Cluster m_eos; //TODO: make private?
+
+ static long long CreateInstance(IMkvReader*, long long, Segment*&);
+ ~Segment();
+
+ //for big-bang loading (source filter)
+ long Load();
+
+ //for incremental loading (splitter)
+ long long Unparsed() const;
+ long long ParseHeaders();
+ long ParseCluster(Cluster*&, long long& newpos) const;
+ bool AddCluster(Cluster*, long long);
+
+ Tracks* GetTracks() const;
+ const SegmentInfo* const GetInfo() const;
+ long long GetDuration() const;
+
+ //NOTE: this turned out to be too inefficient.
+ //long long Load(long long time_nanoseconds);
+
+ Cluster* GetFirst();
+ Cluster* GetLast();
+ unsigned long GetCount() const;
+
+ Cluster* GetNext(const Cluster*);
+ Cluster* GetCluster(long long time_nanoseconds);
+
+private:
+ long long m_pos; //absolute file posn; what has been consumed so far
+ SegmentInfo* m_pInfo;
+ Tracks* m_pTracks;
+ Cluster** m_clusters;
+ size_t m_clusterCount;
+
+ void ParseSeekHead(long long pos, long long size, size_t*);
+ void ParseSeekEntry(long long pos, long long size, size_t*);
+ void ParseSecondarySeekHead(long long off, size_t*);
+};
+
+
+} //end namespace mkvparser
+
+#endif //MKVPARSER_HPP
diff --git a/media/libstagefright/mpeg2ts/ABitReader.cpp b/media/libstagefright/mpeg2ts/ABitReader.cpp
new file mode 100644
index 0000000..24c8df8
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ABitReader.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ABitReader.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+ABitReader::ABitReader(const uint8_t *data, size_t size)
+ : mData(data),
+ mSize(size),
+ mReservoir(0),
+ mNumBitsLeft(0) {
+}
+
+void ABitReader::fillReservoir() {
+ CHECK_GT(mSize, 0u);
+
+ mReservoir = 0;
+ size_t i;
+ for (i = 0; mSize > 0 && i < 4; ++i) {
+ mReservoir = (mReservoir << 8) | *mData;
+
+ ++mData;
+ --mSize;
+ }
+
+ mNumBitsLeft = 8 * i;
+ mReservoir <<= 32 - mNumBitsLeft;
+}
+
+uint32_t ABitReader::getBits(size_t n) {
+ CHECK_LE(n, 32u);
+
+ uint32_t result = 0;
+ while (n > 0) {
+ if (mNumBitsLeft == 0) {
+ fillReservoir();
+ }
+
+ size_t m = n;
+ if (m > mNumBitsLeft) {
+ m = mNumBitsLeft;
+ }
+
+ result = (result << m) | (mReservoir >> (32 - m));
+ mReservoir <<= m;
+ mNumBitsLeft -= m;
+
+ n -= m;
+ }
+
+ return result;
+}
+
+void ABitReader::skipBits(size_t n) {
+ while (n > 32) {
+ getBits(32);
+ n -= 32;
+ }
+
+ if (n > 0) {
+ getBits(n);
+ }
+}
+
+void ABitReader::putBits(uint32_t x, size_t n) {
+ CHECK_LE(mNumBitsLeft + n, 32u);
+
+ mReservoir = (mReservoir >> n) | (x << (32 - n));
+ mNumBitsLeft += n;
+}
+
+size_t ABitReader::numBitsLeft() const {
+ return mSize * 8 + mNumBitsLeft;
+}
+
+const uint8_t *ABitReader::data() const {
+ CHECK_EQ(mNumBitsLeft % 8, 0u);
+
+ return mData - mNumBitsLeft / 8;
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/ABitReader.h b/media/libstagefright/mpeg2ts/ABitReader.h
new file mode 100644
index 0000000..5135211
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ABitReader.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_BIT_READER_H_
+
+#define A_BIT_READER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+
+namespace android {
+
+struct ABitReader {
+ ABitReader(const uint8_t *data, size_t size);
+
+ uint32_t getBits(size_t n);
+ void skipBits(size_t n);
+
+ size_t numBitsLeft() const;
+
+ const uint8_t *data() const;
+
+private:
+ const uint8_t *mData;
+ size_t mSize;
+
+ uint32_t mReservoir; // left-aligned bits
+ size_t mNumBitsLeft;
+
+ void fillReservoir();
+ void putBits(uint32_t x, size_t n);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ABitReader);
+};
+
+} // namespace android
+
+#endif // A_BIT_READER_H_
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
new file mode 100644
index 0000000..d05975d
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -0,0 +1,941 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ATSParser.h"
+
+#include "ABitReader.h"
+#include "AnotherPacketSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/KeyedVector.h>
+
+namespace android {
+
+static const size_t kTSPacketSize = 188;
+
+struct ATSParser::Program : public RefBase {
+ Program(unsigned programMapPID);
+
+ bool parsePID(
+ unsigned pid, unsigned payload_unit_start_indicator,
+ ABitReader *br);
+
+ sp<MediaSource> getSource(SourceType type);
+
+private:
+ unsigned mProgramMapPID;
+ KeyedVector<unsigned, sp<Stream> > mStreams;
+
+ void parseProgramMap(ABitReader *br);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Program);
+};
+
+struct ATSParser::Stream : public RefBase {
+ Stream(unsigned elementaryPID, unsigned streamType);
+
+ void parse(
+ unsigned payload_unit_start_indicator,
+ ABitReader *br);
+
+ sp<MediaSource> getSource(SourceType type);
+
+protected:
+ virtual ~Stream();
+
+private:
+ unsigned mElementaryPID;
+ unsigned mStreamType;
+
+ sp<ABuffer> mBuffer;
+ sp<AnotherPacketSource> mSource;
+ bool mPayloadStarted;
+
+ void flush();
+ void parsePES(ABitReader *br);
+
+ void onPayloadData(
+ unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
+ const uint8_t *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(Stream);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::Program::Program(unsigned programMapPID)
+ : mProgramMapPID(programMapPID) {
+}
+
+bool ATSParser::Program::parsePID(
+ unsigned pid, unsigned payload_unit_start_indicator,
+ ABitReader *br) {
+ if (pid == mProgramMapPID) {
+ if (payload_unit_start_indicator) {
+ unsigned skip = br->getBits(8);
+ br->skipBits(skip * 8);
+ }
+
+ parseProgramMap(br);
+ return true;
+ }
+
+ ssize_t index = mStreams.indexOfKey(pid);
+ if (index < 0) {
+ return false;
+ }
+
+ mStreams.editValueAt(index)->parse(
+ payload_unit_start_indicator, br);
+
+ return true;
+}
+
+void ATSParser::Program::parseProgramMap(ABitReader *br) {
+ unsigned table_id = br->getBits(8);
+ LOG(VERBOSE) << " table_id = " << table_id;
+ CHECK_EQ(table_id, 0x02u);
+
+ unsigned section_syntax_indictor = br->getBits(1);
+ LOG(VERBOSE) << " section_syntax_indictor = " << section_syntax_indictor;
+ CHECK_EQ(section_syntax_indictor, 1u);
+
+ CHECK_EQ(br->getBits(1), 0u);
+ LOG(VERBOSE) << " reserved = " << br->getBits(2);
+
+ unsigned section_length = br->getBits(12);
+ LOG(VERBOSE) << " section_length = " << section_length;
+ CHECK((section_length & 0xc00) == 0);
+ CHECK_LE(section_length, 1021u);
+
+ LOG(VERBOSE) << " program_number = " << br->getBits(16);
+ LOG(VERBOSE) << " reserved = " << br->getBits(2);
+ LOG(VERBOSE) << " version_number = " << br->getBits(5);
+ LOG(VERBOSE) << " current_next_indicator = " << br->getBits(1);
+ LOG(VERBOSE) << " section_number = " << br->getBits(8);
+ LOG(VERBOSE) << " last_section_number = " << br->getBits(8);
+ LOG(VERBOSE) << " reserved = " << br->getBits(3);
+
+ LOG(VERBOSE) << " PCR_PID = "
+ << StringPrintf("0x%04x", br->getBits(13));
+
+ LOG(VERBOSE) << " reserved = " << br->getBits(4);
+
+ unsigned program_info_length = br->getBits(12);
+ LOG(VERBOSE) << " program_info_length = " << program_info_length;
+ CHECK((program_info_length & 0xc00) == 0);
+
+ br->skipBits(program_info_length * 8); // skip descriptors
+
+ // infoBytesRemaining is the number of bytes that make up the
+ // variable length section of ES_infos. It does not include the
+ // final CRC.
+ size_t infoBytesRemaining = section_length - 9 - program_info_length - 4;
+
+ while (infoBytesRemaining > 0) {
+ CHECK_GE(infoBytesRemaining, 5u);
+
+ unsigned streamType = br->getBits(8);
+ LOG(VERBOSE) << " stream_type = "
+ << StringPrintf("0x%02x", streamType);
+
+ LOG(VERBOSE) << " reserved = " << br->getBits(3);
+
+ unsigned elementaryPID = br->getBits(13);
+ LOG(VERBOSE) << " elementary_PID = "
+ << StringPrintf("0x%04x", elementaryPID);
+
+ LOG(VERBOSE) << " reserved = " << br->getBits(4);
+
+ unsigned ES_info_length = br->getBits(12);
+ LOG(VERBOSE) << " ES_info_length = " << ES_info_length;
+ CHECK((ES_info_length & 0xc00) == 0);
+
+ CHECK_GE(infoBytesRemaining - 5, ES_info_length);
+
+#if 0
+ br->skipBits(ES_info_length * 8); // skip descriptors
+#else
+ unsigned info_bytes_remaining = ES_info_length;
+ while (info_bytes_remaining >= 2) {
+ LOG(VERBOSE) << " tag = " << StringPrintf("0x%02x", br->getBits(8));
+
+ unsigned descLength = br->getBits(8);
+ LOG(VERBOSE) << " len = " << descLength;
+
+ CHECK_GE(info_bytes_remaining, 2 + descLength);
+
+ br->skipBits(descLength * 8);
+
+ info_bytes_remaining -= descLength + 2;
+ }
+ CHECK_EQ(info_bytes_remaining, 0u);
+#endif
+
+ ssize_t index = mStreams.indexOfKey(elementaryPID);
+#if 0 // XXX revisit
+ CHECK_LT(index, 0);
+ mStreams.add(elementaryPID, new Stream(elementaryPID, streamType));
+#else
+ if (index < 0) {
+ mStreams.add(elementaryPID, new Stream(elementaryPID, streamType));
+ }
+#endif
+
+ infoBytesRemaining -= 5 + ES_info_length;
+ }
+
+ CHECK_EQ(infoBytesRemaining, 0u);
+
+ LOG(VERBOSE) << " CRC = " << StringPrintf("0x%08x", br->getBits(32));
+}
+
+sp<MediaSource> ATSParser::Program::getSource(SourceType type) {
+ for (size_t i = 0; i < mStreams.size(); ++i) {
+ sp<MediaSource> source = mStreams.editValueAt(i)->getSource(type);
+ if (source != NULL) {
+ return source;
+ }
+ }
+
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::Stream::Stream(unsigned elementaryPID, unsigned streamType)
+ : mElementaryPID(elementaryPID),
+ mStreamType(streamType),
+ mBuffer(new ABuffer(65536)),
+ mPayloadStarted(false) {
+ mBuffer->setRange(0, 0);
+}
+
+ATSParser::Stream::~Stream() {
+}
+
+void ATSParser::Stream::parse(
+ unsigned payload_unit_start_indicator, ABitReader *br) {
+ if (payload_unit_start_indicator) {
+ if (mPayloadStarted) {
+ // Otherwise we run the danger of receiving the trailing bytes
+ // of a PES packet that we never saw the start of and assuming
+ // we have a a complete PES packet.
+
+ flush();
+ }
+
+ mPayloadStarted = true;
+ }
+
+ if (!mPayloadStarted) {
+ return;
+ }
+
+ size_t payloadSizeBits = br->numBitsLeft();
+ CHECK_EQ(payloadSizeBits % 8, 0u);
+
+ CHECK_LE(mBuffer->size() + payloadSizeBits / 8, mBuffer->capacity());
+
+ memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
+ mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
+}
+
+void ATSParser::Stream::parsePES(ABitReader *br) {
+ unsigned packet_startcode_prefix = br->getBits(24);
+
+ LOG(VERBOSE) << "packet_startcode_prefix = "
+ << StringPrintf("0x%08x", packet_startcode_prefix);
+
+ CHECK_EQ(packet_startcode_prefix, 0x000001u);
+
+ unsigned stream_id = br->getBits(8);
+ LOG(VERBOSE) << "stream_id = " << StringPrintf("0x%02x", stream_id);
+
+ unsigned PES_packet_length = br->getBits(16);
+ LOG(VERBOSE) << "PES_packet_length = " << PES_packet_length;
+
+ if (stream_id != 0xbc // program_stream_map
+ && stream_id != 0xbe // padding_stream
+ && stream_id != 0xbf // private_stream_2
+ && stream_id != 0xf0 // ECM
+ && stream_id != 0xf1 // EMM
+ && stream_id != 0xff // program_stream_directory
+ && stream_id != 0xf2 // DSMCC
+ && stream_id != 0xf8) { // H.222.1 type E
+ CHECK_EQ(br->getBits(2), 2u);
+
+ LOG(VERBOSE) << "PES_scrambling_control = " << br->getBits(2);
+ LOG(VERBOSE) << "PES_priority = " << br->getBits(1);
+ LOG(VERBOSE) << "data_alignment_indicator = " << br->getBits(1);
+ LOG(VERBOSE) << "copyright = " << br->getBits(1);
+ LOG(VERBOSE) << "original_or_copy = " << br->getBits(1);
+
+ unsigned PTS_DTS_flags = br->getBits(2);
+ LOG(VERBOSE) << "PTS_DTS_flags = " << PTS_DTS_flags;
+
+ unsigned ESCR_flag = br->getBits(1);
+ LOG(VERBOSE) << "ESCR_flag = " << ESCR_flag;
+
+ unsigned ES_rate_flag = br->getBits(1);
+ LOG(VERBOSE) << "ES_rate_flag = " << ES_rate_flag;
+
+ unsigned DSM_trick_mode_flag = br->getBits(1);
+ LOG(VERBOSE) << "DSM_trick_mode_flag = " << DSM_trick_mode_flag;
+
+ unsigned additional_copy_info_flag = br->getBits(1);
+ LOG(VERBOSE) << "additional_copy_info_flag = "
+ << additional_copy_info_flag;
+
+ LOG(VERBOSE) << "PES_CRC_flag = " << br->getBits(1);
+ LOG(VERBOSE) << "PES_extension_flag = " << br->getBits(1);
+
+ unsigned PES_header_data_length = br->getBits(8);
+ LOG(VERBOSE) << "PES_header_data_length = " << PES_header_data_length;
+
+ unsigned optional_bytes_remaining = PES_header_data_length;
+
+ uint64_t PTS = 0, DTS = 0;
+
+ if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
+ CHECK_GE(optional_bytes_remaining, 5u);
+
+ CHECK_EQ(br->getBits(4), PTS_DTS_flags);
+
+ PTS = ((uint64_t)br->getBits(3)) << 30;
+ CHECK_EQ(br->getBits(1), 1u);
+ PTS |= ((uint64_t)br->getBits(15)) << 15;
+ CHECK_EQ(br->getBits(1), 1u);
+ PTS |= br->getBits(15);
+ CHECK_EQ(br->getBits(1), 1u);
+
+ LOG(VERBOSE) << "PTS = " << PTS;
+ // LOG(INFO) << "PTS = " << PTS / 90000.0f << " secs";
+
+ optional_bytes_remaining -= 5;
+
+ if (PTS_DTS_flags == 3) {
+ CHECK_GE(optional_bytes_remaining, 5u);
+
+ CHECK_EQ(br->getBits(4), 1u);
+
+ DTS = ((uint64_t)br->getBits(3)) << 30;
+ CHECK_EQ(br->getBits(1), 1u);
+ DTS |= ((uint64_t)br->getBits(15)) << 15;
+ CHECK_EQ(br->getBits(1), 1u);
+ DTS |= br->getBits(15);
+ CHECK_EQ(br->getBits(1), 1u);
+
+ LOG(VERBOSE) << "DTS = " << DTS;
+
+ optional_bytes_remaining -= 5;
+ }
+ }
+
+ if (ESCR_flag) {
+ CHECK_GE(optional_bytes_remaining, 6u);
+
+ br->getBits(2);
+
+ uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
+ CHECK_EQ(br->getBits(1), 1u);
+ ESCR |= ((uint64_t)br->getBits(15)) << 15;
+ CHECK_EQ(br->getBits(1), 1u);
+ ESCR |= br->getBits(15);
+ CHECK_EQ(br->getBits(1), 1u);
+
+ LOG(VERBOSE) << "ESCR = " << ESCR;
+ LOG(VERBOSE) << "ESCR_extension = " << br->getBits(9);
+
+ CHECK_EQ(br->getBits(1), 1u);
+
+ optional_bytes_remaining -= 6;
+ }
+
+ if (ES_rate_flag) {
+ CHECK_GE(optional_bytes_remaining, 3u);
+
+ CHECK_EQ(br->getBits(1), 1u);
+ LOG(VERBOSE) << "ES_rate = " << br->getBits(22);
+ CHECK_EQ(br->getBits(1), 1u);
+
+ optional_bytes_remaining -= 3;
+ }
+
+ br->skipBits(optional_bytes_remaining * 8);
+
+ // ES data follows.
+
+ onPayloadData(
+ PTS_DTS_flags, PTS, DTS,
+ br->data(), br->numBitsLeft() / 8);
+
+ if (PES_packet_length != 0) {
+ CHECK_GE(PES_packet_length, PES_header_data_length + 3);
+
+ unsigned dataLength =
+ PES_packet_length - 3 - PES_header_data_length;
+
+ CHECK_EQ(br->numBitsLeft(), dataLength * 8);
+
+ br->skipBits(dataLength * 8);
+ } else {
+ size_t payloadSizeBits = br->numBitsLeft();
+ CHECK((payloadSizeBits % 8) == 0);
+
+ LOG(VERBOSE) << "There's " << (payloadSizeBits / 8)
+ << " bytes of payload.";
+ }
+ } else if (stream_id == 0xbe) { // padding_stream
+ CHECK_NE(PES_packet_length, 0u);
+ br->skipBits(PES_packet_length * 8);
+ } else {
+ CHECK_NE(PES_packet_length, 0u);
+ br->skipBits(PES_packet_length * 8);
+ }
+}
+
+void ATSParser::Stream::flush() {
+ if (mBuffer->size() == 0) {
+ return;
+ }
+
+ LOG(VERBOSE) << "flushing stream "
+ << StringPrintf("0x%04x", mElementaryPID)
+ << " size = " << mBuffer->size();
+
+ ABitReader br(mBuffer->data(), mBuffer->size());
+ parsePES(&br);
+
+ mBuffer->setRange(0, 0);
+}
+
+static sp<ABuffer> FindNAL(
+ const uint8_t *data, size_t size, unsigned nalType,
+ size_t *stopOffset) {
+ bool foundStart = false;
+ size_t startOffset = 0;
+
+ size_t offset = 0;
+ for (;;) {
+ while (offset + 3 < size
+ && memcmp("\x00\x00\x00\x01", &data[offset], 4)) {
+ ++offset;
+ }
+
+ if (foundStart) {
+ size_t nalSize;
+ if (offset + 3 >= size) {
+ nalSize = size - startOffset;
+ } else {
+ nalSize = offset - startOffset;
+ }
+
+ sp<ABuffer> nal = new ABuffer(nalSize);
+ memcpy(nal->data(), &data[startOffset], nalSize);
+
+ if (stopOffset != NULL) {
+ *stopOffset = startOffset + nalSize;
+ }
+
+ return nal;
+ }
+
+ if (offset + 4 >= size) {
+ return NULL;
+ }
+
+ if ((data[offset + 4] & 0x1f) == nalType) {
+ foundStart = true;
+ startOffset = offset + 4;
+ }
+
+ offset += 4;
+ }
+}
+
+static unsigned parseUE(ABitReader *br) {
+ unsigned numZeroes = 0;
+ while (br->getBits(1) == 0) {
+ ++numZeroes;
+ }
+
+ unsigned x = br->getBits(numZeroes);
+
+ return x + (1u << numZeroes) - 1;
+}
+
+// Determine video dimensions from the sequence parameterset.
+static void FindDimensions(
+ const sp<ABuffer> seqParamSet, int32_t *width, int32_t *height) {
+ ABitReader br(seqParamSet->data() + 1, seqParamSet->size() - 1);
+
+ unsigned profile_idc = br.getBits(8);
+ br.skipBits(16);
+ parseUE(&br); // seq_parameter_set_id
+
+ if (profile_idc == 100 || profile_idc == 110
+ || profile_idc == 122 || profile_idc == 144) {
+ TRESPASS();
+ }
+
+ parseUE(&br); // log2_max_frame_num_minus4
+ unsigned pic_order_cnt_type = parseUE(&br);
+
+ if (pic_order_cnt_type == 0) {
+ parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4
+ } else if (pic_order_cnt_type == 1) {
+ br.getBits(1); // delta_pic_order_always_zero_flag
+ parseUE(&br); // offset_for_non_ref_pic
+ parseUE(&br); // offset_for_top_to_bottom_field
+
+ unsigned num_ref_frames_in_pic_order_cnt_cycle = parseUE(&br);
+ for (unsigned i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; ++i) {
+ parseUE(&br); // offset_for_ref_frame
+ }
+ }
+
+ parseUE(&br); // num_ref_frames
+ br.getBits(1); // gaps_in_frame_num_value_allowed_flag
+
+ unsigned pic_width_in_mbs_minus1 = parseUE(&br);
+ unsigned pic_height_in_map_units_minus1 = parseUE(&br);
+ unsigned frame_mbs_only_flag = br.getBits(1);
+
+ *width = pic_width_in_mbs_minus1 * 16 + 16;
+
+ *height = (2 - frame_mbs_only_flag)
+ * (pic_height_in_map_units_minus1 * 16 + 16);
+}
+
+static sp<ABuffer> MakeAVCCodecSpecificData(
+ const sp<ABuffer> &buffer, int32_t *width, int32_t *height) {
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL);
+ if (seqParamSet == NULL) {
+ return NULL;
+ }
+
+ FindDimensions(seqParamSet, width, height);
+
+ size_t stopOffset;
+ sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset);
+ CHECK(picParamSet != NULL);
+
+ buffer->setRange(stopOffset, size - stopOffset);
+ LOG(INFO) << "buffer has " << buffer->size() << " bytes left.";
+
+ size_t csdSize =
+ 1 + 3 + 1 + 1
+ + 2 * 1 + seqParamSet->size()
+ + 1 + 2 * 1 + picParamSet->size();
+
+ sp<ABuffer> csd = new ABuffer(csdSize);
+ uint8_t *out = csd->data();
+
+ *out++ = 0x01; // configurationVersion
+ memcpy(out, seqParamSet->data() + 1, 3); // profile/level...
+ out += 3;
+ *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes
+ *out++ = 0xe0 | 1;
+
+ *out++ = seqParamSet->size() >> 8;
+ *out++ = seqParamSet->size() & 0xff;
+ memcpy(out, seqParamSet->data(), seqParamSet->size());
+ out += seqParamSet->size();
+
+ *out++ = 1;
+
+ *out++ = picParamSet->size() >> 8;
+ *out++ = picParamSet->size() & 0xff;
+ memcpy(out, picParamSet->data(), picParamSet->size());
+
+ return csd;
+}
+
+static bool getNextNALUnit(
+ const uint8_t **_data, size_t *_size,
+ const uint8_t **nalStart, size_t *nalSize) {
+ const uint8_t *data = *_data;
+ size_t size = *_size;
+
+ *nalStart = NULL;
+ *nalSize = 0;
+
+ if (size == 0) {
+ return false;
+ }
+
+ size_t offset = 0;
+ for (;;) {
+ CHECK_LT(offset + 2, size);
+
+ if (!memcmp("\x00\x00\x01", &data[offset], 3)) {
+ break;
+ }
+
+ CHECK_EQ((unsigned)data[offset], 0x00u);
+ ++offset;
+ }
+
+ offset += 3;
+ size_t startOffset = offset;
+
+ while (offset + 2 < size
+ && memcmp("\x00\x00\x00", &data[offset], 3)
+ && memcmp("\x00\x00\x01", &data[offset], 3)) {
+ ++offset;
+ }
+
+ if (offset + 2 >= size) {
+ *nalStart = &data[startOffset];
+ *nalSize = size - startOffset;
+
+ *_data = NULL;
+ *_size = 0;
+
+ return true;
+ }
+
+ size_t endOffset = offset;
+
+ while (offset + 2 < size && memcmp("\x00\x00\x01", &data[offset], 3)) {
+ CHECK_EQ((unsigned)data[offset], 0x00u);
+ ++offset;
+ }
+
+ CHECK_LT(offset + 2, size);
+
+ *nalStart = &data[startOffset];
+ *nalSize = endOffset - startOffset;
+
+ *_data = &data[offset];
+ *_size = size - offset;
+
+ return true;
+}
+
+sp<ABuffer> MakeCleanAVCData(const uint8_t *data, size_t size) {
+ const uint8_t *tmpData = data;
+ size_t tmpSize = size;
+
+ size_t totalSize = 0;
+ const uint8_t *nalStart;
+ size_t nalSize;
+ while (getNextNALUnit(&tmpData, &tmpSize, &nalStart, &nalSize)) {
+ totalSize += 4 + nalSize;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(totalSize);
+ size_t offset = 0;
+ while (getNextNALUnit(&data, &size, &nalStart, &nalSize)) {
+ memcpy(buffer->data() + offset, "\x00\x00\x00\x01", 4);
+ memcpy(buffer->data() + offset + 4, nalStart, nalSize);
+
+ offset += 4 + nalSize;
+ }
+
+ return buffer;
+}
+
+static sp<ABuffer> FindMPEG2ADTSConfig(
+ const sp<ABuffer> &buffer, int32_t *sampleRate, int32_t *channelCount) {
+ ABitReader br(buffer->data(), buffer->size());
+
+ CHECK_EQ(br.getBits(12), 0xfffu);
+ CHECK_EQ(br.getBits(1), 0u);
+ CHECK_EQ(br.getBits(2), 0u);
+ br.getBits(1); // protection_absent
+ unsigned profile = br.getBits(2);
+ LOG(INFO) << "profile = " << profile;
+ CHECK_NE(profile, 3u);
+ unsigned sampling_freq_index = br.getBits(4);
+ br.getBits(1); // private_bit
+ unsigned channel_configuration = br.getBits(3);
+ CHECK_NE(channel_configuration, 0u);
+
+ LOG(INFO) << "sampling_freq_index = " << sampling_freq_index;
+ LOG(INFO) << "channel_configuration = " << channel_configuration;
+
+ CHECK_LE(sampling_freq_index, 11u);
+ static const int32_t kSamplingFreq[] = {
+ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+ 16000, 12000, 11025, 8000
+ };
+ *sampleRate = kSamplingFreq[sampling_freq_index];
+
+ *channelCount = channel_configuration;
+
+ static const uint8_t kStaticESDS[] = {
+ 0x03, 22,
+ 0x00, 0x00, // ES_ID
+ 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ 0x04, 17,
+ 0x40, // Audio ISO/IEC 14496-3
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x05, 2,
+ // AudioSpecificInfo follows
+
+ // oooo offf fccc c000
+ // o - audioObjectType
+ // f - samplingFreqIndex
+ // c - channelConfig
+ };
+ sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
+ memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
+
+ csd->data()[sizeof(kStaticESDS)] =
+ ((profile + 1) << 3) | (sampling_freq_index >> 1);
+
+ csd->data()[sizeof(kStaticESDS) + 1] =
+ ((sampling_freq_index << 7) & 0x80) | (channel_configuration << 3);
+
+ hexdump(csd->data(), csd->size());
+ return csd;
+}
+
+void ATSParser::Stream::onPayloadData(
+ unsigned PTS_DTS_flags, uint64_t PTS, uint64_t DTS,
+ const uint8_t *data, size_t size) {
+ LOG(VERBOSE) << "onPayloadData mStreamType="
+ << StringPrintf("0x%02x", mStreamType);
+
+ sp<ABuffer> buffer;
+
+ if (mStreamType == 0x1b) {
+ buffer = MakeCleanAVCData(data, size);
+ } else {
+ // hexdump(data, size);
+
+ buffer = new ABuffer(size);
+ memcpy(buffer->data(), data, size);
+ }
+
+ if (mSource == NULL) {
+ sp<MetaData> meta = new MetaData;
+
+ if (mStreamType == 0x1b) {
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+ int32_t width, height;
+ sp<ABuffer> csd = MakeAVCCodecSpecificData(buffer, &width, &height);
+
+ if (csd == NULL) {
+ return;
+ }
+
+ meta->setData(kKeyAVCC, 0, csd->data(), csd->size());
+ meta->setInt32(kKeyWidth, width);
+ meta->setInt32(kKeyHeight, height);
+ } else {
+ CHECK_EQ(mStreamType, 0x0fu);
+
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+ int32_t sampleRate, channelCount;
+ sp<ABuffer> csd =
+ FindMPEG2ADTSConfig(buffer, &sampleRate, &channelCount);
+
+ LOG(INFO) << "sampleRate = " << sampleRate;
+ LOG(INFO) << "channelCount = " << channelCount;
+
+ meta->setInt32(kKeySampleRate, sampleRate);
+ meta->setInt32(kKeyChannelCount, channelCount);
+
+ meta->setData(kKeyESDS, 0, csd->data(), csd->size());
+ }
+
+ LOG(INFO) << "created source!";
+ mSource = new AnotherPacketSource(meta);
+
+ // fall through
+ }
+
+ CHECK(PTS_DTS_flags == 2 || PTS_DTS_flags == 3);
+ buffer->meta()->setInt64("time", (PTS * 100) / 9);
+
+ if (mStreamType == 0x0f) {
+ // WHY???
+ buffer->setRange(7, buffer->size() - 7);
+ }
+
+ mSource->queueAccessUnit(buffer);
+}
+
+sp<MediaSource> ATSParser::Stream::getSource(SourceType type) {
+ if ((type == AVC_VIDEO && mStreamType == 0x1b)
+ || (type == MPEG2ADTS_AUDIO && mStreamType == 0x0f)) {
+ return mSource;
+ }
+
+ return NULL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+ATSParser::ATSParser() {
+}
+
+ATSParser::~ATSParser() {
+}
+
+void ATSParser::feedTSPacket(const void *data, size_t size) {
+ CHECK_EQ(size, kTSPacketSize);
+
+ ABitReader br((const uint8_t *)data, kTSPacketSize);
+ parseTS(&br);
+}
+
+void ATSParser::parseProgramAssociationTable(ABitReader *br) {
+ unsigned table_id = br->getBits(8);
+ LOG(VERBOSE) << " table_id = " << table_id;
+ CHECK_EQ(table_id, 0x00u);
+
+ unsigned section_syntax_indictor = br->getBits(1);
+ LOG(VERBOSE) << " section_syntax_indictor = " << section_syntax_indictor;
+ CHECK_EQ(section_syntax_indictor, 1u);
+
+ CHECK_EQ(br->getBits(1), 0u);
+ LOG(VERBOSE) << " reserved = " << br->getBits(2);
+
+ unsigned section_length = br->getBits(12);
+ LOG(VERBOSE) << " section_length = " << section_length;
+ CHECK((section_length & 0xc00) == 0);
+
+ LOG(VERBOSE) << " transport_stream_id = " << br->getBits(16);
+ LOG(VERBOSE) << " reserved = " << br->getBits(2);
+ LOG(VERBOSE) << " version_number = " << br->getBits(5);
+ LOG(VERBOSE) << " current_next_indicator = " << br->getBits(1);
+ LOG(VERBOSE) << " section_number = " << br->getBits(8);
+ LOG(VERBOSE) << " last_section_number = " << br->getBits(8);
+
+ size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
+ CHECK_EQ((numProgramBytes % 4), 0u);
+
+ for (size_t i = 0; i < numProgramBytes / 4; ++i) {
+ unsigned program_number = br->getBits(16);
+ LOG(VERBOSE) << " program_number = " << program_number;
+
+ LOG(VERBOSE) << " reserved = " << br->getBits(3);
+
+ if (program_number == 0) {
+ LOG(VERBOSE) << " network_PID = "
+ << StringPrintf("0x%04x", br->getBits(13));
+ } else {
+ unsigned programMapPID = br->getBits(13);
+
+ LOG(VERBOSE) << " program_map_PID = "
+ << StringPrintf("0x%04x", programMapPID);
+
+ mPrograms.push(new Program(programMapPID));
+ }
+ }
+
+ LOG(VERBOSE) << " CRC = " << StringPrintf("0x%08x", br->getBits(32));
+}
+
+void ATSParser::parsePID(
+ ABitReader *br, unsigned PID,
+ unsigned payload_unit_start_indicator) {
+ if (PID == 0) {
+ if (payload_unit_start_indicator) {
+ unsigned skip = br->getBits(8);
+ br->skipBits(skip * 8);
+ }
+ parseProgramAssociationTable(br);
+ return;
+ }
+
+ bool handled = false;
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ if (mPrograms.editItemAt(i)->parsePID(
+ PID, payload_unit_start_indicator, br)) {
+ handled = true;
+ break;
+ }
+ }
+
+ if (!handled) {
+ LOG(WARNING) << "PID " << StringPrintf("0x%04x", PID)
+ << " not handled.";
+ }
+}
+
+void ATSParser::parseAdaptationField(ABitReader *br) {
+ unsigned adaptation_field_length = br->getBits(8);
+ if (adaptation_field_length > 0) {
+ br->skipBits(adaptation_field_length * 8); // XXX
+ }
+}
+
+void ATSParser::parseTS(ABitReader *br) {
+ LOG(VERBOSE) << "---";
+
+ unsigned sync_byte = br->getBits(8);
+ CHECK_EQ(sync_byte, 0x47u);
+
+ LOG(VERBOSE) << "transport_error_indicator = " << br->getBits(1);
+
+ unsigned payload_unit_start_indicator = br->getBits(1);
+ LOG(VERBOSE) << "payload_unit_start_indicator = "
+ << payload_unit_start_indicator;
+
+ LOG(VERBOSE) << "transport_priority = " << br->getBits(1);
+
+ unsigned PID = br->getBits(13);
+ LOG(VERBOSE) << "PID = " << StringPrintf("0x%04x", PID);
+
+ LOG(VERBOSE) << "transport_scrambling_control = " << br->getBits(2);
+
+ unsigned adaptation_field_control = br->getBits(2);
+ LOG(VERBOSE) << "adaptation_field_control = " << adaptation_field_control;
+
+ LOG(VERBOSE) << "continuity_counter = " << br->getBits(4);
+
+ if (adaptation_field_control == 2 || adaptation_field_control == 3) {
+ parseAdaptationField(br);
+ }
+
+ if (adaptation_field_control == 1 || adaptation_field_control == 3) {
+ parsePID(br, PID, payload_unit_start_indicator);
+ }
+}
+
+sp<MediaSource> ATSParser::getSource(SourceType type) {
+ for (size_t i = 0; i < mPrograms.size(); ++i) {
+ sp<MediaSource> source = mPrograms.editItemAt(i)->getSource(type);
+
+ if (source != NULL) {
+ return source;
+ }
+ }
+
+ return NULL;
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
new file mode 100644
index 0000000..1e22e7b
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_TS_PARSER_H_
+
+#define A_TS_PARSER_H_
+
+#include <sys/types.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Vector.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABitReader;
+struct MediaSource;
+
+struct ATSParser : public RefBase {
+ ATSParser();
+
+ void feedTSPacket(const void *data, size_t size);
+
+ enum SourceType {
+ AVC_VIDEO,
+ MPEG2ADTS_AUDIO
+ };
+ sp<MediaSource> getSource(SourceType type);
+
+protected:
+ virtual ~ATSParser();
+
+private:
+ struct Program;
+ struct Stream;
+
+ Vector<sp<Program> > mPrograms;
+
+ void parseProgramAssociationTable(ABitReader *br);
+ void parseProgramMap(ABitReader *br);
+ void parsePES(ABitReader *br);
+
+ void parsePID(
+ ABitReader *br, unsigned PID,
+ unsigned payload_unit_start_indicator);
+
+ void parseAdaptationField(ABitReader *br);
+ void parseTS(ABitReader *br);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ATSParser);
+};
+
+} // namespace android
+
+#endif // A_TS_PARSER_H_
diff --git a/media/libstagefright/mpeg2ts/Android.mk b/media/libstagefright/mpeg2ts/Android.mk
new file mode 100644
index 0000000..b6772eb
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ ABitReader.cpp \
+ AnotherPacketSource.cpp \
+ ATSParser.cpp \
+ MPEG2TSExtractor.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/frameworks/base/media/libstagefright
+
+LOCAL_MODULE:= libstagefright_mpeg2ts
+
+ifeq ($(TARGET_ARCH),arm)
+ LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
new file mode 100644
index 0000000..3d51177
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AnotherPacketSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
+ : mFormat(meta),
+ mEOSResult(OK) {
+}
+
+AnotherPacketSource::~AnotherPacketSource() {
+}
+
+status_t AnotherPacketSource::start(MetaData *params) {
+ return OK;
+}
+
+status_t AnotherPacketSource::stop() {
+ return OK;
+}
+
+sp<MetaData> AnotherPacketSource::getFormat() {
+ return mFormat;
+}
+
+status_t AnotherPacketSource::read(
+ MediaBuffer **out, const ReadOptions *) {
+ *out = NULL;
+
+ Mutex::Autolock autoLock(mLock);
+ while (mEOSResult == OK && mBuffers.empty()) {
+ mCondition.wait(mLock);
+ }
+
+ if (!mBuffers.empty()) {
+ const sp<ABuffer> buffer = *mBuffers.begin();
+
+ uint64_t timeUs;
+ CHECK(buffer->meta()->findInt64(
+ "time", (int64_t *)&timeUs));
+
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
+ mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+ // hexdump(buffer->data(), buffer->size());
+
+ memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
+ *out = mediaBuffer;
+
+ mBuffers.erase(mBuffers.begin());
+ return OK;
+ }
+
+ return mEOSResult;
+}
+
+void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
+ int32_t damaged;
+ if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
+ // LOG(VERBOSE) << "discarding damaged AU";
+ return;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+ mBuffers.push_back(buffer);
+ mCondition.signal();
+}
+
+void AnotherPacketSource::signalEOS(status_t result) {
+ CHECK(result != OK);
+
+ Mutex::Autolock autoLock(mLock);
+ mEOSResult = result;
+ mCondition.signal();
+}
+
+bool AnotherPacketSource::hasBufferAvailable(status_t *finalResult) {
+ Mutex::Autolock autoLock(mLock);
+ if (!mBuffers.empty()) {
+ return true;
+ }
+
+ *finalResult = mEOSResult;
+ return false;
+}
+
+} // namespace android
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
new file mode 100644
index 0000000..ce83d21
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANOTHER_PACKET_SOURCE_H_
+
+#define ANOTHER_PACKET_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct AnotherPacketSource : public MediaSource {
+ AnotherPacketSource(const sp<MetaData> &meta);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+ bool hasBufferAvailable(status_t *finalResult);
+
+ void queueAccessUnit(const sp<ABuffer> &buffer);
+ void signalEOS(status_t result);
+
+protected:
+ virtual ~AnotherPacketSource();
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ sp<MetaData> mFormat;
+ List<sp<ABuffer> > mBuffers;
+ status_t mEOSResult;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AnotherPacketSource);
+};
+
+
+} // namespace android
+
+#endif // ANOTHER_PACKET_SOURCE_H_
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
new file mode 100644
index 0000000..b287c95
--- /dev/null
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MPEG2TSExtractor"
+#include <utils/Log.h>
+
+#include "include/MPEG2TSExtractor.h"
+
+#include <media/stagefright/DataSource.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/String8.h>
+
+#include "AnotherPacketSource.h"
+#include "ATSParser.h"
+
+namespace android {
+
+struct MPEG2TSSource : public MediaSource {
+ MPEG2TSSource(
+ const sp<MPEG2TSExtractor> &extractor,
+ const sp<AnotherPacketSource> &impl);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+private:
+ sp<MPEG2TSExtractor> mExtractor;
+ sp<AnotherPacketSource> mImpl;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSSource);
+};
+
+MPEG2TSSource::MPEG2TSSource(
+ const sp<MPEG2TSExtractor> &extractor,
+ const sp<AnotherPacketSource> &impl)
+ : mExtractor(extractor),
+ mImpl(impl) {
+}
+
+status_t MPEG2TSSource::start(MetaData *params) {
+ return mImpl->start(params);
+}
+
+status_t MPEG2TSSource::stop() {
+ return mImpl->stop();
+}
+
+sp<MetaData> MPEG2TSSource::getFormat() {
+ return mImpl->getFormat();
+}
+
+status_t MPEG2TSSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ status_t finalResult;
+ while (!mImpl->hasBufferAvailable(&finalResult)) {
+ if (finalResult != OK) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ status_t err = mExtractor->feedMore();
+ if (err != OK) {
+ mImpl->signalEOS(err);
+ }
+ }
+
+ return mImpl->read(out, options);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2TSExtractor::MPEG2TSExtractor(const sp<DataSource> &source)
+ : mDataSource(source),
+ mParser(new ATSParser),
+ mOffset(0) {
+ init();
+}
+
+size_t MPEG2TSExtractor::countTracks() {
+ return mSourceImpls.size();
+}
+
+sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
+ if (index >= mSourceImpls.size()) {
+ return NULL;
+ }
+
+ return new MPEG2TSSource(this, mSourceImpls.editItemAt(index));
+}
+
+sp<MetaData> MPEG2TSExtractor::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ return index < mSourceImpls.size()
+ ? mSourceImpls.editItemAt(index)->getFormat() : NULL;
+}
+
+sp<MetaData> MPEG2TSExtractor::getMetaData() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+ return meta;
+}
+
+void MPEG2TSExtractor::init() {
+ bool haveAudio = false;
+ bool haveVideo = false;
+
+ while (feedMore() == OK) {
+ ATSParser::SourceType type;
+ if (haveAudio && haveVideo) {
+ break;
+ }
+ if (haveVideo) {
+ type = ATSParser::MPEG2ADTS_AUDIO;
+ } else {
+ type = ATSParser::AVC_VIDEO;
+ }
+ sp<AnotherPacketSource> impl =
+ (AnotherPacketSource *)mParser->getSource(type).get();
+
+ if (impl != NULL) {
+ if (type == ATSParser::MPEG2ADTS_AUDIO) {
+ haveAudio = true;
+ } else {
+ haveVideo = true;
+ }
+ mSourceImpls.push(impl);
+ }
+ }
+
+ LOGI("haveAudio=%d, haveVideo=%d", haveAudio, haveVideo);
+}
+
+status_t MPEG2TSExtractor::feedMore() {
+ Mutex::Autolock autoLock(mLock);
+
+ static const size_t kTSPacketSize = 188;
+
+ uint8_t packet[kTSPacketSize];
+ ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
+
+ if (n < (ssize_t)kTSPacketSize) {
+ return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
+ }
+
+ mOffset += kTSPacketSize;
+ mParser->feedTSPacket(packet, kTSPacketSize);
+
+ return OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+bool SniffMPEG2TS(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+#if 0
+ char header;
+ if (source->readAt(0, &header, 1) != 1 || header != 0x47) {
+ return false;
+ }
+
+ *confidence = 0.05f;
+ mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
+
+ return true;
+#else
+ // For now we're going to never identify this type of stream, since we'd
+ // just base our decision on a single byte...
+ // Instead you can instantiate an MPEG2TSExtractor by explicitly stating
+ // its proper mime type in the call to MediaExtractor::Create(...).
+ return false;
+#endif
+}
+
+} // namespace android
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 132e31b..6de761f 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -43,7 +43,7 @@ namespace android {
////////////////////////////////////////////////////////////////////////////////
struct OMX::CallbackDispatcher : public RefBase {
- CallbackDispatcher(OMX *owner);
+ CallbackDispatcher(OMXNodeInstance *owner);
void post(const omx_message &msg);
@@ -53,7 +53,7 @@ protected:
private:
Mutex mLock;
- OMX *mOwner;
+ OMXNodeInstance *mOwner;
bool mDone;
Condition mQueueChanged;
List<omx_message> mQueue;
@@ -69,7 +69,7 @@ private:
CallbackDispatcher &operator=(const CallbackDispatcher &);
};
-OMX::CallbackDispatcher::CallbackDispatcher(OMX *owner)
+OMX::CallbackDispatcher::CallbackDispatcher(OMXNodeInstance *owner)
: mOwner(owner),
mDone(false) {
pthread_attr_t attr;
@@ -101,12 +101,11 @@ void OMX::CallbackDispatcher::post(const omx_message &msg) {
}
void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
- OMXNodeInstance *instance = mOwner->findInstance(msg.node);
- if (instance == NULL) {
+ if (mOwner == NULL) {
LOGV("Would have dispatched a message to a node that's already gone.");
return;
}
- instance->onMessage(msg);
+ mOwner->onMessage(msg);
}
// static
@@ -145,7 +144,6 @@ void OMX::CallbackDispatcher::threadEntry() {
OMX::OMX()
: mMaster(new OMXMaster),
- mDispatcher(new CallbackDispatcher(this)),
mNodeCounter(0) {
}
@@ -166,6 +164,10 @@ void OMX::binderDied(const wp<IBinder> &the_late_who) {
instance = mLiveNodes.editValueAt(index);
mLiveNodes.removeItemsAt(index);
+ index = mDispatchers.indexOfKey(instance->nodeID());
+ CHECK(index >= 0);
+ mDispatchers.removeItemsAt(index);
+
invalidateNodeID_l(instance->nodeID());
}
@@ -226,6 +228,7 @@ status_t OMX::allocateNode(
}
*node = makeNodeID(instance);
+ mDispatchers.add(*node, new CallbackDispatcher(instance));
instance->setHandle(*node, handle);
@@ -241,6 +244,11 @@ status_t OMX::freeNode(node_id node) {
ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
CHECK(index >= 0);
mLiveNodes.removeItemsAt(index);
+
+ index = mDispatchers.indexOfKey(node);
+ CHECK(index >= 0);
+ mDispatchers.removeItemsAt(index);
+
instance->observer()->asBinder()->unlinkToDeath(this);
return instance->freeNode(mMaster);
@@ -341,7 +349,7 @@ OMX_ERRORTYPE OMX::OnEvent(
msg.u.event_data.data1 = nData1;
msg.u.event_data.data2 = nData2;
- mDispatcher->post(msg);
+ findDispatcher(node)->post(msg);
return OMX_ErrorNone;
}
@@ -355,7 +363,7 @@ OMX_ERRORTYPE OMX::OnEmptyBufferDone(
msg.node = node;
msg.u.buffer_data.buffer = pBuffer;
- mDispatcher->post(msg);
+ findDispatcher(node)->post(msg);
return OMX_ErrorNone;
}
@@ -375,7 +383,7 @@ OMX_ERRORTYPE OMX::OnFillBufferDone(
msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
- mDispatcher->post(msg);
+ findDispatcher(node)->post(msg);
return OMX_ErrorNone;
}
@@ -397,6 +405,14 @@ OMXNodeInstance *OMX::findInstance(node_id node) {
return index < 0 ? NULL : mNodeIDToInstance.valueAt(index);
}
+sp<OMX::CallbackDispatcher> OMX::findDispatcher(node_id node) {
+ Mutex::Autolock autoLock(mLock);
+
+ ssize_t index = mDispatchers.indexOfKey(node);
+
+ return index < 0 ? NULL : mDispatchers.valueAt(index);
+}
+
void OMX::invalidateNodeID(node_id node) {
Mutex::Autolock autoLock(mLock);
invalidateNodeID_l(node);
diff --git a/media/libstagefright/omx/OMXMaster.cpp b/media/libstagefright/omx/OMXMaster.cpp
index 9a45bea..56b169a 100644
--- a/media/libstagefright/omx/OMXMaster.cpp
+++ b/media/libstagefright/omx/OMXMaster.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXMaster"
+#include <utils/Log.h>
+
#include "OMXMaster.h"
#include <dlfcn.h>
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index c1a010c..5db516e 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -264,6 +264,8 @@ status_t OMXNodeInstance::useBuffer(
return UNKNOWN_ERROR;
}
+ CHECK_EQ(header->pAppPrivate, buffer_meta);
+
*buffer = header;
addActiveBuffer(portIndex, *buffer);
@@ -294,6 +296,8 @@ status_t OMXNodeInstance::allocateBuffer(
return UNKNOWN_ERROR;
}
+ CHECK_EQ(header->pAppPrivate, buffer_meta);
+
*buffer = header;
*buffer_data = header->pBuffer;
@@ -325,6 +329,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup(
return UNKNOWN_ERROR;
}
+ CHECK_EQ(header->pAppPrivate, buffer_meta);
+
*buffer = header;
addActiveBuffer(portIndex, *buffer);
diff --git a/media/libstagefright/omx/tests/Android.mk b/media/libstagefright/omx/tests/Android.mk
index ee117e5..8bf4336 100644
--- a/media/libstagefright/omx/tests/Android.mk
+++ b/media/libstagefright/omx/tests/Android.mk
@@ -1,5 +1,3 @@
-ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
-
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
@@ -17,7 +15,3 @@ LOCAL_C_INCLUDES:= \
LOCAL_MODULE:= omx_tests
include $(BUILD_EXECUTABLE)
-
-endif
-
-
diff --git a/media/libstagefright/rtsp/AAVCAssembler.cpp b/media/libstagefright/rtsp/AAVCAssembler.cpp
new file mode 100644
index 0000000..3dfb200
--- /dev/null
+++ b/media/libstagefright/rtsp/AAVCAssembler.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AAVCAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#include <stdint.h>
+
+#define BE_VERBOSE 0
+
+namespace android {
+
+// static
+AAVCAssembler::AAVCAssembler(const sp<AMessage> &notify)
+ : mNotifyMsg(notify),
+ mAccessUnitRTPTime(0),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0),
+ mAccessUnitDamaged(false) {
+}
+
+AAVCAssembler::~AAVCAssembler() {
+}
+
+ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
+ const sp<ARTPSource> &source) {
+ List<sp<ABuffer> > *queue = source->queue();
+
+ if (queue->empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+
+ if (mNextExpectedSeqNoValid) {
+ List<sp<ABuffer> >::iterator it = queue->begin();
+ while (it != queue->end()) {
+ if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
+ break;
+ }
+
+ it = queue->erase(it);
+ }
+
+ if (queue->empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+ }
+
+ sp<ABuffer> buffer = *queue->begin();
+
+ if (!mNextExpectedSeqNoValid) {
+ mNextExpectedSeqNoValid = true;
+ mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
+ } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
+#if BE_VERBOSE
+ LOG(VERBOSE) << "Not the sequence number I expected";
+#endif
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if (size < 1 || (data[0] & 0x80)) {
+ // Corrupt.
+
+ LOG(ERROR) << "Ignoring corrupt buffer.";
+ queue->erase(queue->begin());
+
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ unsigned nalType = data[0] & 0x1f;
+ if (nalType >= 1 && nalType <= 23) {
+ addSingleNALUnit(buffer);
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return OK;
+ } else if (nalType == 28) {
+ // FU-A
+ return addFragmentedNALUnit(queue);
+ } else if (nalType == 24) {
+ // STAP-A
+ bool success = addSingleTimeAggregationPacket(buffer);
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return success ? OK : MALFORMED_PACKET;
+ } else {
+ LOG(ERROR) << "Ignoring unsupported buffer (nalType=" << nalType << ")";
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return MALFORMED_PACKET;
+ }
+}
+
+void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
+#if BE_VERBOSE
+ LOG(VERBOSE) << "addSingleNALUnit of size " << buffer->size();
+ hexdump(buffer->data(), buffer->size());
+#endif
+
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
+ submitAccessUnit();
+ }
+ mAccessUnitRTPTime = rtpTime;
+
+ mNALUnits.push_back(buffer);
+}
+
+bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if (size < 3) {
+ LOG(ERROR) << "Discarding too small STAP-A packet.";
+ return false;
+ }
+
+ ++data;
+ --size;
+ while (size >= 2) {
+ size_t nalSize = (data[0] << 8) | data[1];
+
+ if (size < nalSize + 2) {
+ LOG(ERROR) << "Discarding malformed STAP-A packet.";
+ return false;
+ }
+
+ sp<ABuffer> unit = new ABuffer(nalSize);
+ memcpy(unit->data(), &data[2], nalSize);
+
+ PropagateTimes(buffer, unit);
+
+ addSingleNALUnit(unit);
+
+ data += 2 + nalSize;
+ size -= 2 + nalSize;
+ }
+
+ if (size != 0) {
+ LOG(WARNING) << "Unexpected padding at end of STAP-A packet.";
+ }
+
+ return true;
+}
+
+ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
+ List<sp<ABuffer> > *queue) {
+ CHECK(!queue->empty());
+
+ sp<ABuffer> buffer = *queue->begin();
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ CHECK(size > 0);
+ unsigned indicator = data[0];
+
+ CHECK((indicator & 0x1f) == 28);
+
+ if (size < 2) {
+ LOG(ERROR) << "Ignoring malformed FU buffer (size = " << size << ")";
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ if (!(data[1] & 0x80)) {
+ // Start bit not set on the first buffer.
+
+#if BE_VERBOSE
+ LOG(ERROR) << "Start bit not set on first buffer";
+#endif
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+ return MALFORMED_PACKET;
+ }
+
+ uint32_t nalType = data[1] & 0x1f;
+ uint32_t nri = (data[0] >> 5) & 3;
+
+ uint32_t expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
+ size_t totalSize = size - 2;
+ size_t totalCount = 1;
+ bool complete = false;
+
+ if (data[1] & 0x40) {
+ // Huh? End bit also set on the first buffer.
+
+#if BE_VERBOSE
+ LOG(WARNING) << "Grrr. This isn't fragmented at all.";
+#endif
+
+ complete = true;
+ } else {
+ List<sp<ABuffer> >::iterator it = ++queue->begin();
+ while (it != queue->end()) {
+#if BE_VERBOSE
+ LOG(VERBOSE) << "sequence length " << totalCount;
+#endif
+
+ const sp<ABuffer> &buffer = *it;
+
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
+#if BE_VERBOSE
+ LOG(VERBOSE) << "sequence not complete, expected seqNo "
+ << expectedSeqNo << ", got "
+ << (uint32_t)buffer->int32Data();
+#endif
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ if (size < 2
+ || data[0] != indicator
+ || (data[1] & 0x1f) != nalType
+ || (data[1] & 0x80)) {
+ LOG(ERROR) << "Ignoring malformed FU buffer.\n";
+
+ // Delete the whole start of the FU.
+
+ it = queue->begin();
+ for (size_t i = 0; i <= totalCount; ++i) {
+ it = queue->erase(it);
+ }
+
+ mNextExpectedSeqNo = expectedSeqNo + 1;
+
+ return MALFORMED_PACKET;
+ }
+
+ totalSize += size - 2;
+ ++totalCount;
+
+ expectedSeqNo = expectedSeqNo + 1;
+
+ if (data[1] & 0x40) {
+ // This is the last fragment.
+ complete = true;
+ break;
+ }
+
+ ++it;
+ }
+ }
+
+ if (!complete) {
+ return NOT_ENOUGH_DATA;
+ }
+
+ mNextExpectedSeqNo = expectedSeqNo;
+
+ // We found all the fragments that make up the complete NAL unit.
+
+ // Leave room for the header. So far totalSize did not include the
+ // header byte.
+ ++totalSize;
+
+ sp<ABuffer> unit = new ABuffer(totalSize);
+ PropagateTimes(buffer, unit);
+
+ unit->data()[0] = (nri << 5) | nalType;
+
+ size_t offset = 1;
+ List<sp<ABuffer> >::iterator it = queue->begin();
+ for (size_t i = 0; i < totalCount; ++i) {
+ const sp<ABuffer> &buffer = *it;
+
+#if BE_VERBOSE
+ LOG(VERBOSE) << "piece #" << (i + 1) << "/" << totalCount;
+ hexdump(buffer->data(), buffer->size());
+#endif
+
+ memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
+ offset += buffer->size() - 2;
+
+ it = queue->erase(it);
+ }
+
+ unit->setRange(0, totalSize);
+
+ addSingleNALUnit(unit);
+
+#if BE_VERBOSE
+ LOG(VERBOSE) << "successfully assembled a NAL unit from fragments.";
+#endif
+
+ return OK;
+}
+
+void AAVCAssembler::submitAccessUnit() {
+ CHECK(!mNALUnits.empty());
+
+#if BE_VERBOSE
+ LOG(VERBOSE) << "Access unit complete (" << mNALUnits.size() << " nal units)";
+#endif
+
+ uint64_t ntpTime;
+ CHECK((*mNALUnits.begin())->meta()->findInt64(
+ "ntp-time", (int64_t *)&ntpTime));
+
+ size_t totalSize = 0;
+ for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
+ it != mNALUnits.end(); ++it) {
+ totalSize += 4 + (*it)->size();
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ size_t offset = 0;
+ for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
+ it != mNALUnits.end(); ++it) {
+ memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
+ offset += 4;
+
+ sp<ABuffer> nal = *it;
+ memcpy(accessUnit->data() + offset, nal->data(), nal->size());
+ offset += nal->size();
+ }
+
+ accessUnit->meta()->setInt64("ntp-time", ntpTime);
+
+#if 0
+ printf(mAccessUnitDamaged ? "X" : ".");
+ fflush(stdout);
+#endif
+
+ if (mAccessUnitDamaged) {
+ accessUnit->meta()->setInt32("damaged", true);
+ }
+
+ mNALUnits.clear();
+ mAccessUnitDamaged = false;
+
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setObject("access-unit", accessUnit);
+ msg->post();
+}
+
+ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ AssemblyStatus status = addNALUnit(source);
+ if (status == MALFORMED_PACKET) {
+ mAccessUnitDamaged = true;
+ }
+ return status;
+}
+
+void AAVCAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ++mNextExpectedSeqNo;
+
+ mAccessUnitDamaged = true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AAVCAssembler.h b/media/libstagefright/rtsp/AAVCAssembler.h
new file mode 100644
index 0000000..1e97520
--- /dev/null
+++ b/media/libstagefright/rtsp/AAVCAssembler.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_AVC_ASSEMBLER_H_
+
+#define A_AVC_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+
+struct AAVCAssembler : public ARTPAssembler {
+ AAVCAssembler(const sp<AMessage> &notify);
+
+protected:
+ virtual ~AAVCAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void packetLost();
+
+private:
+ sp<AMessage> mNotifyMsg;
+
+ uint32_t mAccessUnitRTPTime;
+ bool mNextExpectedSeqNoValid;
+ uint32_t mNextExpectedSeqNo;
+ bool mAccessUnitDamaged;
+ List<sp<ABuffer> > mNALUnits;
+
+ AssemblyStatus addNALUnit(const sp<ARTPSource> &source);
+ void addSingleNALUnit(const sp<ABuffer> &buffer);
+ AssemblyStatus addFragmentedNALUnit(List<sp<ABuffer> > *queue);
+ bool addSingleTimeAggregationPacket(const sp<ABuffer> &buffer);
+
+ void submitAccessUnit();
+
+ DISALLOW_EVIL_CONSTRUCTORS(AAVCAssembler);
+};
+
+} // namespace android
+
+#endif // A_AVC_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
new file mode 100644
index 0000000..7e55106
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AMPEG4AudioAssembler.h"
+
+#include "ARTPSource.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+AMPEG4AudioAssembler::AMPEG4AudioAssembler(const sp<AMessage> &notify)
+ : mNotifyMsg(notify),
+ mAccessUnitRTPTime(0),
+ mNextExpectedSeqNoValid(false),
+ mNextExpectedSeqNo(0),
+ mAccessUnitDamaged(false) {
+}
+
+AMPEG4AudioAssembler::~AMPEG4AudioAssembler() {
+}
+
+ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::assembleMore(
+ const sp<ARTPSource> &source) {
+ AssemblyStatus status = addPacket(source);
+ if (status == MALFORMED_PACKET) {
+ mAccessUnitDamaged = true;
+ }
+ return status;
+}
+
+ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket(
+ const sp<ARTPSource> &source) {
+ List<sp<ABuffer> > *queue = source->queue();
+
+ if (queue->empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+
+ if (mNextExpectedSeqNoValid) {
+ List<sp<ABuffer> >::iterator it = queue->begin();
+ while (it != queue->end()) {
+ if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
+ break;
+ }
+
+ it = queue->erase(it);
+ }
+
+ if (queue->empty()) {
+ return NOT_ENOUGH_DATA;
+ }
+ }
+
+ sp<ABuffer> buffer = *queue->begin();
+
+ if (!mNextExpectedSeqNoValid) {
+ mNextExpectedSeqNoValid = true;
+ mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
+ } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
+#if VERBOSE
+ LOG(VERBOSE) << "Not the sequence number I expected";
+#endif
+
+ return WRONG_SEQUENCE_NUMBER;
+ }
+
+ uint32_t rtpTime;
+ CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
+ submitAccessUnit();
+ }
+ mAccessUnitRTPTime = rtpTime;
+
+ mPackets.push_back(buffer);
+
+ queue->erase(queue->begin());
+ ++mNextExpectedSeqNo;
+
+ return OK;
+}
+
+void AMPEG4AudioAssembler::submitAccessUnit() {
+ CHECK(!mPackets.empty());
+
+#if VERBOSE
+ LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
+#endif
+
+ uint64_t ntpTime;
+ CHECK((*mPackets.begin())->meta()->findInt64(
+ "ntp-time", (int64_t *)&ntpTime));
+
+ size_t totalSize = 0;
+ List<sp<ABuffer> >::iterator it = mPackets.begin();
+ while (it != mPackets.end()) {
+ const sp<ABuffer> &unit = *it;
+
+ size_t n = 0;
+ while (unit->data()[n] == 0xff) {
+ ++n;
+ }
+ ++n;
+
+ totalSize += unit->size() - n;
+ ++it;
+ }
+
+ sp<ABuffer> accessUnit = new ABuffer(totalSize);
+ size_t offset = 0;
+ it = mPackets.begin();
+ while (it != mPackets.end()) {
+ const sp<ABuffer> &unit = *it;
+
+ size_t n = 0;
+ while (unit->data()[n] == 0xff) {
+ ++n;
+ }
+ ++n;
+
+ memcpy((uint8_t *)accessUnit->data() + offset,
+ unit->data() + n, unit->size() - n);
+
+ offset += unit->size() - n;
+
+ ++it;
+ }
+
+ accessUnit->meta()->setInt64("ntp-time", ntpTime);
+
+#if 0
+ printf(mAccessUnitDamaged ? "X" : ".");
+ fflush(stdout);
+#endif
+
+ if (mAccessUnitDamaged) {
+ accessUnit->meta()->setInt32("damaged", true);
+ }
+
+ mPackets.clear();
+ mAccessUnitDamaged = false;
+
+ sp<AMessage> msg = mNotifyMsg->dup();
+ msg->setObject("access-unit", accessUnit);
+ msg->post();
+}
+
+void AMPEG4AudioAssembler::packetLost() {
+ CHECK(mNextExpectedSeqNoValid);
+ ++mNextExpectedSeqNo;
+
+ mAccessUnitDamaged = true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
new file mode 100644
index 0000000..5c2a2dd
--- /dev/null
+++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_MPEG4_AUDIO_ASSEMBLER_H_
+
+#define A_MPEG4_AUDIO_ASSEMBLER_H_
+
+#include "ARTPAssembler.h"
+
+#include <utils/List.h>
+
+#include <stdint.h>
+
+namespace android {
+
+struct AMessage;
+
+struct AMPEG4AudioAssembler : public ARTPAssembler {
+ AMPEG4AudioAssembler(const sp<AMessage> &notify);
+
+protected:
+ virtual ~AMPEG4AudioAssembler();
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source);
+ virtual void packetLost();
+
+private:
+ sp<AMessage> mNotifyMsg;
+ uint32_t mAccessUnitRTPTime;
+ bool mNextExpectedSeqNoValid;
+ uint32_t mNextExpectedSeqNo;
+ bool mAccessUnitDamaged;
+ List<sp<ABuffer> > mPackets;
+
+ AssemblyStatus addPacket(const sp<ARTPSource> &source);
+ void submitAccessUnit();
+
+ DISALLOW_EVIL_CONSTRUCTORS(AMPEG4AudioAssembler);
+};
+
+} // namespace android
+
+#endif // A_MPEG4_AUDIO_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
new file mode 100644
index 0000000..2869d54
--- /dev/null
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "APacketSource.h"
+
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+ value->clear();
+
+ size_t keyLen = strlen(key);
+
+ for (;;) {
+ const char *colonPos = strchr(s, ';');
+
+ size_t len =
+ (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+ if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
+ value->setTo(&s[keyLen + 1], len - keyLen - 1);
+ return true;
+ }
+
+ if (colonPos == NULL) {
+ return false;
+ }
+
+ s = colonPos + 1;
+ }
+}
+
+static sp<ABuffer> decodeHex(const AString &s) {
+ if ((s.size() % 2) != 0) {
+ return NULL;
+ }
+
+ size_t outLen = s.size() / 2;
+ sp<ABuffer> buffer = new ABuffer(outLen);
+ uint8_t *out = buffer->data();
+
+ uint8_t accum = 0;
+ for (size_t i = 0; i < s.size(); ++i) {
+ char c = s.c_str()[i];
+ unsigned value;
+ if (c >= '0' && c <= '9') {
+ value = c - '0';
+ } else if (c >= 'a' && c <= 'f') {
+ value = c - 'a' + 10;
+ } else if (c >= 'A' && c <= 'F') {
+ value = c - 'A' + 10;
+ } else {
+ return NULL;
+ }
+
+ accum = (accum << 4) | value;
+
+ if (i & 1) {
+ *out++ = accum;
+
+ accum = 0;
+ }
+ }
+
+ return buffer;
+}
+
+static sp<ABuffer> MakeAVCCodecSpecificData(const char *params) {
+ AString val;
+ CHECK(GetAttribute(params, "profile-level-id", &val));
+
+ sp<ABuffer> profileLevelID = decodeHex(val);
+ CHECK(profileLevelID != NULL);
+ CHECK_EQ(profileLevelID->size(), 3u);
+
+ Vector<sp<ABuffer> > paramSets;
+
+ size_t numSeqParameterSets = 0;
+ size_t totalSeqParameterSetSize = 0;
+ size_t numPicParameterSets = 0;
+ size_t totalPicParameterSetSize = 0;
+
+ CHECK(GetAttribute(params, "sprop-parameter-sets", &val));
+ size_t start = 0;
+ for (;;) {
+ ssize_t commaPos = val.find(",", start);
+ size_t end = (commaPos < 0) ? val.size() : commaPos;
+
+ AString nalString(val, start, end - start);
+ sp<ABuffer> nal = decodeBase64(nalString);
+ CHECK(nal != NULL);
+ CHECK_GT(nal->size(), 0u);
+ CHECK_LE(nal->size(), 65535u);
+
+ uint8_t nalType = nal->data()[0] & 0x1f;
+ if (numSeqParameterSets == 0) {
+ CHECK_EQ((unsigned)nalType, 7u);
+ } else if (numPicParameterSets > 0) {
+ CHECK_EQ((unsigned)nalType, 8u);
+ }
+ if (nalType == 7) {
+ ++numSeqParameterSets;
+ totalSeqParameterSetSize += nal->size();
+ } else {
+ CHECK_EQ((unsigned)nalType, 8u);
+ ++numPicParameterSets;
+ totalPicParameterSetSize += nal->size();
+ }
+
+ paramSets.push(nal);
+
+ if (commaPos < 0) {
+ break;
+ }
+
+ start = commaPos + 1;
+ }
+
+ CHECK_LT(numSeqParameterSets, 32u);
+ CHECK_LE(numPicParameterSets, 255u);
+
+ size_t csdSize =
+ 1 + 3 + 1 + 1
+ + 2 * numSeqParameterSets + totalSeqParameterSetSize
+ + 1 + 2 * numPicParameterSets + totalPicParameterSetSize;
+
+ sp<ABuffer> csd = new ABuffer(csdSize);
+ uint8_t *out = csd->data();
+
+ *out++ = 0x01; // configurationVersion
+ memcpy(out, profileLevelID->data(), 3);
+ out += 3;
+ *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes
+ *out++ = 0xe0 | numSeqParameterSets;
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ sp<ABuffer> nal = paramSets.editItemAt(i);
+
+ *out++ = nal->size() >> 8;
+ *out++ = nal->size() & 0xff;
+
+ memcpy(out, nal->data(), nal->size());
+
+ out += nal->size();
+ }
+
+ *out++ = numPicParameterSets;
+
+ for (size_t i = 0; i < numPicParameterSets; ++i) {
+ sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets);
+
+ *out++ = nal->size() >> 8;
+ *out++ = nal->size() & 0xff;
+
+ memcpy(out, nal->data(), nal->size());
+
+ out += nal->size();
+ }
+
+ hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
+sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
+ AString val;
+ CHECK(GetAttribute(params, "config", &val));
+
+ sp<ABuffer> config = decodeHex(val);
+ CHECK(config != NULL);
+ CHECK_GE(config->size(), 4u);
+
+ const uint8_t *data = config->data();
+ uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ x = (x >> 1) & 0xffff;
+
+ static const uint8_t kStaticESDS[] = {
+ 0x03, 22,
+ 0x00, 0x00, // ES_ID
+ 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
+
+ 0x04, 17,
+ 0x40, // Audio ISO/IEC 14496-3
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+
+ 0x05, 2,
+ // AudioSpecificInfo follows
+ };
+
+ sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
+ memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
+ csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
+ csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
+
+ hexdump(csd->data(), csd->size());
+
+ return csd;
+}
+
+APacketSource::APacketSource(
+ const sp<ASessionDescription> &sessionDesc, size_t index)
+ : mFormat(new MetaData),
+ mEOSResult(OK) {
+ unsigned long PT;
+ AString desc;
+ AString params;
+ sessionDesc->getFormatType(index, &PT, &desc, &params);
+
+ int64_t durationUs;
+ if (sessionDesc->getDurationUs(&durationUs)) {
+ mFormat->setInt64(kKeyDuration, durationUs);
+ } else {
+ mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
+ }
+
+ if (!strncmp(desc.c_str(), "H264/", 5)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+
+ int32_t width, height;
+ sessionDesc->getDimensions(index, PT, &width, &height);
+
+ mFormat->setInt32(kKeyWidth, width);
+ mFormat->setInt32(kKeyHeight, height);
+
+ sp<ABuffer> codecSpecificData =
+ MakeAVCCodecSpecificData(params.c_str());
+
+ mFormat->setData(
+ kKeyAVCC, 0,
+ codecSpecificData->data(), codecSpecificData->size());
+
+ } else if (!strncmp(desc.c_str(), "MP4A-LATM", 9)) {
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+
+ int32_t sampleRate, numChannels;
+ ASessionDescription::ParseFormatDesc(
+ desc.c_str(), &sampleRate, &numChannels);
+
+ mFormat->setInt32(kKeySampleRate, sampleRate);
+ mFormat->setInt32(kKeyChannelCount, numChannels);
+
+ sp<ABuffer> codecSpecificData =
+ MakeAACCodecSpecificData(params.c_str());
+
+ mFormat->setData(
+ kKeyESDS, 0,
+ codecSpecificData->data(), codecSpecificData->size());
+ } else {
+ TRESPASS();
+ }
+}
+
+APacketSource::~APacketSource() {
+}
+
+status_t APacketSource::start(MetaData *params) {
+ return OK;
+}
+
+status_t APacketSource::stop() {
+ return OK;
+}
+
+sp<MetaData> APacketSource::getFormat() {
+ return mFormat;
+}
+
+status_t APacketSource::read(
+ MediaBuffer **out, const ReadOptions *) {
+ *out = NULL;
+
+ Mutex::Autolock autoLock(mLock);
+ while (mEOSResult == OK && mBuffers.empty()) {
+ mCondition.wait(mLock);
+ }
+
+ if (!mBuffers.empty()) {
+ const sp<ABuffer> buffer = *mBuffers.begin();
+
+ uint64_t ntpTime;
+ CHECK(buffer->meta()->findInt64(
+ "ntp-time", (int64_t *)&ntpTime));
+
+ int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
+
+ MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
+ mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+ memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
+ *out = mediaBuffer;
+
+ mBuffers.erase(mBuffers.begin());
+ return OK;
+ }
+
+ return mEOSResult;
+}
+
+void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
+ int32_t damaged;
+ if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
+ // LOG(VERBOSE) << "discarding damaged AU";
+ return;
+ }
+
+ Mutex::Autolock autoLock(mLock);
+ mBuffers.push_back(buffer);
+ mCondition.signal();
+}
+
+void APacketSource::signalEOS(status_t result) {
+ CHECK(result != OK);
+
+ Mutex::Autolock autoLock(mLock);
+ mEOSResult = result;
+ mCondition.signal();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
new file mode 100644
index 0000000..4040eee
--- /dev/null
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_PACKET_SOURCE_H_
+
+#define A_PACKET_SOURCE_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+struct ASessionDescription;
+
+struct APacketSource : public MediaSource {
+ APacketSource(const sp<ASessionDescription> &sessionDesc, size_t index);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+ void queueAccessUnit(const sp<ABuffer> &buffer);
+ void signalEOS(status_t result);
+
+protected:
+ virtual ~APacketSource();
+
+private:
+ Mutex mLock;
+ Condition mCondition;
+
+ sp<MetaData> mFormat;
+ List<sp<ABuffer> > mBuffers;
+ status_t mEOSResult;
+
+ DISALLOW_EVIL_CONSTRUCTORS(APacketSource);
+};
+
+
+} // namespace android
+
+#endif // A_PACKET_SOURCE_H_
diff --git a/media/libstagefright/rtsp/ARTPAssembler.cpp b/media/libstagefright/rtsp/ARTPAssembler.cpp
new file mode 100644
index 0000000..24225b8
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPAssembler.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ARTPAssembler.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <stdint.h>
+
+namespace android {
+
+static int64_t getNowUs() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ return (int64_t)tv.tv_usec + tv.tv_sec * 1000000ll;
+}
+
+ARTPAssembler::ARTPAssembler()
+ : mFirstFailureTimeUs(-1) {
+}
+
+void ARTPAssembler::PropagateTimes(
+ const sp<ABuffer> &from, const sp<ABuffer> &to) {
+ uint32_t rtpTime;
+ CHECK(from->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ uint64_t ntpTime = 0;
+ CHECK(from->meta()->findInt64("ntp-time", (int64_t *)&ntpTime));
+
+ to->meta()->setInt32("rtp-time", rtpTime);
+ to->meta()->setInt64("ntp-time", ntpTime);
+}
+
+void ARTPAssembler::onPacketReceived(const sp<ARTPSource> &source) {
+ AssemblyStatus status;
+ for (;;) {
+ status = assembleMore(source);
+
+ if (status == WRONG_SEQUENCE_NUMBER) {
+ if (mFirstFailureTimeUs >= 0) {
+ if (getNowUs() - mFirstFailureTimeUs > 10000ll) {
+ mFirstFailureTimeUs = -1;
+
+ // LOG(VERBOSE) << "waited too long for packet.";
+ packetLost();
+ continue;
+ }
+ } else {
+ mFirstFailureTimeUs = getNowUs();
+ }
+ break;
+ } else {
+ mFirstFailureTimeUs = -1;
+
+ if (status == NOT_ENOUGH_DATA) {
+ break;
+ }
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ARTPAssembler.h b/media/libstagefright/rtsp/ARTPAssembler.h
new file mode 100644
index 0000000..892bd65
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPAssembler.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_RTP_ASSEMBLER_H_
+
+#define A_RTP_ASSEMBLER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct ARTPSource;
+
+struct ARTPAssembler : public RefBase {
+ enum AssemblyStatus {
+ MALFORMED_PACKET,
+ WRONG_SEQUENCE_NUMBER,
+ NOT_ENOUGH_DATA,
+ OK
+ };
+
+ ARTPAssembler();
+
+ void onPacketReceived(const sp<ARTPSource> &source);
+
+protected:
+ static void PropagateTimes(
+ const sp<ABuffer> &from, const sp<ABuffer> &to);
+
+ virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source) = 0;
+ virtual void packetLost() = 0;
+
+private:
+ int64_t mFirstFailureTimeUs;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPAssembler);
+};
+
+} // namespace android
+
+#endif // A_RTP_ASSEMBLER_H_
diff --git a/media/libstagefright/rtsp/ARTPConnection.cpp b/media/libstagefright/rtsp/ARTPConnection.cpp
new file mode 100644
index 0000000..a4413f0
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPConnection.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ARTPConnection.h"
+
+#include "ARTPSource.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#define VERBOSE 0
+
+#if VERBOSE
+#include "hexdump.h"
+#endif
+
+namespace android {
+
+static uint16_t u16at(const uint8_t *data) {
+ return data[0] << 8 | data[1];
+}
+
+static uint32_t u32at(const uint8_t *data) {
+ return u16at(data) << 16 | u16at(&data[2]);
+}
+
+static uint64_t u64at(const uint8_t *data) {
+ return (uint64_t)(u32at(data)) << 32 | u32at(&data[4]);
+}
+
+// static
+const int64_t ARTPConnection::kSelectTimeoutUs = 1000ll;
+
+struct ARTPConnection::StreamInfo {
+ int mRTPSocket;
+ int mRTCPSocket;
+ sp<ASessionDescription> mSessionDesc;
+ size_t mIndex;
+ sp<AMessage> mNotifyMsg;
+};
+
+ARTPConnection::ARTPConnection()
+ : mPollEventPending(false) {
+}
+
+ARTPConnection::~ARTPConnection() {
+}
+
+void ARTPConnection::addStream(
+ int rtpSocket, int rtcpSocket,
+ const sp<ASessionDescription> &sessionDesc,
+ size_t index,
+ const sp<AMessage> &notify) {
+ sp<AMessage> msg = new AMessage(kWhatAddStream, id());
+ msg->setInt32("rtp-socket", rtpSocket);
+ msg->setInt32("rtcp-socket", rtcpSocket);
+ msg->setObject("session-desc", sessionDesc);
+ msg->setSize("index", index);
+ msg->setMessage("notify", notify);
+ msg->post();
+}
+
+void ARTPConnection::removeStream(int rtpSocket, int rtcpSocket) {
+ sp<AMessage> msg = new AMessage(kWhatRemoveStream, id());
+ msg->setInt32("rtp-socket", rtpSocket);
+ msg->setInt32("rtcp-socket", rtcpSocket);
+ msg->post();
+}
+
+static void bumpSocketBufferSize(int s) {
+ int size = 256 * 1024;
+ CHECK_EQ(setsockopt(s, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)), 0);
+}
+
+// static
+void ARTPConnection::MakePortPair(
+ int *rtpSocket, int *rtcpSocket, unsigned *rtpPort) {
+ *rtpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(*rtpSocket, 0);
+
+ bumpSocketBufferSize(*rtpSocket);
+
+ *rtcpSocket = socket(AF_INET, SOCK_DGRAM, 0);
+ CHECK_GE(*rtcpSocket, 0);
+
+ bumpSocketBufferSize(*rtcpSocket);
+
+ unsigned start = (rand() * 1000)/ RAND_MAX + 15550;
+ start &= ~1;
+
+ for (unsigned port = start; port < 65536; port += 2) {
+ struct sockaddr_in addr;
+ memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_port = htons(port);
+
+ if (bind(*rtpSocket,
+ (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ continue;
+ }
+
+ addr.sin_port = htons(port + 1);
+
+ if (bind(*rtcpSocket,
+ (const struct sockaddr *)&addr, sizeof(addr)) == 0) {
+ *rtpPort = port;
+ return;
+ }
+ }
+
+ TRESPASS();
+}
+
+void ARTPConnection::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatAddStream:
+ {
+ onAddStream(msg);
+ break;
+ }
+
+ case kWhatRemoveStream:
+ {
+ onRemoveStream(msg);
+ break;
+ }
+
+ case kWhatPollStreams:
+ {
+ onPollStreams();
+ break;
+ }
+
+ default:
+ {
+ TRESPASS();
+ break;
+ }
+ }
+}
+
+void ARTPConnection::onAddStream(const sp<AMessage> &msg) {
+ mStreams.push_back(StreamInfo());
+ StreamInfo *info = &*--mStreams.end();
+
+ int32_t s;
+ CHECK(msg->findInt32("rtp-socket", &s));
+ info->mRTPSocket = s;
+ CHECK(msg->findInt32("rtcp-socket", &s));
+ info->mRTCPSocket = s;
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("session-desc", &obj));
+ info->mSessionDesc = static_cast<ASessionDescription *>(obj.get());
+
+ CHECK(msg->findSize("index", &info->mIndex));
+ CHECK(msg->findMessage("notify", &info->mNotifyMsg));
+
+ postPollEvent();
+}
+
+void ARTPConnection::onRemoveStream(const sp<AMessage> &msg) {
+ int32_t rtpSocket, rtcpSocket;
+ CHECK(msg->findInt32("rtp-socket", &rtpSocket));
+ CHECK(msg->findInt32("rtcp-socket", &rtcpSocket));
+
+ List<StreamInfo>::iterator it = mStreams.begin();
+ while (it != mStreams.end()
+ && (it->mRTPSocket != rtpSocket || it->mRTCPSocket != rtcpSocket)) {
+ ++it;
+ }
+
+ if (it == mStreams.end()) {
+ TRESPASS();
+ }
+
+ mStreams.erase(it);
+}
+
+void ARTPConnection::postPollEvent() {
+ if (mPollEventPending) {
+ return;
+ }
+
+ sp<AMessage> msg = new AMessage(kWhatPollStreams, id());
+ msg->post();
+
+ mPollEventPending = true;
+}
+
+void ARTPConnection::onPollStreams() {
+ mPollEventPending = false;
+
+ if (mStreams.empty()) {
+ return;
+ }
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = kSelectTimeoutUs;
+
+ fd_set rs;
+ FD_ZERO(&rs);
+
+ int maxSocket = -1;
+ for (List<StreamInfo>::iterator it = mStreams.begin();
+ it != mStreams.end(); ++it) {
+ FD_SET(it->mRTPSocket, &rs);
+ FD_SET(it->mRTCPSocket, &rs);
+
+ if (it->mRTPSocket > maxSocket) {
+ maxSocket = it->mRTPSocket;
+ }
+ if (it->mRTCPSocket > maxSocket) {
+ maxSocket = it->mRTCPSocket;
+ }
+ }
+
+ int res = select(maxSocket + 1, &rs, NULL, NULL, &tv);
+ CHECK_GE(res, 0);
+
+ if (res > 0) {
+ for (List<StreamInfo>::iterator it = mStreams.begin();
+ it != mStreams.end(); ++it) {
+ if (FD_ISSET(it->mRTPSocket, &rs)) {
+ receive(&*it, true);
+ }
+ if (FD_ISSET(it->mRTCPSocket, &rs)) {
+ receive(&*it, false);
+ }
+ }
+ }
+
+ postPollEvent();
+}
+
+status_t ARTPConnection::receive(StreamInfo *s, bool receiveRTP) {
+ sp<ABuffer> buffer = new ABuffer(65536);
+
+ struct sockaddr_in from;
+ socklen_t fromSize = sizeof(from);
+
+ ssize_t nbytes = recvfrom(
+ receiveRTP ? s->mRTPSocket : s->mRTCPSocket,
+ buffer->data(),
+ buffer->capacity(),
+ 0,
+ (struct sockaddr *)&from,
+ &fromSize);
+
+ if (nbytes < 0) {
+ return -1;
+ }
+
+ buffer->setRange(0, nbytes);
+
+ status_t err;
+ if (receiveRTP) {
+ err = parseRTP(s, buffer);
+ } else {
+ err = parseRTCP(s, buffer);
+ }
+
+ return err;
+}
+
+status_t ARTPConnection::parseRTP(StreamInfo *s, const sp<ABuffer> &buffer) {
+ size_t size = buffer->size();
+
+ if (size < 12) {
+ // Too short to be a valid RTP header.
+ return -1;
+ }
+
+ const uint8_t *data = buffer->data();
+
+ if ((data[0] >> 6) != 2) {
+ // Unsupported version.
+ return -1;
+ }
+
+ if (data[0] & 0x20) {
+ // Padding present.
+
+ size_t paddingLength = data[size - 1];
+
+ if (paddingLength + 12 > size) {
+ // If we removed this much padding we'd end up with something
+ // that's too short to be a valid RTP header.
+ return -1;
+ }
+
+ size -= paddingLength;
+ }
+
+ int numCSRCs = data[0] & 0x0f;
+
+ size_t payloadOffset = 12 + 4 * numCSRCs;
+
+ if (size < payloadOffset) {
+ // Not enough data to fit the basic header and all the CSRC entries.
+ return -1;
+ }
+
+ if (data[0] & 0x10) {
+ // Header eXtension present.
+
+ if (size < payloadOffset + 4) {
+ // Not enough data to fit the basic header, all CSRC entries
+ // and the first 4 bytes of the extension header.
+
+ return -1;
+ }
+
+ const uint8_t *extensionData = &data[payloadOffset];
+
+ size_t extensionLength =
+ 4 * (extensionData[2] << 8 | extensionData[3]);
+
+ if (size < payloadOffset + 4 + extensionLength) {
+ return -1;
+ }
+
+ payloadOffset += 4 + extensionLength;
+ }
+
+ uint32_t srcId = u32at(&data[8]);
+
+ sp<ARTPSource> source;
+ ssize_t index = mSources.indexOfKey(srcId);
+ if (index < 0) {
+ index = mSources.size();
+
+ source = new ARTPSource(
+ srcId, s->mSessionDesc, s->mIndex, s->mNotifyMsg);
+
+ mSources.add(srcId, source);
+ } else {
+ source = mSources.valueAt(index);
+ }
+
+ uint32_t rtpTime = u32at(&data[4]);
+
+ sp<AMessage> meta = buffer->meta();
+ meta->setInt32("ssrc", srcId);
+ meta->setInt32("rtp-time", rtpTime);
+ meta->setInt32("PT", data[1] & 0x7f);
+ meta->setInt32("M", data[1] >> 7);
+
+ buffer->setInt32Data(u16at(&data[2]));
+
+#if VERBOSE
+ printf("RTP = {\n"
+ " PT: %d\n"
+ " sequence number: %d\n"
+ " RTP-time: 0x%08x\n"
+ " M: %d\n"
+ " SSRC: 0x%08x\n"
+ "}\n",
+ data[1] & 0x7f,
+ u16at(&data[2]),
+ rtpTime,
+ data[1] >> 7,
+ srcId);
+
+ // hexdump(&data[payloadOffset], size - payloadOffset);
+#endif
+
+ buffer->setRange(payloadOffset, size - payloadOffset);
+
+ source->processRTPPacket(buffer);
+
+ return OK;
+}
+
+status_t ARTPConnection::parseRTCP(StreamInfo *s, const sp<ABuffer> &buffer) {
+ const uint8_t *data = buffer->data();
+ size_t size = buffer->size();
+
+ while (size > 0) {
+ if (size < 8) {
+ // Too short to be a valid RTCP header
+ return -1;
+ }
+
+ if ((data[0] >> 6) != 2) {
+ // Unsupported version.
+ return -1;
+ }
+
+ if (data[0] & 0x20) {
+ // Padding present.
+
+ size_t paddingLength = data[size - 1];
+
+ if (paddingLength + 12 > size) {
+ // If we removed this much padding we'd end up with something
+ // that's too short to be a valid RTP header.
+ return -1;
+ }
+
+ size -= paddingLength;
+ }
+
+ size_t headerLength = 4 * (data[2] << 8 | data[3]) + 4;
+
+ if (size < headerLength) {
+ // Only received a partial packet?
+ return -1;
+ }
+
+ switch (data[1]) {
+ case 200:
+ {
+ parseSR(s, data, headerLength);
+ break;
+ }
+
+ default:
+ {
+#if VERBOSE
+ printf("Unknown RTCP packet type %d of size %ld\n",
+ data[1], headerLength);
+
+ hexdump(data, headerLength);
+#endif
+ break;
+ }
+ }
+
+ data += headerLength;
+ size -= headerLength;
+ }
+
+ return OK;
+}
+
+status_t ARTPConnection::parseSR(
+ StreamInfo *s, const uint8_t *data, size_t size) {
+ size_t RC = data[0] & 0x1f;
+
+ if (size < (7 + RC * 6) * 4) {
+ // Packet too short for the minimal SR header.
+ return -1;
+ }
+
+ uint32_t id = u32at(&data[4]);
+ uint64_t ntpTime = u64at(&data[8]);
+ uint32_t rtpTime = u32at(&data[16]);
+
+#if VERBOSE
+ printf("SR = {\n"
+ " SSRC: 0x%08x\n"
+ " NTP-time: 0x%016llx\n"
+ " RTP-time: 0x%08x\n"
+ "}\n",
+ id, ntpTime, rtpTime);
+#endif
+
+ sp<ARTPSource> source;
+ ssize_t index = mSources.indexOfKey(id);
+ if (index < 0) {
+ index = mSources.size();
+
+ source = new ARTPSource(
+ id, s->mSessionDesc, s->mIndex, s->mNotifyMsg);
+
+ mSources.add(id, source);
+ } else {
+ source = mSources.valueAt(index);
+ }
+
+ source->timeUpdate(rtpTime, ntpTime);
+
+ return 0;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/ARTPConnection.h b/media/libstagefright/rtsp/ARTPConnection.h
new file mode 100644
index 0000000..c77e3a4
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPConnection.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_RTP_CONNECTION_H_
+
+#define A_RTP_CONNECTION_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+#include <utils/List.h>
+
+namespace android {
+
+struct ABuffer;
+struct ARTPSource;
+struct ASessionDescription;
+
+struct ARTPConnection : public AHandler {
+ ARTPConnection();
+
+ void addStream(
+ int rtpSocket, int rtcpSocket,
+ const sp<ASessionDescription> &sessionDesc, size_t index,
+ const sp<AMessage> &notify);
+
+ void removeStream(int rtpSocket, int rtcpSocket);
+
+ // Creates a pair of UDP datagram sockets bound to adjacent ports
+ // (the rtpSocket is bound to an even port, the rtcpSocket to the
+ // next higher port).
+ static void MakePortPair(
+ int *rtpSocket, int *rtcpSocket, unsigned *rtpPort);
+
+protected:
+ virtual ~ARTPConnection();
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum {
+ kWhatAddStream,
+ kWhatRemoveStream,
+ kWhatPollStreams,
+ };
+
+ static const int64_t kSelectTimeoutUs;
+
+ struct StreamInfo;
+ List<StreamInfo> mStreams;
+
+ KeyedVector<uint32_t, sp<ARTPSource> > mSources;
+
+ bool mPollEventPending;
+
+ void onAddStream(const sp<AMessage> &msg);
+ void onRemoveStream(const sp<AMessage> &msg);
+ void onPollStreams();
+
+ status_t receive(StreamInfo *info, bool receiveRTP);
+
+ status_t parseRTP(StreamInfo *info, const sp<ABuffer> &buffer);
+ status_t parseRTCP(StreamInfo *info, const sp<ABuffer> &buffer);
+ status_t parseSR(StreamInfo *info, const uint8_t *data, size_t size);
+
+ void postPollEvent();
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPConnection);
+};
+
+} // namespace android
+
+#endif // A_RTP_CONNECTION_H_
diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp
new file mode 100644
index 0000000..f05daa8
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSource.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ARTPSource.h"
+
+#include "AAVCAssembler.h"
+#include "AMPEG4AudioAssembler.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#define VERBOSE 0
+
+namespace android {
+
+ARTPSource::ARTPSource(
+ uint32_t id,
+ const sp<ASessionDescription> &sessionDesc, size_t index,
+ const sp<AMessage> &notify)
+ : mID(id),
+ mHighestSeqNumber(0),
+ mNumBuffersReceived(0),
+ mNumTimes(0) {
+ unsigned long PT;
+ AString desc;
+ AString params;
+ sessionDesc->getFormatType(index, &PT, &desc, &params);
+
+ if (!strncmp(desc.c_str(), "H264/", 5)) {
+ mAssembler = new AAVCAssembler(notify);
+ } else if (!strncmp(desc.c_str(), "MP4A-LATM", 9)) {
+ mAssembler = new AMPEG4AudioAssembler(notify);
+ } else {
+ TRESPASS();
+ }
+}
+
+static uint32_t AbsDiff(uint32_t seq1, uint32_t seq2) {
+ return seq1 > seq2 ? seq1 - seq2 : seq2 - seq1;
+}
+
+void ARTPSource::processRTPPacket(const sp<ABuffer> &buffer) {
+ if (queuePacket(buffer) && mNumTimes == 2 && mAssembler != NULL) {
+ mAssembler->onPacketReceived(this);
+ }
+
+ dump();
+}
+
+void ARTPSource::timeUpdate(uint32_t rtpTime, uint64_t ntpTime) {
+#if VERBOSE
+ LOG(VERBOSE) << "timeUpdate";
+#endif
+
+ if (mNumTimes == 2) {
+ mNTPTime[0] = mNTPTime[1];
+ mRTPTime[0] = mRTPTime[1];
+ mNumTimes = 1;
+ }
+ mNTPTime[mNumTimes] = ntpTime;
+ mRTPTime[mNumTimes++] = rtpTime;
+
+ if (mNumTimes == 2) {
+ for (List<sp<ABuffer> >::iterator it = mQueue.begin();
+ it != mQueue.end(); ++it) {
+ sp<AMessage> meta = (*it)->meta();
+
+ uint32_t rtpTime;
+ CHECK(meta->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ meta->setInt64("ntp-time", RTP2NTP(rtpTime));
+ }
+ }
+}
+
+bool ARTPSource::queuePacket(const sp<ABuffer> &buffer) {
+ uint32_t seqNum = (uint32_t)buffer->int32Data();
+
+ if (mNumTimes == 2) {
+ sp<AMessage> meta = buffer->meta();
+
+ uint32_t rtpTime;
+ CHECK(meta->findInt32("rtp-time", (int32_t *)&rtpTime));
+
+ meta->setInt64("ntp-time", RTP2NTP(rtpTime));
+ }
+
+ if (mNumBuffersReceived++ == 0) {
+ mHighestSeqNumber = seqNum;
+ mQueue.push_back(buffer);
+ return true;
+ }
+
+ // Only the lower 16-bit of the sequence numbers are transmitted,
+ // derive the high-order bits by choosing the candidate closest
+ // to the highest sequence number (extended to 32 bits) received so far.
+
+ uint32_t seq1 = seqNum | (mHighestSeqNumber & 0xffff0000);
+ uint32_t seq2 = seqNum | ((mHighestSeqNumber & 0xffff0000) + 0x10000);
+ uint32_t seq3 = seqNum | ((mHighestSeqNumber & 0xffff0000) - 0x10000);
+ uint32_t diff1 = AbsDiff(seq1, mHighestSeqNumber);
+ uint32_t diff2 = AbsDiff(seq2, mHighestSeqNumber);
+ uint32_t diff3 = AbsDiff(seq3, mHighestSeqNumber);
+
+ if (diff1 < diff2) {
+ if (diff1 < diff3) {
+ // diff1 < diff2 ^ diff1 < diff3
+ seqNum = seq1;
+ } else {
+ // diff3 <= diff1 < diff2
+ seqNum = seq3;
+ }
+ } else if (diff2 < diff3) {
+ // diff2 <= diff1 ^ diff2 < diff3
+ seqNum = seq2;
+ } else {
+ // diff3 <= diff2 <= diff1
+ seqNum = seq3;
+ }
+
+ if (seqNum > mHighestSeqNumber) {
+ mHighestSeqNumber = seqNum;
+ }
+
+ buffer->setInt32Data(seqNum);
+
+ List<sp<ABuffer> >::iterator it = mQueue.begin();
+ while (it != mQueue.end() && (uint32_t)(*it)->int32Data() < seqNum) {
+ ++it;
+ }
+
+ if (it != mQueue.end() && (uint32_t)(*it)->int32Data() == seqNum) {
+ LOG(WARNING) << "Discarding duplicate buffer";
+ return false;
+ }
+
+ mQueue.insert(it, buffer);
+
+ return true;
+}
+
+void ARTPSource::dump() const {
+ if ((mNumBuffersReceived % 128) != 0) {
+ return;
+ }
+
+#if 0
+ if (mAssembler == NULL) {
+ char tmp[20];
+ sprintf(tmp, "0x%08x", mID);
+
+ int32_t numMissing = 0;
+
+ if (!mQueue.empty()) {
+ List<sp<ABuffer> >::const_iterator it = mQueue.begin();
+ uint32_t expectedSeqNum = (uint32_t)(*it)->int32Data();
+ ++expectedSeqNum;
+ ++it;
+
+ for (; it != mQueue.end(); ++it) {
+ uint32_t seqNum = (uint32_t)(*it)->int32Data();
+ CHECK_GE(seqNum, expectedSeqNum);
+
+ if (seqNum != expectedSeqNum) {
+ numMissing += seqNum - expectedSeqNum;
+ expectedSeqNum = seqNum;
+ }
+
+ ++expectedSeqNum;
+ }
+ }
+
+ LOG(VERBOSE) << "[" << tmp << "] Missing " << numMissing
+ << " / " << (mNumBuffersReceived + numMissing) << " packets. ("
+ << (100.0 * numMissing / (mNumBuffersReceived + numMissing))
+ << " %%)";
+ }
+#endif
+
+#if 0
+ AString out;
+
+ out.append(tmp);
+ out.append(" [");
+
+ List<sp<ABuffer> >::const_iterator it = mQueue.begin();
+ while (it != mQueue.end()) {
+ uint32_t start = (uint32_t)(*it)->int32Data();
+
+ out.append(start);
+
+ ++it;
+ uint32_t expected = start + 1;
+
+ while (it != mQueue.end()) {
+ uint32_t seqNum = (uint32_t)(*it)->int32Data();
+
+ if (seqNum != expected) {
+ if (expected > start + 1) {
+ out.append("-");
+ out.append(expected - 1);
+ }
+ out.append(", ");
+ break;
+ }
+
+ ++it;
+ ++expected;
+ }
+
+ if (it == mQueue.end()) {
+ if (expected > start + 1) {
+ out.append("-");
+ out.append(expected - 1);
+ }
+ }
+ }
+
+ out.append("]");
+
+ LOG(VERBOSE) << out;
+#endif
+}
+
+uint64_t ARTPSource::RTP2NTP(uint32_t rtpTime) const {
+ CHECK_EQ(mNumTimes, 2u);
+
+ return mNTPTime[0] + (double)(mNTPTime[1] - mNTPTime[0])
+ * ((double)rtpTime - (double)mRTPTime[0])
+ / (double)(mRTPTime[1] - mRTPTime[0]);
+}
+
+} // namespace android
+
+
diff --git a/media/libstagefright/rtsp/ARTPSource.h b/media/libstagefright/rtsp/ARTPSource.h
new file mode 100644
index 0000000..b93cd56
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTPSource.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_RTP_SOURCE_H_
+
+#define A_RTP_SOURCE_H_
+
+#include <stdint.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/List.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ABuffer;
+struct AMessage;
+struct ARTPAssembler;
+struct ASessionDescription;
+
+struct ARTPSource : public RefBase {
+ ARTPSource(
+ uint32_t id,
+ const sp<ASessionDescription> &sessionDesc, size_t index,
+ const sp<AMessage> &notify);
+
+ void processRTPPacket(const sp<ABuffer> &buffer);
+ void timeUpdate(uint32_t rtpTime, uint64_t ntpTime);
+
+ List<sp<ABuffer> > *queue() { return &mQueue; }
+
+private:
+ uint32_t mID;
+ uint32_t mHighestSeqNumber;
+ int32_t mNumBuffersReceived;
+
+ List<sp<ABuffer> > mQueue;
+ sp<ARTPAssembler> mAssembler;
+
+ size_t mNumTimes;
+ uint64_t mNTPTime[2];
+ uint32_t mRTPTime[2];
+
+ uint64_t RTP2NTP(uint32_t rtpTime) const;
+
+ bool queuePacket(const sp<ABuffer> &buffer);
+ void dump() const;
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTPSource);
+};
+
+} // namespace android
+
+#endif // A_RTP_SOURCE_H_
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
new file mode 100644
index 0000000..e9162c0
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ARTSPConnection.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+namespace android {
+
+// static
+const int64_t ARTSPConnection::kSelectTimeoutUs = 1000ll;
+
+ARTSPConnection::ARTSPConnection()
+ : mState(DISCONNECTED),
+ mSocket(-1),
+ mConnectionID(0),
+ mNextCSeq(0),
+ mReceiveResponseEventPending(false) {
+}
+
+ARTSPConnection::~ARTSPConnection() {
+ if (mSocket >= 0) {
+ LOG(ERROR) << "Connection is still open, closing the socket.";
+ close(mSocket);
+ mSocket = -1;
+ }
+}
+
+void ARTSPConnection::connect(const char *url, const sp<AMessage> &reply) {
+ sp<AMessage> msg = new AMessage(kWhatConnect, id());
+ msg->setString("url", url);
+ msg->setMessage("reply", reply);
+ msg->post();
+}
+
+void ARTSPConnection::disconnect(const sp<AMessage> &reply) {
+ sp<AMessage> msg = new AMessage(kWhatDisconnect, id());
+ msg->setMessage("reply", reply);
+ msg->post();
+}
+
+void ARTSPConnection::sendRequest(
+ const char *request, const sp<AMessage> &reply) {
+ sp<AMessage> msg = new AMessage(kWhatSendRequest, id());
+ msg->setString("request", request);
+ msg->setMessage("reply", reply);
+ msg->post();
+}
+
+void ARTSPConnection::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatConnect:
+ onConnect(msg);
+ break;
+
+ case kWhatDisconnect:
+ onDisconnect(msg);
+ break;
+
+ case kWhatCompleteConnection:
+ onCompleteConnection(msg);
+ break;
+
+ case kWhatSendRequest:
+ onSendRequest(msg);
+ break;
+
+ case kWhatReceiveResponse:
+ onReceiveResponse();
+ break;
+
+ default:
+ TRESPASS();
+ break;
+ }
+}
+
+// static
+bool ARTSPConnection::ParseURL(
+ const char *url, AString *host, unsigned *port, AString *path) {
+ host->clear();
+ *port = 0;
+ path->clear();
+
+ if (strncasecmp("rtsp://", url, 7)) {
+ return false;
+ }
+
+ const char *slashPos = strchr(&url[7], '/');
+
+ if (slashPos == NULL) {
+ host->setTo(&url[7]);
+ path->setTo("/");
+ } else {
+ host->setTo(&url[7], slashPos - &url[7]);
+ path->setTo(slashPos);
+ }
+
+ char *colonPos = strchr(host->c_str(), ':');
+
+ if (colonPos != NULL) {
+ unsigned long x;
+ if (!ParseSingleUnsignedLong(colonPos + 1, &x) || x >= 65536) {
+ return false;
+ }
+
+ *port = x;
+
+ size_t colonOffset = colonPos - host->c_str();
+ size_t trailing = host->size() - colonOffset;
+ host->erase(colonOffset, trailing);
+ } else {
+ *port = 554;
+ }
+
+ return true;
+}
+
+void ARTSPConnection::onConnect(const sp<AMessage> &msg) {
+ ++mConnectionID;
+
+ if (mState != DISCONNECTED) {
+ close(mSocket);
+ mSocket = -1;
+
+ flushPendingRequests();
+ }
+
+ mState = CONNECTING;
+
+ mSocket = socket(AF_INET, SOCK_STREAM, 0);
+
+ // Make socket non-blocking.
+ int flags = fcntl(mSocket, F_GETFL, 0);
+ CHECK_NE(flags, -1);
+ CHECK_NE(fcntl(mSocket, F_SETFL, flags | O_NONBLOCK), -1);
+
+ AString url;
+ CHECK(msg->findString("url", &url));
+
+ AString host, path;
+ unsigned port;
+ CHECK(ParseURL(url.c_str(), &host, &port, &path));
+
+ struct hostent *ent = gethostbyname(host.c_str());
+ CHECK(ent != NULL);
+
+ struct sockaddr_in remote;
+ memset(remote.sin_zero, 0, sizeof(remote.sin_zero));
+ remote.sin_family = AF_INET;
+ remote.sin_addr.s_addr = *(in_addr_t *)ent->h_addr;
+ remote.sin_port = htons(port);
+
+ int err = ::connect(
+ mSocket, (const struct sockaddr *)&remote, sizeof(remote));
+
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ reply->setInt32("server-ip", ntohl(remote.sin_addr.s_addr));
+
+ if (err < 0) {
+ if (errno == EINPROGRESS) {
+ sp<AMessage> msg = new AMessage(kWhatCompleteConnection, id());
+ msg->setMessage("reply", reply);
+ msg->setInt32("connection-id", mConnectionID);
+ msg->post();
+ return;
+ }
+
+ reply->setInt32("result", -errno);
+ mState = DISCONNECTED;
+
+ close(mSocket);
+ mSocket = -1;
+ } else {
+ reply->setInt32("result", OK);
+ mState = CONNECTED;
+ mNextCSeq = 1;
+
+ postReceiveReponseEvent();
+ }
+
+ reply->post();
+}
+
+void ARTSPConnection::onDisconnect(const sp<AMessage> &msg) {
+ if (mState == CONNECTED || mState == CONNECTING) {
+ close(mSocket);
+ mSocket = -1;
+
+ flushPendingRequests();
+ }
+
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ reply->setInt32("result", OK);
+ mState = DISCONNECTED;
+
+ reply->post();
+}
+
+void ARTSPConnection::onCompleteConnection(const sp<AMessage> &msg) {
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ int32_t connectionID;
+ CHECK(msg->findInt32("connection-id", &connectionID));
+
+ if ((connectionID != mConnectionID) || mState != CONNECTING) {
+ // While we were attempting to connect, the attempt was
+ // cancelled.
+ reply->setInt32("result", -ECONNABORTED);
+ reply->post();
+ return;
+ }
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = kSelectTimeoutUs;
+
+ fd_set ws;
+ FD_ZERO(&ws);
+ FD_SET(mSocket, &ws);
+
+ int res = select(mSocket + 1, NULL, &ws, NULL, &tv);
+ CHECK_GE(res, 0);
+
+ if (res == 0) {
+ // Timed out. Not yet connected.
+
+ msg->post();
+ return;
+ }
+
+ int err;
+ socklen_t optionLen = sizeof(err);
+ CHECK_EQ(getsockopt(mSocket, SOL_SOCKET, SO_ERROR, &err, &optionLen), 0);
+ CHECK_EQ(optionLen, (socklen_t)sizeof(err));
+
+ if (err != 0) {
+ LOG(ERROR) << "err = " << err << " (" << strerror(err) << ")";
+
+ reply->setInt32("result", -err);
+
+ mState = DISCONNECTED;
+ close(mSocket);
+ mSocket = -1;
+ } else {
+ reply->setInt32("result", OK);
+ mState = CONNECTED;
+ mNextCSeq = 1;
+
+ postReceiveReponseEvent();
+ }
+
+ reply->post();
+}
+
+void ARTSPConnection::onSendRequest(const sp<AMessage> &msg) {
+ sp<AMessage> reply;
+ CHECK(msg->findMessage("reply", &reply));
+
+ if (mState != CONNECTED) {
+ reply->setInt32("result", -ENOTCONN);
+ reply->post();
+ return;
+ }
+
+ AString request;
+ CHECK(msg->findString("request", &request));
+
+ // Find the boundary between headers and the body.
+ ssize_t i = request.find("\r\n\r\n");
+ CHECK_GE(i, 0);
+
+ int32_t cseq = mNextCSeq++;
+
+ AString cseqHeader = "CSeq: ";
+ cseqHeader.append(cseq);
+ cseqHeader.append("\r\n");
+
+ request.insert(cseqHeader, i + 2);
+
+ LOG(VERBOSE) << request;
+
+ size_t numBytesSent = 0;
+ while (numBytesSent < request.size()) {
+ ssize_t n =
+ send(mSocket, request.c_str() + numBytesSent,
+ request.size() - numBytesSent, 0);
+
+ if (n == 0) {
+ // Server closed the connection.
+ TRESPASS();
+ } else if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ TRESPASS();
+ }
+
+ numBytesSent += (size_t)n;
+ }
+
+ mPendingRequests.add(cseq, reply);
+}
+
+void ARTSPConnection::onReceiveResponse() {
+ mReceiveResponseEventPending = false;
+
+ if (mState != CONNECTED) {
+ return;
+ }
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = kSelectTimeoutUs;
+
+ fd_set rs;
+ FD_ZERO(&rs);
+ FD_SET(mSocket, &rs);
+
+ int res = select(mSocket + 1, &rs, NULL, NULL, &tv);
+ CHECK_GE(res, 0);
+
+ if (res == 1) {
+ if (!receiveRTSPReponse()) {
+ // Something horrible, irreparable has happened.
+ flushPendingRequests();
+ return;
+ }
+ }
+
+ postReceiveReponseEvent();
+}
+
+void ARTSPConnection::flushPendingRequests() {
+ for (size_t i = 0; i < mPendingRequests.size(); ++i) {
+ sp<AMessage> reply = mPendingRequests.valueAt(i);
+
+ reply->setInt32("result", -ECONNABORTED);
+ reply->post();
+ }
+
+ mPendingRequests.clear();
+}
+
+void ARTSPConnection::postReceiveReponseEvent() {
+ if (mReceiveResponseEventPending) {
+ return;
+ }
+
+ sp<AMessage> msg = new AMessage(kWhatReceiveResponse, id());
+ msg->post();
+
+ mReceiveResponseEventPending = true;
+}
+
+bool ARTSPConnection::receiveLine(AString *line) {
+ line->clear();
+
+ bool sawCR = false;
+ for (;;) {
+ char c;
+ ssize_t n = recv(mSocket, &c, 1, 0);
+ if (n == 0) {
+ // Server closed the connection.
+ return false;
+ } else if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ TRESPASS();
+ }
+
+ if (sawCR && c == '\n') {
+ line->erase(line->size() - 1, 1);
+ return true;
+ }
+
+ line->append(&c, 1);
+
+ sawCR = (c == '\r');
+ }
+}
+
+bool ARTSPConnection::receiveRTSPReponse() {
+ sp<ARTSPResponse> response = new ARTSPResponse;
+
+ if (!receiveLine(&response->mStatusLine)) {
+ return false;
+ }
+
+ LOG(INFO) << "status: " << response->mStatusLine;
+
+ ssize_t space1 = response->mStatusLine.find(" ");
+ if (space1 < 0) {
+ return false;
+ }
+ ssize_t space2 = response->mStatusLine.find(" ", space1 + 1);
+ if (space2 < 0) {
+ return false;
+ }
+
+ AString statusCodeStr(
+ response->mStatusLine, space1 + 1, space2 - space1 - 1);
+
+ if (!ParseSingleUnsignedLong(
+ statusCodeStr.c_str(), &response->mStatusCode)
+ || response->mStatusCode < 100 || response->mStatusCode > 999) {
+ return false;
+ }
+
+ AString line;
+ for (;;) {
+ if (!receiveLine(&line)) {
+ break;
+ }
+
+ if (line.empty()) {
+ break;
+ }
+
+ LOG(VERBOSE) << "line: " << line;
+
+ ssize_t colonPos = line.find(":");
+ if (colonPos < 0) {
+ // Malformed header line.
+ return false;
+ }
+
+ AString key(line, 0, colonPos);
+ key.trim();
+ key.tolower();
+
+ line.erase(0, colonPos + 1);
+ line.trim();
+
+ response->mHeaders.add(key, line);
+ }
+
+ unsigned long contentLength = 0;
+
+ ssize_t i = response->mHeaders.indexOfKey("content-length");
+
+ if (i >= 0) {
+ AString value = response->mHeaders.valueAt(i);
+ if (!ParseSingleUnsignedLong(value.c_str(), &contentLength)) {
+ return false;
+ }
+ }
+
+ if (contentLength > 0) {
+ response->mContent = new ABuffer(contentLength);
+
+ size_t numBytesRead = 0;
+ while (numBytesRead < contentLength) {
+ ssize_t n = recv(
+ mSocket, response->mContent->data() + numBytesRead,
+ contentLength - numBytesRead, 0);
+
+ if (n == 0) {
+ // Server closed the connection.
+ TRESPASS();
+ } else if (n < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+
+ TRESPASS();
+ }
+
+ numBytesRead += (size_t)n;
+ }
+ }
+
+ return notifyResponseListener(response);
+}
+
+// static
+bool ARTSPConnection::ParseSingleUnsignedLong(
+ const char *from, unsigned long *x) {
+ char *end;
+ *x = strtoul(from, &end, 10);
+
+ if (end == from || *end != '\0') {
+ return false;
+ }
+
+ return true;
+}
+
+bool ARTSPConnection::notifyResponseListener(
+ const sp<ARTSPResponse> &response) {
+ ssize_t i = response->mHeaders.indexOfKey("cseq");
+
+ if (i < 0) {
+ return true;
+ }
+
+ AString value = response->mHeaders.valueAt(i);
+
+ unsigned long cseq;
+ if (!ParseSingleUnsignedLong(value.c_str(), &cseq)) {
+ return false;
+ }
+
+ i = mPendingRequests.indexOfKey(cseq);
+
+ if (i < 0) {
+ // Unsolicited response?
+ TRESPASS();
+ }
+
+ sp<AMessage> reply = mPendingRequests.valueAt(i);
+ mPendingRequests.removeItemsAt(i);
+
+ reply->setInt32("result", OK);
+ reply->setObject("response", response);
+ reply->post();
+
+ return true;
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ARTSPConnection.h b/media/libstagefright/rtsp/ARTSPConnection.h
new file mode 100644
index 0000000..3577a2f
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPConnection.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_RTSP_CONNECTION_H_
+
+#define A_RTSP_CONNECTION_H_
+
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+struct ABuffer;
+
+struct ARTSPResponse : public RefBase {
+ unsigned long mStatusCode;
+ AString mStatusLine;
+ KeyedVector<AString,AString> mHeaders;
+ sp<ABuffer> mContent;
+};
+
+struct ARTSPConnection : public AHandler {
+ ARTSPConnection();
+
+ void connect(const char *url, const sp<AMessage> &reply);
+ void disconnect(const sp<AMessage> &reply);
+
+ void sendRequest(const char *request, const sp<AMessage> &reply);
+
+protected:
+ virtual ~ARTSPConnection();
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+private:
+ enum State {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ };
+
+ enum {
+ kWhatConnect = 'conn',
+ kWhatDisconnect = 'disc',
+ kWhatCompleteConnection = 'comc',
+ kWhatSendRequest = 'sreq',
+ kWhatReceiveResponse = 'rres',
+ };
+
+ static const int64_t kSelectTimeoutUs;
+
+ State mState;
+ int mSocket;
+ int32_t mConnectionID;
+ int32_t mNextCSeq;
+ bool mReceiveResponseEventPending;
+
+ KeyedVector<int32_t, sp<AMessage> > mPendingRequests;
+
+ void onConnect(const sp<AMessage> &msg);
+ void onDisconnect(const sp<AMessage> &msg);
+ void onCompleteConnection(const sp<AMessage> &msg);
+ void onSendRequest(const sp<AMessage> &msg);
+ void onReceiveResponse();
+
+ void flushPendingRequests();
+ void postReceiveReponseEvent();
+
+ // Return false iff something went unrecoverably wrong.
+ bool receiveRTSPReponse();
+ bool receiveLine(AString *line);
+ bool notifyResponseListener(const sp<ARTSPResponse> &response);
+
+ static bool ParseURL(
+ const char *url, AString *host, unsigned *port, AString *path);
+
+ static bool ParseSingleUnsignedLong(
+ const char *from, unsigned long *x);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ARTSPConnection);
+};
+
+} // namespace android
+
+#endif // A_RTSP_CONNECTION_H_
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
new file mode 100644
index 0000000..195323e
--- /dev/null
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ARTSPController.h"
+
+#include "MyHandler.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+ARTSPController::ARTSPController(const sp<ALooper> &looper)
+ : mLooper(looper) {
+}
+
+ARTSPController::~ARTSPController() {
+}
+
+status_t ARTSPController::connect(const char *url) {
+ if (mHandler != NULL) {
+ return ERROR_ALREADY_CONNECTED;
+ }
+
+ mHandler = new MyHandler(url, mLooper);
+ mHandler->connect();
+
+ sleep(10);
+
+ return OK;
+}
+
+void ARTSPController::disconnect() {
+ if (mHandler == NULL) {
+ return;
+ }
+
+ mHandler->disconnect();
+ mHandler.clear();
+}
+
+size_t ARTSPController::countTracks() {
+ if (mHandler == NULL) {
+ return 0;
+ }
+
+ return mHandler->countTracks();
+}
+
+sp<MediaSource> ARTSPController::getTrack(size_t index) {
+ CHECK(mHandler != NULL);
+
+ return mHandler->getPacketSource(index);
+}
+
+sp<MetaData> ARTSPController::getTrackMetaData(
+ size_t index, uint32_t flags) {
+ CHECK(mHandler != NULL);
+
+ return mHandler->getPacketSource(index)->getFormat();
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/ASessionDescription.cpp b/media/libstagefright/rtsp/ASessionDescription.cpp
new file mode 100644
index 0000000..ca4c55e
--- /dev/null
+++ b/media/libstagefright/rtsp/ASessionDescription.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AString.h>
+
+#include <stdlib.h>
+
+namespace android {
+
+ASessionDescription::ASessionDescription()
+ : mIsValid(false) {
+}
+
+ASessionDescription::~ASessionDescription() {
+}
+
+bool ASessionDescription::setTo(const void *data, size_t size) {
+ mIsValid = parse(data, size);
+
+ if (!mIsValid) {
+ mTracks.clear();
+ mFormats.clear();
+ }
+
+ return mIsValid;
+}
+
+bool ASessionDescription::parse(const void *data, size_t size) {
+ mTracks.clear();
+ mFormats.clear();
+
+ mTracks.push(Attribs());
+ mFormats.push(AString("[root]"));
+
+ AString desc((const char *)data, size);
+ LOG(VERBOSE) << desc;
+
+ size_t i = 0;
+ for (;;) {
+ ssize_t eolPos = desc.find("\r\n", i);
+ if (eolPos < 0) {
+ break;
+ }
+
+ AString line(desc, i, eolPos - i);
+
+ if (line.size() < 2 || line.c_str()[1] != '=') {
+ return false;
+ }
+
+ switch (line.c_str()[0]) {
+ case 'v':
+ {
+ if (strcmp(line.c_str(), "v=0")) {
+ return false;
+ }
+ break;
+ }
+
+ case 'a':
+ case 'b':
+ {
+ AString key, value;
+
+ ssize_t colonPos = line.find(":", 2);
+ if (colonPos < 0) {
+ key = line;
+ } else {
+ key.setTo(line, 0, colonPos);
+
+ if (key == "a=fmtp" || key == "a=rtpmap"
+ || key == "a=framesize") {
+ ssize_t spacePos = line.find(" ", colonPos + 1);
+ if (spacePos < 0) {
+ return false;
+ }
+
+ key.setTo(line, 0, spacePos);
+
+ colonPos = spacePos;
+ }
+
+ value.setTo(line, colonPos + 1, line.size() - colonPos - 1);
+ }
+
+ key.trim();
+ value.trim();
+
+ LOG(VERBOSE) << "adding '" << key << "' => '" << value << "'";
+
+ mTracks.editItemAt(mTracks.size() - 1).add(key, value);
+ break;
+ }
+
+ case 'm':
+ {
+ LOG(VERBOSE) << "new section '" << AString(line, 2, line.size() - 2) << "'";
+
+ mTracks.push(Attribs());
+ mFormats.push(AString(line, 2, line.size() - 2));
+ break;
+ }
+ }
+
+ i = eolPos + 2;
+ }
+
+ return true;
+}
+
+bool ASessionDescription::isValid() const {
+ return mIsValid;
+}
+
+size_t ASessionDescription::countTracks() const {
+ return mTracks.size();
+}
+
+void ASessionDescription::getFormat(size_t index, AString *value) const {
+ CHECK_GE(index, 0u);
+ CHECK_LT(index, mTracks.size());
+
+ *value = mFormats.itemAt(index);
+}
+
+bool ASessionDescription::findAttribute(
+ size_t index, const char *key, AString *value) const {
+ CHECK_GE(index, 0u);
+ CHECK_LT(index, mTracks.size());
+
+ value->clear();
+
+ const Attribs &track = mTracks.itemAt(index);
+ ssize_t i = track.indexOfKey(AString(key));
+
+ if (i < 0) {
+ return false;
+ }
+
+ *value = track.valueAt(i);
+
+ return true;
+}
+
+void ASessionDescription::getFormatType(
+ size_t index, unsigned long *PT,
+ AString *desc, AString *params) const {
+ AString format;
+ getFormat(index, &format);
+
+ char *lastSpacePos = strrchr(format.c_str(), ' ');
+ CHECK(lastSpacePos != NULL);
+
+ char *end;
+ unsigned long x = strtoul(lastSpacePos + 1, &end, 10);
+ CHECK_GT(end, lastSpacePos + 1);
+ CHECK_EQ(*end, '\0');
+
+ *PT = x;
+
+ char key[20];
+ sprintf(key, "a=rtpmap:%lu", x);
+
+ CHECK(findAttribute(index, key, desc));
+
+ sprintf(key, "a=fmtp:%lu", x);
+ if (!findAttribute(index, key, params)) {
+ params->clear();
+ }
+}
+
+void ASessionDescription::getDimensions(
+ size_t index, unsigned long PT,
+ int32_t *width, int32_t *height) const {
+ char key[20];
+ sprintf(key, "a=framesize:%lu", PT);
+ AString value;
+ CHECK(findAttribute(index, key, &value));
+
+ const char *s = value.c_str();
+ char *end;
+ *width = strtoul(s, &end, 10);
+ CHECK_GT(end, s);
+ CHECK_EQ(*end, '-');
+
+ s = end + 1;
+ *height = strtoul(s, &end, 10);
+ CHECK_GT(end, s);
+ CHECK_EQ(*end, '\0');
+}
+
+bool ASessionDescription::getDurationUs(int64_t *durationUs) const {
+ *durationUs = 0;
+
+ CHECK(mIsValid);
+
+ AString value;
+ if (!findAttribute(0, "a=range", &value)) {
+ return false;
+ }
+
+ if (value == "npt=now-") {
+ return false;
+ }
+
+ if (strncmp(value.c_str(), "npt=", 4)) {
+ return false;
+ }
+
+ const char *s = value.c_str() + 4;
+ char *end;
+ double from = strtod(s, &end);
+ CHECK_GT(end, s);
+ CHECK_EQ(*end, '-');
+
+ s = end + 1;
+ double to = strtod(s, &end);
+ CHECK_GT(end, s);
+ CHECK_EQ(*end, '\0');
+
+ CHECK_GE(to, from);
+
+ *durationUs = (int64_t)((to - from) * 1E6);
+
+ return true;
+}
+
+// static
+void ASessionDescription::ParseFormatDesc(
+ const char *desc, int32_t *timescale, int32_t *numChannels) {
+ const char *slash1 = strchr(desc, '/');
+ CHECK(slash1 != NULL);
+
+ const char *s = slash1 + 1;
+ char *end;
+ unsigned long x = strtoul(s, &end, 10);
+ CHECK_GT(end, s);
+ CHECK(*end == '\0' || *end == '/');
+
+ *timescale = x;
+ *numChannels = 1;
+
+ if (*end == '/') {
+ s = end + 1;
+ unsigned long x = strtoul(s, &end, 10);
+ CHECK_GT(end, s);
+ CHECK_EQ(*end, '\0');
+
+ *numChannels = x;
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/rtsp/ASessionDescription.h b/media/libstagefright/rtsp/ASessionDescription.h
new file mode 100644
index 0000000..b26980f
--- /dev/null
+++ b/media/libstagefright/rtsp/ASessionDescription.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef A_SESSION_DESCRIPTION_H_
+
+#define A_SESSION_DESCRIPTION_H_
+
+#include <sys/types.h>
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/KeyedVector.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct AString;
+
+struct ASessionDescription : public RefBase {
+ ASessionDescription();
+
+ bool setTo(const void *data, size_t size);
+ bool isValid() const;
+
+ // Actually, 1 + number of tracks, as index 0 is reserved for the
+ // session description root-level attributes.
+ size_t countTracks() const;
+ void getFormat(size_t index, AString *value) const;
+
+ void getFormatType(
+ size_t index, unsigned long *PT,
+ AString *desc, AString *params) const;
+
+ void getDimensions(
+ size_t index, unsigned long PT,
+ int32_t *width, int32_t *height) const;
+
+ bool getDurationUs(int64_t *durationUs) const;
+
+ static void ParseFormatDesc(
+ const char *desc, int32_t *timescale, int32_t *numChannels);
+
+ bool findAttribute(size_t index, const char *key, AString *value) const;
+
+protected:
+ virtual ~ASessionDescription();
+
+private:
+ typedef KeyedVector<AString,AString> Attribs;
+
+ bool mIsValid;
+ Vector<Attribs> mTracks;
+ Vector<AString> mFormats;
+
+ bool parse(const void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(ASessionDescription);
+};
+
+} // namespace android
+
+#endif // A_SESSION_DESCRIPTION_H_
diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk
new file mode 100644
index 0000000..4608fa0
--- /dev/null
+++ b/media/libstagefright/rtsp/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ ARTSPController.cpp \
+ AAVCAssembler.cpp \
+ AMPEG4AudioAssembler.cpp \
+ APacketSource.cpp \
+ ARTPAssembler.cpp \
+ ARTPConnection.cpp \
+ ARTPSource.cpp \
+ ARTSPConnection.cpp \
+ ASessionDescription.cpp \
+
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
+ $(TOP)/frameworks/base/media/libstagefright/include \
+
+LOCAL_MODULE:= libstagefright_rtsp
+
+ifeq ($(TARGET_ARCH),arm)
+ LOCAL_CFLAGS += -Wno-psabi
+endif
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
new file mode 100644
index 0000000..044393f
--- /dev/null
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MY_HANDLER_H_
+
+#define MY_HANDLER_H_
+
+#include "APacketSource.h"
+#include "ARTPConnection.h"
+#include "ARTSPConnection.h"
+#include "ASessionDescription.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+
+namespace android {
+
+struct MyHandler : public AHandler {
+ MyHandler(const char *url, const sp<ALooper> &looper)
+ : mLooper(looper),
+ mNetLooper(new ALooper),
+ mConn(new ARTSPConnection),
+ mRTPConn(new ARTPConnection),
+ mSessionURL(url),
+ mSetupTracksSuccessful(false),
+ mFirstAccessUnit(true),
+ mFirstAccessUnitNTP(-1) {
+
+ mNetLooper->start(false /* runOnCallingThread */,
+ false /* canCallJava */,
+ PRIORITY_HIGHEST);
+ }
+
+ void connect() {
+ mLooper->registerHandler(this);
+ mLooper->registerHandler(mConn);
+ (1 ? mNetLooper : mLooper)->registerHandler(mRTPConn);
+ sp<AMessage> reply = new AMessage('conn', id());
+
+ mConn->connect(mSessionURL.c_str(), reply);
+ }
+
+ void disconnect() {
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ }
+
+ virtual void onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case 'conn':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "connection request completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ if (result == OK) {
+ AString request;
+ request = "DESCRIBE ";
+ request.append(mSessionURL);
+ request.append(" RTSP/1.0\r\n");
+ request.append("Accept: application/sdp\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('desc', id());
+ mConn->sendRequest(request.c_str(), reply);
+ }
+ break;
+ }
+
+ case 'disc':
+ {
+ LOG(INFO) << "disconnect completed";
+
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ case 'desc':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "DESCRIBE completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ if (result == OK) {
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ if (response->mStatusCode == 302) {
+ ssize_t i = response->mHeaders.indexOfKey("location");
+ CHECK_GE(i, 0);
+
+ mSessionURL = response->mHeaders.valueAt(i);
+
+ AString request;
+ request = "DESCRIBE ";
+ request.append(mSessionURL);
+ request.append(" RTSP/1.0\r\n");
+ request.append("Accept: application/sdp\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('desc', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ CHECK_EQ(response->mStatusCode, 200u);
+
+ mSessionDesc = new ASessionDescription;
+
+ mSessionDesc->setTo(
+ response->mContent->data(),
+ response->mContent->size());
+
+ CHECK(mSessionDesc->isValid());
+
+ ssize_t i = response->mHeaders.indexOfKey("content-base");
+ if (i >= 0) {
+ mBaseURL = response->mHeaders.valueAt(i);
+ } else {
+ i = response->mHeaders.indexOfKey("content-location");
+ if (i >= 0) {
+ mBaseURL = response->mHeaders.valueAt(i);
+ } else {
+ mBaseURL = mSessionURL;
+ }
+ }
+
+ CHECK_GT(mSessionDesc->countTracks(), 1u);
+ setupTrack(1);
+ } else {
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ }
+ break;
+ }
+
+ case 'setu':
+ {
+ size_t index;
+ CHECK(msg->findSize("index", &index));
+
+ size_t trackIndex;
+ CHECK(msg->findSize("track-index", &trackIndex));
+
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "SETUP(" << index << ") completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+
+ if (result == OK) {
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ CHECK_EQ(response->mStatusCode, 200u);
+
+ ssize_t i = response->mHeaders.indexOfKey("session");
+ CHECK_GE(i, 0);
+
+ if (index == 1) {
+ mSessionID = response->mHeaders.valueAt(i);
+ i = mSessionID.find(";");
+ if (i >= 0) {
+ // Remove options, i.e. ";timeout=90"
+ mSessionID.erase(i, mSessionID.size() - i);
+ }
+ }
+
+ sp<AMessage> notify = new AMessage('accu', id());
+ notify->setSize("track-index", trackIndex);
+
+ mRTPConn->addStream(
+ track->mRTPSocket, track->mRTCPSocket,
+ mSessionDesc, index,
+ notify);
+
+ track->mPacketSource =
+ new APacketSource(mSessionDesc, index);
+
+ mSetupTracksSuccessful = true;
+
+ ++index;
+ if (index < mSessionDesc->countTracks()) {
+ setupTrack(index);
+ break;
+ }
+ } else {
+ close(track->mRTPSocket);
+ close(track->mRTCPSocket);
+
+ mTracks.removeItemsAt(mTracks.size() - 1);
+ }
+
+ if (mSetupTracksSuccessful) {
+ AString request = "PLAY ";
+ request.append(mSessionURL);
+ request.append(" RTSP/1.0\r\n");
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('play', id());
+ mConn->sendRequest(request.c_str(), reply);
+ } else {
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ }
+ break;
+ }
+
+ case 'play':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "PLAY completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ if (result == OK) {
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ CHECK_EQ(response->mStatusCode, 200u);
+
+ sp<AMessage> msg = new AMessage('abor', id());
+ msg->post(60000000ll);
+ } else {
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ }
+
+ break;
+ }
+
+ case 'abor':
+ {
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ mTracks.editItemAt(i).mPacketSource->signalEOS(
+ ERROR_END_OF_STREAM);
+ }
+
+ sp<AMessage> reply = new AMessage('tear', id());
+
+ AString request;
+ request = "TEARDOWN ";
+
+ // XXX should use aggregate url from SDP here...
+ request.append(mSessionURL);
+ request.append(" RTSP/1.0\r\n");
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+
+ request.append("\r\n");
+
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'tear':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "TEARDOWN completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ sp<AMessage> reply = new AMessage('disc', id());
+ mConn->disconnect(reply);
+ break;
+ }
+
+ case 'quit':
+ {
+ break;
+ }
+
+ case 'accu':
+ {
+ size_t trackIndex;
+ CHECK(msg->findSize("track-index", &trackIndex));
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("access-unit", &obj));
+
+ sp<ABuffer> accessUnit = static_cast<ABuffer *>(obj.get());
+
+ uint64_t ntpTime;
+ CHECK(accessUnit->meta()->findInt64(
+ "ntp-time", (int64_t *)&ntpTime));
+
+ if (mFirstAccessUnit) {
+ mFirstAccessUnit = false;
+ mFirstAccessUnitNTP = ntpTime;
+ }
+ if (ntpTime > mFirstAccessUnitNTP) {
+ ntpTime -= mFirstAccessUnitNTP;
+ } else {
+ ntpTime = 0;
+ }
+
+ accessUnit->meta()->setInt64("ntp-time", ntpTime);
+
+#if 0
+ int32_t damaged;
+ if (accessUnit->meta()->findInt32("damaged", &damaged)
+ && damaged != 0) {
+ LOG(INFO) << "ignoring damaged AU";
+ } else
+#endif
+ {
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+ track->mPacketSource->queueAccessUnit(accessUnit);
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ break;
+ }
+ }
+
+ sp<APacketSource> getPacketSource(size_t index) {
+ CHECK_GE(index, 0u);
+ CHECK_LT(index, mTracks.size());
+
+ return mTracks.editItemAt(index).mPacketSource;
+ }
+
+ size_t countTracks() const {
+ return mTracks.size();
+ }
+
+private:
+ sp<ALooper> mLooper;
+ sp<ALooper> mNetLooper;
+ sp<ARTSPConnection> mConn;
+ sp<ARTPConnection> mRTPConn;
+ sp<ASessionDescription> mSessionDesc;
+ AString mSessionURL;
+ AString mBaseURL;
+ AString mSessionID;
+ bool mSetupTracksSuccessful;
+ bool mFirstAccessUnit;
+ uint64_t mFirstAccessUnitNTP;
+
+ struct TrackInfo {
+ int mRTPSocket;
+ int mRTCPSocket;
+
+ sp<APacketSource> mPacketSource;
+ };
+ Vector<TrackInfo> mTracks;
+
+ void setupTrack(size_t index) {
+ AString url;
+ CHECK(mSessionDesc->findAttribute(index, "a=control", &url));
+
+ AString trackURL;
+ CHECK(MakeURL(mBaseURL.c_str(), url.c_str(), &trackURL));
+
+ mTracks.push(TrackInfo());
+ TrackInfo *info = &mTracks.editItemAt(mTracks.size() - 1);
+
+ unsigned rtpPort;
+ ARTPConnection::MakePortPair(
+ &info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
+
+ AString request = "SETUP ";
+ request.append(trackURL);
+ request.append(" RTSP/1.0\r\n");
+
+ request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
+ request.append(rtpPort);
+ request.append("-");
+ request.append(rtpPort + 1);
+ request.append("\r\n");
+
+ if (index > 1) {
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+ }
+
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('setu', id());
+ reply->setSize("index", index);
+ reply->setSize("track-index", mTracks.size() - 1);
+ mConn->sendRequest(request.c_str(), reply);
+ }
+
+ static bool MakeURL(const char *baseURL, const char *url, AString *out) {
+ out->clear();
+
+ if (strncasecmp("rtsp://", baseURL, 7)) {
+ // Base URL must be absolute
+ return false;
+ }
+
+ if (!strncasecmp("rtsp://", url, 7)) {
+ // "url" is already an absolute URL, ignore base URL.
+ out->setTo(url);
+ return true;
+ }
+
+ size_t n = strlen(baseURL);
+ if (baseURL[n - 1] == '/') {
+ out->setTo(baseURL);
+ out->append(url);
+ } else {
+ char *slashPos = strrchr(baseURL, '/');
+
+ if (slashPos > &baseURL[6]) {
+ out->setTo(baseURL, slashPos - baseURL);
+ } else {
+ out->setTo(baseURL);
+ }
+
+ out->append("/");
+ out->append(url);
+ }
+
+ return true;
+ }
+
+ DISALLOW_EVIL_CONSTRUCTORS(MyHandler);
+};
+
+} // namespace android
+
+#endif // MY_HANDLER_H_
diff --git a/media/libstagefright/rtsp/MyTransmitter.h b/media/libstagefright/rtsp/MyTransmitter.h
new file mode 100644
index 0000000..009a3b1
--- /dev/null
+++ b/media/libstagefright/rtsp/MyTransmitter.h
@@ -0,0 +1,981 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MY_TRANSMITTER_H_
+
+#define MY_TRANSMITTER_H_
+
+#include "ARTPConnection.h"
+
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+#include <openssl/md5.h>
+
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/base64.h>
+#include <media/stagefright/foundation/hexdump.h>
+
+#ifdef ANDROID
+#include "VideoSource.h"
+
+#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
+#endif
+
+namespace android {
+
+#define TRACK_SUFFIX "trackid=1"
+#define PT 96
+#define PT_STR "96"
+
+#define USERNAME "bcast"
+#define PASSWORD "test"
+
+static int uniformRand(int limit) {
+ return ((double)rand() * limit) / RAND_MAX;
+}
+
+static bool GetAttribute(const char *s, const char *key, AString *value) {
+ value->clear();
+
+ size_t keyLen = strlen(key);
+
+ for (;;) {
+ const char *colonPos = strchr(s, ';');
+
+ size_t len =
+ (colonPos == NULL) ? strlen(s) : colonPos - s;
+
+ if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
+ value->setTo(&s[keyLen + 1], len - keyLen - 1);
+ return true;
+ }
+
+ if (colonPos == NULL) {
+ return false;
+ }
+
+ s = colonPos + 1;
+ }
+}
+
+struct MyTransmitter : public AHandler {
+ MyTransmitter(const char *url, const sp<ALooper> &looper)
+ : mServerURL(url),
+ mLooper(looper),
+ mConn(new ARTSPConnection),
+ mConnected(false),
+ mAuthType(NONE),
+ mRTPSocket(-1),
+ mRTCPSocket(-1),
+ mSourceID(rand()),
+ mSeqNo(uniformRand(65536)),
+ mRTPTimeBase(rand()),
+ mNumSamplesSent(0),
+ mNumRTPSent(0),
+ mNumRTPOctetsSent(0),
+ mLastRTPTime(0),
+ mLastNTPTime(0) {
+ mStreamURL = mServerURL;
+ mStreamURL.append("/bazong.sdp");
+
+ mTrackURL = mStreamURL;
+ mTrackURL.append("/");
+ mTrackURL.append(TRACK_SUFFIX);
+
+ mLooper->registerHandler(this);
+ mLooper->registerHandler(mConn);
+
+ sp<AMessage> reply = new AMessage('conn', id());
+ mConn->connect(mServerURL.c_str(), reply);
+
+#ifdef ANDROID
+ int width = 640;
+ int height = 480;
+
+ sp<MediaSource> source = new VideoSource(width, height);
+
+ sp<MetaData> encMeta = new MetaData;
+ encMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
+ encMeta->setInt32(kKeyWidth, width);
+ encMeta->setInt32(kKeyHeight, height);
+
+ OMXClient client;
+ client.connect();
+
+ mEncoder = OMXCodec::Create(
+ client.interface(), encMeta,
+ true /* createEncoder */, source);
+
+ mEncoder->start();
+
+ MediaBuffer *buffer;
+ CHECK_EQ(mEncoder->read(&buffer), (status_t)OK);
+ CHECK(buffer != NULL);
+
+ makeH264SPropParamSets(buffer);
+
+ buffer->release();
+ buffer = NULL;
+#endif
+ }
+
+ uint64_t ntpTime() {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ uint64_t nowUs = tv.tv_sec * 1000000ll + tv.tv_usec;
+
+ nowUs += ((70ll * 365 + 17) * 24) * 60 * 60 * 1000000ll;
+
+ uint64_t hi = nowUs / 1000000ll;
+ uint64_t lo = ((1ll << 32) * (nowUs % 1000000ll)) / 1000000ll;
+
+ return (hi << 32) | lo;
+ }
+
+ void issueAnnounce() {
+ AString sdp;
+ sdp = "v=0\r\n";
+
+ sdp.append("o=- ");
+
+ uint64_t ntp = ntpTime();
+ sdp.append(ntp);
+ sdp.append(" ");
+ sdp.append(ntp);
+ sdp.append(" IN IP4 127.0.0.0\r\n");
+
+ sdp.append(
+ "s=Sample\r\n"
+ "i=Playing around with ANNOUNCE\r\n"
+ "c=IN IP4 ");
+
+ struct in_addr addr;
+ addr.s_addr = htonl(mServerIP);
+
+ sdp.append(inet_ntoa(addr));
+
+ sdp.append(
+ "\r\n"
+ "t=0 0\r\n"
+ "a=range:npt=now-\r\n");
+
+#ifdef ANDROID
+ sp<MetaData> meta = mEncoder->getFormat();
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ sdp.append(
+ "m=video 0 RTP/AVP " PT_STR "\r\n"
+ "b=AS 320000\r\n"
+ "a=rtpmap:" PT_STR " H264/90000\r\n");
+
+ sdp.append("a=cliprect 0,0,");
+ sdp.append(height);
+ sdp.append(",");
+ sdp.append(width);
+ sdp.append("\r\n");
+
+ sdp.append(
+ "a=framesize:" PT_STR " ");
+ sdp.append(width);
+ sdp.append("-");
+ sdp.append(height);
+ sdp.append("\r\n");
+
+ sdp.append(
+ "a=fmtp:" PT_STR " profile-level-id=42C015;sprop-parameter-sets=");
+
+ sdp.append(mSeqParamSet);
+ sdp.append(",");
+ sdp.append(mPicParamSet);
+ sdp.append(";packetization-mode=1\r\n");
+#else
+ sdp.append(
+ "m=audio 0 RTP/AVP " PT_STR "\r\n"
+ "a=rtpmap:" PT_STR " L8/8000/1\r\n");
+#endif
+
+ sdp.append("a=control:" TRACK_SUFFIX "\r\n");
+
+ AString request;
+ request.append("ANNOUNCE ");
+ request.append(mStreamURL);
+ request.append(" RTSP/1.0\r\n");
+
+ addAuthentication(&request, "ANNOUNCE", mStreamURL.c_str());
+
+ request.append("Content-Type: application/sdp\r\n");
+ request.append("Content-Length: ");
+ request.append(sdp.size());
+ request.append("\r\n");
+
+ request.append("\r\n");
+ request.append(sdp);
+
+ sp<AMessage> reply = new AMessage('anno', id());
+ mConn->sendRequest(request.c_str(), reply);
+ }
+
+ void H(const AString &s, AString *out) {
+ out->clear();
+
+ MD5_CTX m;
+ MD5_Init(&m);
+ MD5_Update(&m, s.c_str(), s.size());
+
+ uint8_t key[16];
+ MD5_Final(key, &m);
+
+ for (size_t i = 0; i < 16; ++i) {
+ char nibble = key[i] >> 4;
+ if (nibble <= 9) {
+ nibble += '0';
+ } else {
+ nibble += 'a' - 10;
+ }
+ out->append(&nibble, 1);
+
+ nibble = key[i] & 0x0f;
+ if (nibble <= 9) {
+ nibble += '0';
+ } else {
+ nibble += 'a' - 10;
+ }
+ out->append(&nibble, 1);
+ }
+ }
+
+ void authenticate(const sp<ARTSPResponse> &response) {
+ ssize_t i = response->mHeaders.indexOfKey("www-authenticate");
+ CHECK_GE(i, 0);
+
+ AString value = response->mHeaders.valueAt(i);
+
+ if (!strncmp(value.c_str(), "Basic", 5)) {
+ mAuthType = BASIC;
+ } else {
+ CHECK(!strncmp(value.c_str(), "Digest", 6));
+ mAuthType = DIGEST;
+
+ i = value.find("nonce=");
+ CHECK_GE(i, 0);
+ CHECK_EQ(value.c_str()[i + 6], '\"');
+ ssize_t j = value.find("\"", i + 7);
+ CHECK_GE(j, 0);
+
+ mNonce.setTo(value, i + 7, j - i - 7);
+ }
+
+ issueAnnounce();
+ }
+
+ void addAuthentication(
+ AString *request, const char *method, const char *url) {
+ if (mAuthType == NONE) {
+ return;
+ }
+
+ if (mAuthType == BASIC) {
+ request->append("Authorization: Basic YmNhc3Q6dGVzdAo=\r\n");
+ return;
+ }
+
+ CHECK_EQ((int)mAuthType, (int)DIGEST);
+
+ AString A1;
+ A1.append(USERNAME);
+ A1.append(":");
+ A1.append("Streaming Server");
+ A1.append(":");
+ A1.append(PASSWORD);
+
+ AString A2;
+ A2.append(method);
+ A2.append(":");
+ A2.append(url);
+
+ AString HA1, HA2;
+ H(A1, &HA1);
+ H(A2, &HA2);
+
+ AString tmp;
+ tmp.append(HA1);
+ tmp.append(":");
+ tmp.append(mNonce);
+ tmp.append(":");
+ tmp.append(HA2);
+
+ AString digest;
+ H(tmp, &digest);
+
+ request->append("Authorization: Digest ");
+ request->append("nonce=\"");
+ request->append(mNonce);
+ request->append("\", ");
+ request->append("username=\"" USERNAME "\", ");
+ request->append("uri=\"");
+ request->append(url);
+ request->append("\", ");
+ request->append("response=\"");
+ request->append(digest);
+ request->append("\"");
+ request->append("\r\n");
+ }
+
+ virtual void onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case 'conn':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "connection request completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ if (result != OK) {
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ mConnected = true;
+
+ CHECK(msg->findInt32("server-ip", (int32_t *)&mServerIP));
+
+ issueAnnounce();
+ break;
+ }
+
+ case 'anno':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "ANNOUNCE completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response;
+
+ if (result == OK) {
+ response = static_cast<ARTSPResponse *>(obj.get());
+ CHECK(response != NULL);
+
+ if (response->mStatusCode == 401) {
+ if (mAuthType != NONE) {
+ LOG(INFO) << "FAILED to authenticate";
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ authenticate(response);
+ break;
+ }
+ }
+
+ if (result != OK || response->mStatusCode != 200) {
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ unsigned rtpPort;
+ ARTPConnection::MakePortPair(&mRTPSocket, &mRTCPSocket, &rtpPort);
+
+ // (new AMessage('poll', id()))->post();
+
+ AString request;
+ request.append("SETUP ");
+ request.append(mTrackURL);
+ request.append(" RTSP/1.0\r\n");
+
+ addAuthentication(&request, "SETUP", mTrackURL.c_str());
+
+ request.append("Transport: RTP/AVP;unicast;client_port=");
+ request.append(rtpPort);
+ request.append("-");
+ request.append(rtpPort + 1);
+ request.append(";mode=record\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('setu', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+#if 0
+ case 'poll':
+ {
+ fd_set rs;
+ FD_ZERO(&rs);
+ FD_SET(mRTCPSocket, &rs);
+
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ int res = select(mRTCPSocket + 1, &rs, NULL, NULL, &tv);
+
+ if (res == 1) {
+ sp<ABuffer> buffer = new ABuffer(65536);
+ ssize_t n = recv(mRTCPSocket, buffer->data(), buffer->size(), 0);
+
+ if (n <= 0) {
+ LOG(ERROR) << "recv returned " << n;
+ } else {
+ LOG(INFO) << "recv returned " << n << " bytes of data.";
+
+ hexdump(buffer->data(), n);
+ }
+ }
+
+ msg->post(50000);
+ break;
+ }
+#endif
+
+ case 'setu':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "SETUP completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response;
+
+ if (result == OK) {
+ response = static_cast<ARTSPResponse *>(obj.get());
+ CHECK(response != NULL);
+ }
+
+ if (result != OK || response->mStatusCode != 200) {
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ ssize_t i = response->mHeaders.indexOfKey("session");
+ CHECK_GE(i, 0);
+ mSessionID = response->mHeaders.valueAt(i);
+ i = mSessionID.find(";");
+ if (i >= 0) {
+ // Remove options, i.e. ";timeout=90"
+ mSessionID.erase(i, mSessionID.size() - i);
+ }
+
+ i = response->mHeaders.indexOfKey("transport");
+ CHECK_GE(i, 0);
+ AString transport = response->mHeaders.valueAt(i);
+
+ LOG(INFO) << "transport = '" << transport << "'";
+
+ AString value;
+ CHECK(GetAttribute(transport.c_str(), "server_port", &value));
+
+ unsigned rtpPort, rtcpPort;
+ CHECK_EQ(sscanf(value.c_str(), "%u-%u", &rtpPort, &rtcpPort), 2);
+
+ CHECK(GetAttribute(transport.c_str(), "source", &value));
+
+ memset(mRemoteAddr.sin_zero, 0, sizeof(mRemoteAddr.sin_zero));
+ mRemoteAddr.sin_family = AF_INET;
+ mRemoteAddr.sin_addr.s_addr = inet_addr(value.c_str());
+ mRemoteAddr.sin_port = htons(rtpPort);
+
+ mRemoteRTCPAddr = mRemoteAddr;
+ mRemoteRTCPAddr.sin_port = htons(rtpPort + 1);
+
+ CHECK_EQ(0, connect(mRTPSocket,
+ (const struct sockaddr *)&mRemoteAddr,
+ sizeof(mRemoteAddr)));
+
+ CHECK_EQ(0, connect(mRTCPSocket,
+ (const struct sockaddr *)&mRemoteRTCPAddr,
+ sizeof(mRemoteRTCPAddr)));
+
+ uint32_t x = ntohl(mRemoteAddr.sin_addr.s_addr);
+ LOG(INFO) << "sending data to "
+ << (x >> 24)
+ << "."
+ << ((x >> 16) & 0xff)
+ << "."
+ << ((x >> 8) & 0xff)
+ << "."
+ << (x & 0xff)
+ << ":"
+ << rtpPort;
+
+ AString request;
+ request.append("RECORD ");
+ request.append(mStreamURL);
+ request.append(" RTSP/1.0\r\n");
+
+ addAuthentication(&request, "RECORD", mStreamURL.c_str());
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('reco', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'reco':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "RECORD completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response;
+
+ if (result == OK) {
+ response = static_cast<ARTSPResponse *>(obj.get());
+ CHECK(response != NULL);
+ }
+
+ if (result != OK) {
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ (new AMessage('more', id()))->post();
+ (new AMessage('sr ', id()))->post();
+ (new AMessage('aliv', id()))->post(30000000ll);
+ break;
+ }
+
+ case 'aliv':
+ {
+ if (!mConnected) {
+ break;
+ }
+
+ AString request;
+ request.append("OPTIONS ");
+ request.append(mStreamURL);
+ request.append(" RTSP/1.0\r\n");
+
+ addAuthentication(&request, "RECORD", mStreamURL.c_str());
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('opts', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'opts':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "OPTIONS completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ if (!mConnected) {
+ break;
+ }
+
+ (new AMessage('aliv', id()))->post(30000000ll);
+ break;
+ }
+
+ case 'more':
+ {
+ if (!mConnected) {
+ break;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(65536);
+ uint8_t *data = buffer->data();
+ data[0] = 0x80;
+ data[1] = (1 << 7) | PT; // M-bit
+ data[2] = (mSeqNo >> 8) & 0xff;
+ data[3] = mSeqNo & 0xff;
+ data[8] = mSourceID >> 24;
+ data[9] = (mSourceID >> 16) & 0xff;
+ data[10] = (mSourceID >> 8) & 0xff;
+ data[11] = mSourceID & 0xff;
+
+#ifdef ANDROID
+ MediaBuffer *mediaBuf = NULL;
+ for (;;) {
+ CHECK_EQ(mEncoder->read(&mediaBuf), (status_t)OK);
+ if (mediaBuf->range_length() > 0) {
+ break;
+ }
+ mediaBuf->release();
+ mediaBuf = NULL;
+ }
+
+ int64_t timeUs;
+ CHECK(mediaBuf->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ uint32_t rtpTime = mRTPTimeBase + (timeUs * 9 / 100ll);
+
+ const uint8_t *mediaData =
+ (const uint8_t *)mediaBuf->data() + mediaBuf->range_offset();
+
+ CHECK(!memcmp("\x00\x00\x00\x01", mediaData, 4));
+
+ CHECK_LE(mediaBuf->range_length() - 4 + 12, buffer->size());
+
+ memcpy(&data[12],
+ mediaData + 4, mediaBuf->range_length() - 4);
+
+ buffer->setRange(0, mediaBuf->range_length() - 4 + 12);
+
+ mediaBuf->release();
+ mediaBuf = NULL;
+#else
+ uint32_t rtpTime = mRTPTimeBase + mNumRTPSent * 128;
+ memset(&data[12], 0, 128);
+ buffer->setRange(0, 12 + 128);
+#endif
+
+ data[4] = rtpTime >> 24;
+ data[5] = (rtpTime >> 16) & 0xff;
+ data[6] = (rtpTime >> 8) & 0xff;
+ data[7] = rtpTime & 0xff;
+
+ ssize_t n = send(
+ mRTPSocket, data, buffer->size(), 0);
+ if (n < 0) {
+ LOG(ERROR) << "send failed (" << strerror(errno) << ")";
+ }
+ CHECK_EQ(n, (ssize_t)buffer->size());
+
+ ++mSeqNo;
+
+ ++mNumRTPSent;
+ mNumRTPOctetsSent += buffer->size() - 12;
+
+ mLastRTPTime = rtpTime;
+ mLastNTPTime = ntpTime();
+
+#ifdef ANDROID
+ if (mNumRTPSent < 60 * 25) { // 60 secs worth
+ msg->post(40000);
+#else
+ if (mNumRTPOctetsSent < 8000 * 60) {
+ msg->post(1000000ll * 128 / 8000);
+#endif
+ } else {
+ LOG(INFO) << "That's enough, pausing.";
+
+ AString request;
+ request.append("PAUSE ");
+ request.append(mStreamURL);
+ request.append(" RTSP/1.0\r\n");
+
+ addAuthentication(&request, "PAUSE", mStreamURL.c_str());
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('paus', id());
+ mConn->sendRequest(request.c_str(), reply);
+ }
+ break;
+ }
+
+ case 'sr ':
+ {
+ if (!mConnected) {
+ break;
+ }
+
+ sp<ABuffer> buffer = new ABuffer(65536);
+ buffer->setRange(0, 0);
+
+ addSR(buffer);
+ addSDES(buffer);
+
+ uint8_t *data = buffer->data();
+ ssize_t n = send(
+ mRTCPSocket, data, buffer->size(), 0);
+ CHECK_EQ(n, (ssize_t)buffer->size());
+
+ msg->post(3000000);
+ break;
+ }
+
+ case 'paus':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "PAUSE completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response;
+
+ AString request;
+ request.append("TEARDOWN ");
+ request.append(mStreamURL);
+ request.append(" RTSP/1.0\r\n");
+
+ addAuthentication(&request, "TEARDOWN", mStreamURL.c_str());
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('tear', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'tear':
+ {
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+
+ LOG(INFO) << "TEARDOWN completed with result "
+ << result << " (" << strerror(-result) << ")";
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response;
+
+ if (result == OK) {
+ response = static_cast<ARTSPResponse *>(obj.get());
+ CHECK(response != NULL);
+ }
+
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ case 'disc':
+ {
+ LOG(INFO) << "disconnect completed";
+
+ mConnected = false;
+ (new AMessage('quit', id()))->post();
+ break;
+ }
+
+ case 'quit':
+ {
+ if (mConnected) {
+ mConn->disconnect(new AMessage('disc', id()));
+ break;
+ }
+
+ if (mRTPSocket >= 0) {
+ close(mRTPSocket);
+ mRTPSocket = -1;
+ }
+
+ if (mRTCPSocket >= 0) {
+ close(mRTCPSocket);
+ mRTCPSocket = -1;
+ }
+
+#ifdef ANDROID
+ mEncoder->stop();
+ mEncoder.clear();
+#endif
+
+ mLooper->stop();
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+ }
+
+protected:
+ virtual ~MyTransmitter() {
+ }
+
+private:
+ enum AuthType {
+ NONE,
+ BASIC,
+ DIGEST
+ };
+
+ AString mServerURL;
+ AString mTrackURL;
+ AString mStreamURL;
+
+ sp<ALooper> mLooper;
+ sp<ARTSPConnection> mConn;
+ bool mConnected;
+ uint32_t mServerIP;
+ AuthType mAuthType;
+ AString mNonce;
+ AString mSessionID;
+ int mRTPSocket, mRTCPSocket;
+ uint32_t mSourceID;
+ uint32_t mSeqNo;
+ uint32_t mRTPTimeBase;
+ struct sockaddr_in mRemoteAddr;
+ struct sockaddr_in mRemoteRTCPAddr;
+ size_t mNumSamplesSent;
+ uint32_t mNumRTPSent;
+ uint32_t mNumRTPOctetsSent;
+ uint32_t mLastRTPTime;
+ uint64_t mLastNTPTime;
+
+#ifdef ANDROID
+ sp<MediaSource> mEncoder;
+ AString mSeqParamSet;
+ AString mPicParamSet;
+
+ void makeH264SPropParamSets(MediaBuffer *buffer) {
+ static const char kStartCode[] = "\x00\x00\x00\x01";
+
+ const uint8_t *data =
+ (const uint8_t *)buffer->data() + buffer->range_offset();
+ size_t size = buffer->range_length();
+
+ CHECK_GE(size, 0u);
+ CHECK(!memcmp(kStartCode, data, 4));
+
+ data += 4;
+ size -= 4;
+
+ size_t startCodePos = 0;
+ while (startCodePos + 3 < size
+ && memcmp(kStartCode, &data[startCodePos], 4)) {
+ ++startCodePos;
+ }
+
+ CHECK_LT(startCodePos + 3, size);
+
+ encodeBase64(data, startCodePos, &mSeqParamSet);
+
+ encodeBase64(&data[startCodePos + 4], size - startCodePos - 4,
+ &mPicParamSet);
+ }
+#endif
+
+ void addSR(const sp<ABuffer> &buffer) {
+ uint8_t *data = buffer->data() + buffer->size();
+
+ data[0] = 0x80 | 0;
+ data[1] = 200; // SR
+ data[2] = 0;
+ data[3] = 6;
+ data[4] = mSourceID >> 24;
+ data[5] = (mSourceID >> 16) & 0xff;
+ data[6] = (mSourceID >> 8) & 0xff;
+ data[7] = mSourceID & 0xff;
+
+ data[8] = mLastNTPTime >> (64 - 8);
+ data[9] = (mLastNTPTime >> (64 - 16)) & 0xff;
+ data[10] = (mLastNTPTime >> (64 - 24)) & 0xff;
+ data[11] = (mLastNTPTime >> 32) & 0xff;
+ data[12] = (mLastNTPTime >> 24) & 0xff;
+ data[13] = (mLastNTPTime >> 16) & 0xff;
+ data[14] = (mLastNTPTime >> 8) & 0xff;
+ data[15] = mLastNTPTime & 0xff;
+
+ data[16] = (mLastRTPTime >> 24) & 0xff;
+ data[17] = (mLastRTPTime >> 16) & 0xff;
+ data[18] = (mLastRTPTime >> 8) & 0xff;
+ data[19] = mLastRTPTime & 0xff;
+
+ data[20] = mNumRTPSent >> 24;
+ data[21] = (mNumRTPSent >> 16) & 0xff;
+ data[22] = (mNumRTPSent >> 8) & 0xff;
+ data[23] = mNumRTPSent & 0xff;
+
+ data[24] = mNumRTPOctetsSent >> 24;
+ data[25] = (mNumRTPOctetsSent >> 16) & 0xff;
+ data[26] = (mNumRTPOctetsSent >> 8) & 0xff;
+ data[27] = mNumRTPOctetsSent & 0xff;
+
+ buffer->setRange(buffer->offset(), buffer->size() + 28);
+ }
+
+ void addSDES(const sp<ABuffer> &buffer) {
+ uint8_t *data = buffer->data() + buffer->size();
+ data[0] = 0x80 | 1;
+ data[1] = 202; // SDES
+ data[4] = mSourceID >> 24;
+ data[5] = (mSourceID >> 16) & 0xff;
+ data[6] = (mSourceID >> 8) & 0xff;
+ data[7] = mSourceID & 0xff;
+
+ size_t offset = 8;
+
+ data[offset++] = 1; // CNAME
+
+ static const char *kCNAME = "andih@laptop";
+ data[offset++] = strlen(kCNAME);
+
+ memcpy(&data[offset], kCNAME, strlen(kCNAME));
+ offset += strlen(kCNAME);
+
+ data[offset++] = 7; // NOTE
+
+ static const char *kNOTE = "Hell's frozen over.";
+ data[offset++] = strlen(kNOTE);
+
+ memcpy(&data[offset], kNOTE, strlen(kNOTE));
+ offset += strlen(kNOTE);
+
+ data[offset++] = 0;
+
+ if ((offset % 4) > 0) {
+ size_t count = 4 - (offset % 4);
+ switch (count) {
+ case 3:
+ data[offset++] = 0;
+ case 2:
+ data[offset++] = 0;
+ case 1:
+ data[offset++] = 0;
+ }
+ }
+
+ size_t numWords = (offset / 4) - 1;
+ data[2] = numWords >> 8;
+ data[3] = numWords & 0xff;
+
+ buffer->setRange(buffer->offset(), buffer->size() + offset);
+ }
+
+ DISALLOW_EVIL_CONSTRUCTORS(MyTransmitter);
+};
+
+} // namespace android
+
+#endif // MY_TRANSMITTER_H_
diff --git a/media/libstagefright/rtsp/VideoSource.h b/media/libstagefright/rtsp/VideoSource.h
new file mode 100644
index 0000000..ae0c85b
--- /dev/null
+++ b/media/libstagefright/rtsp/VideoSource.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef VIDEO_SOURCE_H_
+
+#define VIDEO_SOURCE_H_
+
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+class VideoSource : public MediaSource {
+ static const int32_t kFramerate = 24; // fps
+
+public:
+ VideoSource(int width, int height)
+ : mWidth(width),
+ mHeight(height),
+ mSize((width * height * 3) / 2) {
+ mGroup.add_buffer(new MediaBuffer(mSize));
+ }
+
+ virtual sp<MetaData> getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyWidth, mWidth);
+ meta->setInt32(kKeyHeight, mHeight);
+ meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
+
+ return meta;
+ }
+
+ virtual status_t start(MetaData *params) {
+ mNumFramesOutput = 0;
+ return OK;
+ }
+
+ virtual status_t stop() {
+ return OK;
+ }
+
+ virtual status_t read(
+ MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
+ if (mNumFramesOutput == kFramerate * 100) {
+ // Stop returning data after 10 secs.
+ return ERROR_END_OF_STREAM;
+ }
+
+ // printf("VideoSource::read\n");
+ status_t err = mGroup.acquire_buffer(buffer);
+ if (err != OK) {
+ return err;
+ }
+
+ char x = (char)((double)rand() / RAND_MAX * 255);
+ memset((*buffer)->data(), x, mSize);
+ (*buffer)->set_range(0, mSize);
+ (*buffer)->meta_data()->clear();
+ (*buffer)->meta_data()->setInt64(
+ kKeyTime, (mNumFramesOutput * 1000000) / kFramerate);
+ ++mNumFramesOutput;
+
+ // printf("VideoSource::read - returning buffer\n");
+ // LOG(INFO)("VideoSource::read - returning buffer");
+ return OK;
+ }
+
+protected:
+ virtual ~VideoSource() {}
+
+private:
+ MediaBufferGroup mGroup;
+ int mWidth, mHeight;
+ size_t mSize;
+ int64_t mNumFramesOutput;;
+
+ VideoSource(const VideoSource &);
+ VideoSource &operator=(const VideoSource &);
+};
+
+} // namespace android
+
+#endif // VIDEO_SOURCE_H_